blob: 5eeaa0795339f6794a7895c13994e5adfccc38a8 [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
56import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.ENTRY;
57import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.EXIT;
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +053058import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction.constructExtendedListenerErrorMessage;
Gaurav Agrawalbd804472016-03-25 11:25:36 +053059import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction.constructListenerErrorMessage;
60import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.INVALID_HOLDER;
61import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.MISSING_CURRENT_HOLDER;
62import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.MISSING_HOLDER;
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +053063import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.UNHANDLED_PARSED_DATA;
Gaurav Agrawalbd804472016-03-25 11:25:36 +053064import static org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation.checkStackIsNotEmpty;
65import static org.onosproject.yangutils.utils.YangConstructType.TYPE_DATA;
66import static org.onosproject.yangutils.utils.YangConstructType.UNION_DATA;
67
68/**
Bharat saraswald9822e92016-04-05 15:13:44 +053069 * Represents listener based call back function corresponding to the "union" rule
Gaurav Agrawalbd804472016-03-25 11:25:36 +053070 * defined in ANTLR grammar file for corresponding ABNF rule in RFC 6020.
71 */
72public final class UnionListener {
Bharat saraswald9822e92016-04-05 15:13:44 +053073
Gaurav Agrawalbd804472016-03-25 11:25:36 +053074 /**
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +053075 * Suffix to be used while creating union class.
76 */
77 private static final String UNION_CLASS_SUFFIX = "_union";
78
79 /**
Gaurav Agrawalbd804472016-03-25 11:25:36 +053080 * Creates a new union listener.
81 */
82 private UnionListener() {
83 }
84
85 /**
86 * It is called when parser enters grammar rule (union), it perform
87 * validations and updates the data model tree.
88 *
89 * @param listener listener's object
90 * @param ctx context object of the grammar rule
91 */
92 public static void processUnionEntry(TreeWalkListener listener,
93 GeneratedYangParser.UnionSpecificationContext ctx) {
94
95 // Check for stack to be non empty.
96 checkStackIsNotEmpty(listener, MISSING_HOLDER, UNION_DATA, "", ENTRY);
97
98 if (listener.getParsedDataStack().peek() instanceof YangType) {
99 YangUnion unionNode = new YangUnion();
100 Parsable typeData = listener.getParsedDataStack().pop();
101
102 // Check for stack to be non empty.
103 checkStackIsNotEmpty(listener, MISSING_HOLDER, UNION_DATA, "", ENTRY);
104
105 Parsable tmpData = listener.getParsedDataStack().peek();
106
107 switch (tmpData.getYangConstructType()) {
108 case LEAF_DATA:
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +0530109 // Set the name of union same as leaf.
110 unionNode.setName(((YangLeaf) tmpData).getLeafName() + UNION_CLASS_SUFFIX);
111 // Pop the stack entry to obtain the parent YANG node.
112 Parsable leaf = listener.getParsedDataStack().pop();
113 // Add the union node to the parent holder of leaf.
114 addChildToParentNode(listener, unionNode);
115 // Push the popped entry back to the stack.
116 listener.getParsedDataStack().push(leaf);
Gaurav Agrawalbd804472016-03-25 11:25:36 +0530117 break;
118 case LEAF_LIST_DATA:
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +0530119 // Set the name of union same as leaf list.
120 unionNode.setName(((YangLeafList) tmpData).getLeafName() + UNION_CLASS_SUFFIX);
121 // Pop the stack entry to obtain the parent YANG node.
122 Parsable leafList = listener.getParsedDataStack().pop();
123 // Add the union node to the parent holder of leaf.
124 addChildToParentNode(listener, unionNode);
125 // Push the popped entry back to the stack.
126 listener.getParsedDataStack().push(leafList);
Gaurav Agrawalbd804472016-03-25 11:25:36 +0530127 break;
128 case UNION_DATA:
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +0530129 YangUnion parentUnion = (YangUnion) tmpData;
130 /*
131 * In case parent of union is again a union, name of the
132 * child union is parent union name suffixed with running
133 * integer number, this is done because under union there
134 * could be multiple child union types.
135 */
136 unionNode.setName(parentUnion.getName() + UNION_CLASS_SUFFIX + parentUnion.getChildUnionNumber());
137 // Increment the running number.
138 parentUnion.setChildUnionNumber(parentUnion.getChildUnionNumber() + 1);
139 // Add union as a child to parent union.
140 addChildToParentNode(listener, unionNode);
Gaurav Agrawalbd804472016-03-25 11:25:36 +0530141 break;
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +0530142 case TYPEDEF_DATA:
143 YangTypeDef typeDef = (YangTypeDef) tmpData;
144 // Set the name of union same as typedef name.
145 unionNode.setName(typeDef.getName() + UNION_CLASS_SUFFIX);
146 // Add union as a child to parent type def.
147 addChildToParentNode(listener, unionNode);
148 break;
149 // TODO deviate.
Gaurav Agrawalbd804472016-03-25 11:25:36 +0530150 default:
151 throw new ParserException(constructListenerErrorMessage(INVALID_HOLDER, TYPE_DATA,
152 ((YangType<?>) typeData).getDataTypeName(), ENTRY));
153 }
154 listener.getParsedDataStack().push(typeData);
155 listener.getParsedDataStack().push(unionNode);
156 } else {
157 throw new ParserException(constructListenerErrorMessage(INVALID_HOLDER, UNION_DATA, "", ENTRY));
158 }
159 }
160
161 /**
162 * It is called when parser exits from grammar rule (union), it perform
163 * validations and update the data model tree.
164 *
165 * @param listener Listener's object
166 * @param ctx context object of the grammar rule
167 */
168 public static void processUnionExit(TreeWalkListener listener,
169 GeneratedYangParser.UnionSpecificationContext ctx) {
170
171 // Check for stack to be non empty.
172 checkStackIsNotEmpty(listener, MISSING_HOLDER, UNION_DATA, "", EXIT);
173
174 Parsable tmpUnionNode = listener.getParsedDataStack().peek();
175 if (tmpUnionNode instanceof YangUnion) {
176 YangUnion unionNode = (YangUnion) tmpUnionNode;
177 listener.getParsedDataStack().pop();
178
179 // Check for stack to be non empty.
180 checkStackIsNotEmpty(listener, MISSING_HOLDER, UNION_DATA, "", EXIT);
181
182 Parsable tmpNode = listener.getParsedDataStack().peek();
183 switch (tmpNode.getYangConstructType()) {
184 case TYPE_DATA: {
185 YangType<YangUnion> typeNode = (YangType<YangUnion>) tmpNode;
186 typeNode.setDataTypeExtendedInfo(unionNode);
187 break;
188 }
189 default:
190 throw new ParserException(
191 constructListenerErrorMessage(INVALID_HOLDER, UNION_DATA, "", EXIT));
192 }
193 } else {
194 throw new ParserException(
195 constructListenerErrorMessage(MISSING_CURRENT_HOLDER, UNION_DATA, "", EXIT));
196 }
197 }
Gaurav Agrawal1c8f80c2016-04-12 13:30:16 +0530198
199 /**
200 * Adds the union node to the parent holder.
201 *
202 * @param listener listener's object
203 * @param unionNode union node which needs to be added to parent
204 */
205 private static void addChildToParentNode(TreeWalkListener listener, YangUnion unionNode) {
206 if (!(listener.getParsedDataStack().peek() instanceof YangNode)) {
207 throw new ParserException(constructListenerErrorMessage(INVALID_HOLDER, UNION_DATA,
208 "", ENTRY));
209 } else {
210 YangNode curNode = (YangNode) listener.getParsedDataStack().peek();
211 try {
212 curNode.addChild(unionNode);
213 } catch (DataModelException e) {
214 throw new ParserException(constructExtendedListenerErrorMessage(UNHANDLED_PARSED_DATA,
215 YangConstructType.UNION_DATA, "", ENTRY, e.getMessage()));
216 }
217 }
218 }
Gaurav Agrawalbd804472016-03-25 11:25:36 +0530219}