blob: 2a78eecd7717704a7aa92aa1bebeca221ee5682b [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;
54
Gaurav Agrawal338735b2016-04-18 18:53:11 +053055import static org.onosproject.yangutils.datamodel.utils.GeneratedLanguage.JAVA_GENERATION;
56import static org.onosproject.yangutils.datamodel.utils.YangDataModelFactory.getYangUnionNode;
Gaurav Agrawalbd804472016-03-25 11:25:36 +053057import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.ENTRY;
58import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.EXIT;
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +053059import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction.constructExtendedListenerErrorMessage;
Gaurav Agrawalbd804472016-03-25 11:25:36 +053060import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction.constructListenerErrorMessage;
61import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.INVALID_HOLDER;
62import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.MISSING_CURRENT_HOLDER;
63import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.MISSING_HOLDER;
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +053064import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.UNHANDLED_PARSED_DATA;
Gaurav Agrawalbd804472016-03-25 11:25:36 +053065import static org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation.checkStackIsNotEmpty;
66import static org.onosproject.yangutils.utils.YangConstructType.TYPE_DATA;
67import static org.onosproject.yangutils.utils.YangConstructType.UNION_DATA;
68
69/**
Bharat saraswald9822e92016-04-05 15:13:44 +053070 * Represents listener based call back function corresponding to the "union" rule
Gaurav Agrawalbd804472016-03-25 11:25:36 +053071 * defined in ANTLR grammar file for corresponding ABNF rule in RFC 6020.
72 */
73public final class UnionListener {
Bharat saraswald9822e92016-04-05 15:13:44 +053074
Gaurav Agrawalbd804472016-03-25 11:25:36 +053075 /**
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +053076 * Suffix to be used while creating union class.
77 */
78 private static final String UNION_CLASS_SUFFIX = "_union";
79
80 /**
Gaurav Agrawalbd804472016-03-25 11:25:36 +053081 * Creates a new union listener.
82 */
83 private UnionListener() {
84 }
85
86 /**
87 * It is called when parser enters grammar rule (union), it perform
88 * validations and updates the data model tree.
89 *
90 * @param listener listener's object
91 * @param ctx context object of the grammar rule
92 */
93 public static void processUnionEntry(TreeWalkListener listener,
94 GeneratedYangParser.UnionSpecificationContext ctx) {
95
96 // Check for stack to be non empty.
97 checkStackIsNotEmpty(listener, MISSING_HOLDER, UNION_DATA, "", ENTRY);
98
99 if (listener.getParsedDataStack().peek() instanceof YangType) {
Gaurav Agrawal338735b2016-04-18 18:53:11 +0530100 YangUnion unionNode = getYangUnionNode(JAVA_GENERATION);
Gaurav Agrawalbd804472016-03-25 11:25:36 +0530101 Parsable typeData = listener.getParsedDataStack().pop();
102
103 // Check for stack to be non empty.
104 checkStackIsNotEmpty(listener, MISSING_HOLDER, UNION_DATA, "", ENTRY);
105
106 Parsable tmpData = listener.getParsedDataStack().peek();
107
108 switch (tmpData.getYangConstructType()) {
109 case LEAF_DATA:
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +0530110 // Set the name of union same as leaf.
Vinod Kumar Se4b9b0c2016-04-30 21:09:15 +0530111 unionNode.setName(((YangLeaf) tmpData).getName() + UNION_CLASS_SUFFIX);
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +0530112 // Pop the stack entry to obtain the parent YANG node.
113 Parsable leaf = listener.getParsedDataStack().pop();
114 // Add the union node to the parent holder of leaf.
115 addChildToParentNode(listener, unionNode);
116 // Push the popped entry back to the stack.
117 listener.getParsedDataStack().push(leaf);
Gaurav Agrawalbd804472016-03-25 11:25:36 +0530118 break;
119 case LEAF_LIST_DATA:
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +0530120 // Set the name of union same as leaf list.
Vinod Kumar Se4b9b0c2016-04-30 21:09:15 +0530121 unionNode.setName(((YangLeafList) tmpData).getName() + UNION_CLASS_SUFFIX);
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +0530122 // Pop the stack entry to obtain the parent YANG node.
123 Parsable leafList = listener.getParsedDataStack().pop();
124 // Add the union node to the parent holder of leaf.
125 addChildToParentNode(listener, unionNode);
126 // Push the popped entry back to the stack.
127 listener.getParsedDataStack().push(leafList);
Gaurav Agrawalbd804472016-03-25 11:25:36 +0530128 break;
129 case UNION_DATA:
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +0530130 YangUnion parentUnion = (YangUnion) tmpData;
131 /*
132 * In case parent of union is again a union, name of the
133 * child union is parent union name suffixed with running
134 * integer number, this is done because under union there
135 * could be multiple child union types.
136 */
137 unionNode.setName(parentUnion.getName() + UNION_CLASS_SUFFIX + parentUnion.getChildUnionNumber());
138 // Increment the running number.
139 parentUnion.setChildUnionNumber(parentUnion.getChildUnionNumber() + 1);
140 // Add union as a child to parent union.
141 addChildToParentNode(listener, unionNode);
Gaurav Agrawalbd804472016-03-25 11:25:36 +0530142 break;
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +0530143 case TYPEDEF_DATA:
144 YangTypeDef typeDef = (YangTypeDef) tmpData;
145 // Set the name of union same as typedef name.
146 unionNode.setName(typeDef.getName() + UNION_CLASS_SUFFIX);
147 // Add union as a child to parent type def.
148 addChildToParentNode(listener, unionNode);
149 break;
150 // TODO deviate.
Gaurav Agrawalbd804472016-03-25 11:25:36 +0530151 default:
152 throw new ParserException(constructListenerErrorMessage(INVALID_HOLDER, TYPE_DATA,
153 ((YangType<?>) typeData).getDataTypeName(), ENTRY));
154 }
155 listener.getParsedDataStack().push(typeData);
156 listener.getParsedDataStack().push(unionNode);
157 } else {
158 throw new ParserException(constructListenerErrorMessage(INVALID_HOLDER, UNION_DATA, "", ENTRY));
159 }
160 }
161
162 /**
163 * It is called when parser exits from grammar rule (union), it perform
164 * validations and update the data model tree.
165 *
166 * @param listener Listener's object
167 * @param ctx context object of the grammar rule
168 */
169 public static void processUnionExit(TreeWalkListener listener,
170 GeneratedYangParser.UnionSpecificationContext ctx) {
171
172 // Check for stack to be non empty.
173 checkStackIsNotEmpty(listener, MISSING_HOLDER, UNION_DATA, "", EXIT);
174
175 Parsable tmpUnionNode = listener.getParsedDataStack().peek();
176 if (tmpUnionNode instanceof YangUnion) {
177 YangUnion unionNode = (YangUnion) tmpUnionNode;
178 listener.getParsedDataStack().pop();
179
180 // Check for stack to be non empty.
181 checkStackIsNotEmpty(listener, MISSING_HOLDER, UNION_DATA, "", EXIT);
182
183 Parsable tmpNode = listener.getParsedDataStack().peek();
184 switch (tmpNode.getYangConstructType()) {
185 case TYPE_DATA: {
186 YangType<YangUnion> typeNode = (YangType<YangUnion>) tmpNode;
187 typeNode.setDataTypeExtendedInfo(unionNode);
188 break;
189 }
190 default:
191 throw new ParserException(
192 constructListenerErrorMessage(INVALID_HOLDER, UNION_DATA, "", EXIT));
193 }
194 } else {
195 throw new ParserException(
196 constructListenerErrorMessage(MISSING_CURRENT_HOLDER, UNION_DATA, "", EXIT));
197 }
198 }
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +0530199
200 /**
201 * Adds the union node to the parent holder.
202 *
203 * @param listener listener's object
204 * @param unionNode union node which needs to be added to parent
205 */
206 private static void addChildToParentNode(TreeWalkListener listener, YangUnion unionNode) {
207 if (!(listener.getParsedDataStack().peek() instanceof YangNode)) {
208 throw new ParserException(constructListenerErrorMessage(INVALID_HOLDER, UNION_DATA,
209 "", ENTRY));
210 } else {
211 YangNode curNode = (YangNode) listener.getParsedDataStack().peek();
212 try {
213 curNode.addChild(unionNode);
214 } catch (DataModelException e) {
215 throw new ParserException(constructExtendedListenerErrorMessage(UNHANDLED_PARSED_DATA,
Vidyashree Rama7142d9c2016-04-26 15:06:06 +0530216 UNION_DATA, "", ENTRY, e.getMessage()));
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +0530217 }
218 }
219 }
Vinod Kumar Se4b9b0c2016-04-30 21:09:15 +0530220}