blob: 9653e4005340940b5ef264405cab3c6af3116171 [file] [log] [blame]
Gaurav Agrawalf6ccc972016-03-25 11:25:36 +05301/*
Brian O'Connor0f7908b2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Gaurav Agrawalf6ccc972016-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 Agrawal26390042016-04-12 13:30:16 +053045import org.onosproject.yangutils.datamodel.YangNode;
Gaurav Agrawalf6ccc972016-03-25 11:25:36 +053046import org.onosproject.yangutils.datamodel.YangType;
Gaurav Agrawal26390042016-04-12 13:30:16 +053047import org.onosproject.yangutils.datamodel.YangTypeDef;
Gaurav Agrawalf6ccc972016-03-25 11:25:36 +053048import org.onosproject.yangutils.datamodel.YangUnion;
Gaurav Agrawal26390042016-04-12 13:30:16 +053049import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
Bharat saraswalc2d3be12016-06-16 00:29:12 +053050import org.onosproject.yangutils.datamodel.utils.Parsable;
Gaurav Agrawalf6ccc972016-03-25 11:25:36 +053051import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser;
52import org.onosproject.yangutils.parser.exceptions.ParserException;
53import org.onosproject.yangutils.parser.impl.TreeWalkListener;
54
Gaurav Agrawal97a5e1c2016-04-18 18:53:11 +053055import static org.onosproject.yangutils.datamodel.utils.GeneratedLanguage.JAVA_GENERATION;
Bharat saraswalc2d3be12016-06-16 00:29:12 +053056import static org.onosproject.yangutils.datamodel.utils.YangConstructType.TYPE_DATA;
57import static org.onosproject.yangutils.datamodel.utils.YangConstructType.UNION_DATA;
Gaurav Agrawalf6ccc972016-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 Agrawal26390042016-04-12 13:30:16 +053060import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction.constructExtendedListenerErrorMessage;
Gaurav Agrawalf6ccc972016-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 Agrawal26390042016-04-12 13:30:16 +053065import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.UNHANDLED_PARSED_DATA;
Gaurav Agrawalf6ccc972016-03-25 11:25:36 +053066import static org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation.checkStackIsNotEmpty;
Bharat saraswalc2d3be12016-06-16 00:29:12 +053067import static org.onosproject.yangutils.translator.tojava.YangDataModelFactory.getYangUnionNode;
Gaurav Agrawalf6ccc972016-03-25 11:25:36 +053068
69/**
Bharat saraswal63f26fb2016-04-05 15:13:44 +053070 * Represents listener based call back function corresponding to the "union" rule
Gaurav Agrawalf6ccc972016-03-25 11:25:36 +053071 * defined in ANTLR grammar file for corresponding ABNF rule in RFC 6020.
72 */
73public final class UnionListener {
Bharat saraswal63f26fb2016-04-05 15:13:44 +053074
Gaurav Agrawalf6ccc972016-03-25 11:25:36 +053075 /**
Gaurav Agrawal26390042016-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 Agrawalf6ccc972016-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 Agrawal97a5e1c2016-04-18 18:53:11 +0530100 YangUnion unionNode = getYangUnionNode(JAVA_GENERATION);
Gaurav Agrawalf6ccc972016-03-25 11:25:36 +0530101 Parsable typeData = listener.getParsedDataStack().pop();
102
Bharat saraswale3175d32016-08-31 17:50:11 +0530103 unionNode.setLineNumber(ctx.getStart().getLine());
104 unionNode.setCharPosition(ctx.getStart().getCharPositionInLine());
105 unionNode.setFileName(listener.getFileName());
Gaurav Agrawalf6ccc972016-03-25 11:25:36 +0530106 // Check for stack to be non empty.
107 checkStackIsNotEmpty(listener, MISSING_HOLDER, UNION_DATA, "", ENTRY);
108
109 Parsable tmpData = listener.getParsedDataStack().peek();
110
111 switch (tmpData.getYangConstructType()) {
112 case LEAF_DATA:
Gaurav Agrawal26390042016-04-12 13:30:16 +0530113 // Set the name of union same as leaf.
Vinod Kumar S79a374b2016-04-30 21:09:15 +0530114 unionNode.setName(((YangLeaf) tmpData).getName() + UNION_CLASS_SUFFIX);
Gaurav Agrawal26390042016-04-12 13:30:16 +0530115 // Pop the stack entry to obtain the parent YANG node.
116 Parsable leaf = listener.getParsedDataStack().pop();
117 // Add the union node to the parent holder of leaf.
118 addChildToParentNode(listener, unionNode);
119 // Push the popped entry back to the stack.
120 listener.getParsedDataStack().push(leaf);
Gaurav Agrawalf6ccc972016-03-25 11:25:36 +0530121 break;
122 case LEAF_LIST_DATA:
Gaurav Agrawal26390042016-04-12 13:30:16 +0530123 // Set the name of union same as leaf list.
Vinod Kumar S79a374b2016-04-30 21:09:15 +0530124 unionNode.setName(((YangLeafList) tmpData).getName() + UNION_CLASS_SUFFIX);
Gaurav Agrawal26390042016-04-12 13:30:16 +0530125 // Pop the stack entry to obtain the parent YANG node.
126 Parsable leafList = listener.getParsedDataStack().pop();
127 // Add the union node to the parent holder of leaf.
128 addChildToParentNode(listener, unionNode);
129 // Push the popped entry back to the stack.
130 listener.getParsedDataStack().push(leafList);
Gaurav Agrawalf6ccc972016-03-25 11:25:36 +0530131 break;
132 case UNION_DATA:
Gaurav Agrawal26390042016-04-12 13:30:16 +0530133 YangUnion parentUnion = (YangUnion) tmpData;
134 /*
135 * In case parent of union is again a union, name of the
136 * child union is parent union name suffixed with running
137 * integer number, this is done because under union there
138 * could be multiple child union types.
139 */
140 unionNode.setName(parentUnion.getName() + UNION_CLASS_SUFFIX + parentUnion.getChildUnionNumber());
141 // Increment the running number.
142 parentUnion.setChildUnionNumber(parentUnion.getChildUnionNumber() + 1);
143 // Add union as a child to parent union.
144 addChildToParentNode(listener, unionNode);
Gaurav Agrawalf6ccc972016-03-25 11:25:36 +0530145 break;
Gaurav Agrawal26390042016-04-12 13:30:16 +0530146 case TYPEDEF_DATA:
147 YangTypeDef typeDef = (YangTypeDef) tmpData;
148 // Set the name of union same as typedef name.
149 unionNode.setName(typeDef.getName() + UNION_CLASS_SUFFIX);
150 // Add union as a child to parent type def.
151 addChildToParentNode(listener, unionNode);
152 break;
153 // TODO deviate.
Gaurav Agrawalf6ccc972016-03-25 11:25:36 +0530154 default:
155 throw new ParserException(constructListenerErrorMessage(INVALID_HOLDER, TYPE_DATA,
156 ((YangType<?>) typeData).getDataTypeName(), ENTRY));
157 }
158 listener.getParsedDataStack().push(typeData);
159 listener.getParsedDataStack().push(unionNode);
160 } else {
161 throw new ParserException(constructListenerErrorMessage(INVALID_HOLDER, UNION_DATA, "", ENTRY));
162 }
163 }
164
165 /**
166 * It is called when parser exits from grammar rule (union), it perform
167 * validations and update the data model tree.
168 *
169 * @param listener Listener's object
170 * @param ctx context object of the grammar rule
171 */
172 public static void processUnionExit(TreeWalkListener listener,
VinodKumarS-Huawei8f164222016-08-31 15:47:30 +0530173 GeneratedYangParser.UnionSpecificationContext ctx) {
Gaurav Agrawalf6ccc972016-03-25 11:25:36 +0530174
175 // Check for stack to be non empty.
176 checkStackIsNotEmpty(listener, MISSING_HOLDER, UNION_DATA, "", EXIT);
177
178 Parsable tmpUnionNode = listener.getParsedDataStack().peek();
179 if (tmpUnionNode instanceof YangUnion) {
180 YangUnion unionNode = (YangUnion) tmpUnionNode;
181 listener.getParsedDataStack().pop();
182
183 // Check for stack to be non empty.
184 checkStackIsNotEmpty(listener, MISSING_HOLDER, UNION_DATA, "", EXIT);
185
186 Parsable tmpNode = listener.getParsedDataStack().peek();
187 switch (tmpNode.getYangConstructType()) {
188 case TYPE_DATA: {
189 YangType<YangUnion> typeNode = (YangType<YangUnion>) tmpNode;
190 typeNode.setDataTypeExtendedInfo(unionNode);
191 break;
192 }
193 default:
194 throw new ParserException(
195 constructListenerErrorMessage(INVALID_HOLDER, UNION_DATA, "", EXIT));
196 }
197 } else {
198 throw new ParserException(
199 constructListenerErrorMessage(MISSING_CURRENT_HOLDER, UNION_DATA, "", EXIT));
200 }
201 }
Gaurav Agrawal26390042016-04-12 13:30:16 +0530202
203 /**
204 * Adds the union node to the parent holder.
205 *
206 * @param listener listener's object
207 * @param unionNode union node which needs to be added to parent
208 */
209 private static void addChildToParentNode(TreeWalkListener listener, YangUnion unionNode) {
210 if (!(listener.getParsedDataStack().peek() instanceof YangNode)) {
211 throw new ParserException(constructListenerErrorMessage(INVALID_HOLDER, UNION_DATA,
212 "", ENTRY));
213 } else {
214 YangNode curNode = (YangNode) listener.getParsedDataStack().peek();
215 try {
216 curNode.addChild(unionNode);
217 } catch (DataModelException e) {
218 throw new ParserException(constructExtendedListenerErrorMessage(UNHANDLED_PARSED_DATA,
Vidyashree Rama13960652016-04-26 15:06:06 +0530219 UNION_DATA, "", ENTRY, e.getMessage()));
Gaurav Agrawal26390042016-04-12 13:30:16 +0530220 }
221 }
222 }
Vinod Kumar S79a374b2016-04-30 21:09:15 +0530223}