blob: 5a257627efb02a681af6dc36367eee998a7756db [file] [log] [blame]
Gaurav Agrawalbd804472016-03-25 11:25:36 +05301/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Gaurav Agrawalbd804472016-03-25 11:25:36 +05303 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.yangutils.parser.impl.listeners;
18
19/*
20 * Reference: RFC6020 and YANG ANTLR Grammar
21 *
22 * ABNF grammar as per RFC6020
23 * type-body-stmts = numerical-restrictions /
24 * decimal64-specification /
25 * string-restrictions /
26 * enum-specification /
27 * leafref-specification /
28 * identityref-specification /
29 * instance-identifier-specification /
30 * bits-specification /
31 * union-specification
32 *
33 * union-specification = 1*(type-stmt stmtsep)
34 *
35 * ANTLR grammar rule
36 * typeBodyStatements : numericalRestrictions | stringRestrictions | enumSpecification
37 * | leafrefSpecification | identityrefSpecification | instanceIdentifierSpecification
38 * | bitsSpecification | unionSpecification;
39 *
40 * unionSpecification : typeStatement+;
41 */
42
43import org.onosproject.yangutils.datamodel.YangLeaf;
44import org.onosproject.yangutils.datamodel.YangLeafList;
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +053045import org.onosproject.yangutils.datamodel.YangNode;
Gaurav Agrawalbd804472016-03-25 11:25:36 +053046import org.onosproject.yangutils.datamodel.YangType;
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +053047import org.onosproject.yangutils.datamodel.YangTypeDef;
Gaurav Agrawalbd804472016-03-25 11:25:36 +053048import org.onosproject.yangutils.datamodel.YangUnion;
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +053049import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
Gaurav Agrawalbd804472016-03-25 11:25:36 +053050import org.onosproject.yangutils.parser.Parsable;
51import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser;
52import org.onosproject.yangutils.parser.exceptions.ParserException;
53import org.onosproject.yangutils.parser.impl.TreeWalkListener;
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +053054import org.onosproject.yangutils.utils.YangConstructType;
Gaurav Agrawalbd804472016-03-25 11:25:36 +053055
Gaurav Agrawal338735b2016-04-18 18:53:11 +053056import static org.onosproject.yangutils.datamodel.utils.GeneratedLanguage.JAVA_GENERATION;
57import static org.onosproject.yangutils.datamodel.utils.YangDataModelFactory.getYangUnionNode;
Gaurav Agrawalbd804472016-03-25 11:25:36 +053058import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.ENTRY;
59import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.EXIT;
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +053060import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction.constructExtendedListenerErrorMessage;
Gaurav Agrawalbd804472016-03-25 11:25:36 +053061import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction.constructListenerErrorMessage;
62import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.INVALID_HOLDER;
63import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.MISSING_CURRENT_HOLDER;
64import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.MISSING_HOLDER;
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +053065import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.UNHANDLED_PARSED_DATA;
Gaurav Agrawalbd804472016-03-25 11:25:36 +053066import static org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation.checkStackIsNotEmpty;
67import static org.onosproject.yangutils.utils.YangConstructType.TYPE_DATA;
68import static org.onosproject.yangutils.utils.YangConstructType.UNION_DATA;
69
70/**
Bharat saraswald9822e92016-04-05 15:13:44 +053071 * Represents listener based call back function corresponding to the "union" rule
Gaurav Agrawalbd804472016-03-25 11:25:36 +053072 * defined in ANTLR grammar file for corresponding ABNF rule in RFC 6020.
73 */
74public final class UnionListener {
Bharat saraswald9822e92016-04-05 15:13:44 +053075
Gaurav Agrawalbd804472016-03-25 11:25:36 +053076 /**
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +053077 * Suffix to be used while creating union class.
78 */
79 private static final String UNION_CLASS_SUFFIX = "_union";
80
81 /**
Gaurav Agrawalbd804472016-03-25 11:25:36 +053082 * Creates a new union listener.
83 */
84 private UnionListener() {
85 }
86
87 /**
88 * It is called when parser enters grammar rule (union), it perform
89 * validations and updates the data model tree.
90 *
91 * @param listener listener's object
92 * @param ctx context object of the grammar rule
93 */
94 public static void processUnionEntry(TreeWalkListener listener,
95 GeneratedYangParser.UnionSpecificationContext ctx) {
96
97 // Check for stack to be non empty.
98 checkStackIsNotEmpty(listener, MISSING_HOLDER, UNION_DATA, "", ENTRY);
99
100 if (listener.getParsedDataStack().peek() instanceof YangType) {
Gaurav Agrawal338735b2016-04-18 18:53:11 +0530101 YangUnion unionNode = getYangUnionNode(JAVA_GENERATION);
Gaurav Agrawalbd804472016-03-25 11:25:36 +0530102 Parsable typeData = listener.getParsedDataStack().pop();
103
104 // Check for stack to be non empty.
105 checkStackIsNotEmpty(listener, MISSING_HOLDER, UNION_DATA, "", ENTRY);
106
107 Parsable tmpData = listener.getParsedDataStack().peek();
108
109 switch (tmpData.getYangConstructType()) {
110 case LEAF_DATA:
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +0530111 // Set the name of union same as leaf.
112 unionNode.setName(((YangLeaf) tmpData).getLeafName() + UNION_CLASS_SUFFIX);
113 // Pop the stack entry to obtain the parent YANG node.
114 Parsable leaf = listener.getParsedDataStack().pop();
115 // Add the union node to the parent holder of leaf.
116 addChildToParentNode(listener, unionNode);
117 // Push the popped entry back to the stack.
118 listener.getParsedDataStack().push(leaf);
Gaurav Agrawalbd804472016-03-25 11:25:36 +0530119 break;
120 case LEAF_LIST_DATA:
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +0530121 // Set the name of union same as leaf list.
122 unionNode.setName(((YangLeafList) tmpData).getLeafName() + UNION_CLASS_SUFFIX);
123 // Pop the stack entry to obtain the parent YANG node.
124 Parsable leafList = listener.getParsedDataStack().pop();
125 // Add the union node to the parent holder of leaf.
126 addChildToParentNode(listener, unionNode);
127 // Push the popped entry back to the stack.
128 listener.getParsedDataStack().push(leafList);
Gaurav Agrawalbd804472016-03-25 11:25:36 +0530129 break;
130 case UNION_DATA:
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +0530131 YangUnion parentUnion = (YangUnion) tmpData;
132 /*
133 * In case parent of union is again a union, name of the
134 * child union is parent union name suffixed with running
135 * integer number, this is done because under union there
136 * could be multiple child union types.
137 */
138 unionNode.setName(parentUnion.getName() + UNION_CLASS_SUFFIX + parentUnion.getChildUnionNumber());
139 // Increment the running number.
140 parentUnion.setChildUnionNumber(parentUnion.getChildUnionNumber() + 1);
141 // Add union as a child to parent union.
142 addChildToParentNode(listener, unionNode);
Gaurav Agrawalbd804472016-03-25 11:25:36 +0530143 break;
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +0530144 case TYPEDEF_DATA:
145 YangTypeDef typeDef = (YangTypeDef) tmpData;
146 // Set the name of union same as typedef name.
147 unionNode.setName(typeDef.getName() + UNION_CLASS_SUFFIX);
148 // Add union as a child to parent type def.
149 addChildToParentNode(listener, unionNode);
150 break;
151 // TODO deviate.
Gaurav Agrawalbd804472016-03-25 11:25:36 +0530152 default:
153 throw new ParserException(constructListenerErrorMessage(INVALID_HOLDER, TYPE_DATA,
154 ((YangType<?>) typeData).getDataTypeName(), ENTRY));
155 }
156 listener.getParsedDataStack().push(typeData);
157 listener.getParsedDataStack().push(unionNode);
158 } else {
159 throw new ParserException(constructListenerErrorMessage(INVALID_HOLDER, UNION_DATA, "", ENTRY));
160 }
161 }
162
163 /**
164 * It is called when parser exits from grammar rule (union), it perform
165 * validations and update the data model tree.
166 *
167 * @param listener Listener's object
168 * @param ctx context object of the grammar rule
169 */
170 public static void processUnionExit(TreeWalkListener listener,
171 GeneratedYangParser.UnionSpecificationContext ctx) {
172
173 // Check for stack to be non empty.
174 checkStackIsNotEmpty(listener, MISSING_HOLDER, UNION_DATA, "", EXIT);
175
176 Parsable tmpUnionNode = listener.getParsedDataStack().peek();
177 if (tmpUnionNode instanceof YangUnion) {
178 YangUnion unionNode = (YangUnion) tmpUnionNode;
179 listener.getParsedDataStack().pop();
180
181 // Check for stack to be non empty.
182 checkStackIsNotEmpty(listener, MISSING_HOLDER, UNION_DATA, "", EXIT);
183
184 Parsable tmpNode = listener.getParsedDataStack().peek();
185 switch (tmpNode.getYangConstructType()) {
186 case TYPE_DATA: {
187 YangType<YangUnion> typeNode = (YangType<YangUnion>) tmpNode;
188 typeNode.setDataTypeExtendedInfo(unionNode);
189 break;
190 }
191 default:
192 throw new ParserException(
193 constructListenerErrorMessage(INVALID_HOLDER, UNION_DATA, "", EXIT));
194 }
195 } else {
196 throw new ParserException(
197 constructListenerErrorMessage(MISSING_CURRENT_HOLDER, UNION_DATA, "", EXIT));
198 }
199 }
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +0530200
201 /**
202 * Adds the union node to the parent holder.
203 *
204 * @param listener listener's object
205 * @param unionNode union node which needs to be added to parent
206 */
207 private static void addChildToParentNode(TreeWalkListener listener, YangUnion unionNode) {
208 if (!(listener.getParsedDataStack().peek() instanceof YangNode)) {
209 throw new ParserException(constructListenerErrorMessage(INVALID_HOLDER, UNION_DATA,
210 "", ENTRY));
211 } else {
212 YangNode curNode = (YangNode) listener.getParsedDataStack().peek();
213 try {
214 curNode.addChild(unionNode);
215 } catch (DataModelException e) {
216 throw new ParserException(constructExtendedListenerErrorMessage(UNHANDLED_PARSED_DATA,
217 YangConstructType.UNION_DATA, "", ENTRY, e.getMessage()));
218 }
219 }
220 }
Gaurav Agrawalbd804472016-03-25 11:25:36 +0530221}