blob: 2319b8eb4961cd68e81725cfe0b527f182df29d1 [file] [log] [blame]
Vidyashree Rama92fc5562016-02-12 18:44:12 +05301/*
2 * Copyright 2016 Open Networking Laboratory
3 *
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
Vidyashree Rama4f1f08b2016-02-13 21:47:58 +053019import org.onosproject.yangutils.datamodel.YangList;
Vidyashree Ramaf4c617c2016-02-24 12:28:22 +053020import org.onosproject.yangutils.datamodel.YangContainer;
21import org.onosproject.yangutils.datamodel.YangModule;
Vidyashree Rama4f1f08b2016-02-13 21:47:58 +053022import org.onosproject.yangutils.datamodel.YangNode;
23import org.onosproject.yangutils.datamodel.YangNodeType;
24import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
25import org.onosproject.yangutils.parser.Parsable;
26import org.onosproject.yangutils.parser.ParsableDataType;
Vidyashree Rama92fc5562016-02-12 18:44:12 +053027import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser;
Vidyashree Rama4f1f08b2016-02-13 21:47:58 +053028import org.onosproject.yangutils.parser.exceptions.ParserException;
Vidyashree Rama92fc5562016-02-12 18:44:12 +053029import org.onosproject.yangutils.parser.impl.TreeWalkListener;
Vidyashree Rama4f1f08b2016-02-13 21:47:58 +053030import org.onosproject.yangutils.parser.impl.YangUtilsParserManager;
Vidyashree Rama4f1f08b2016-02-13 21:47:58 +053031import org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation;
Vidyashree Rama92fc5562016-02-12 18:44:12 +053032
Vidyashree Ramaf4c617c2016-02-24 12:28:22 +053033import static org.onosproject.yangutils.parser.ParsableDataType.LIST_DATA;
34import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.ENTRY;
35import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.EXIT;
36import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction.constructExtendedListenerErrorMessage;
37import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction.constructListenerErrorMessage;
38import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.MISSING_CURRENT_HOLDER;
39import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.MISSING_HOLDER;
40import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.INVALID_HOLDER;
41import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.UNHANDLED_PARSED_DATA;
42import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.INVALID_CARDINALITY;
43import static org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation.checkStackIsNotEmpty;
44
Vidyashree Rama92fc5562016-02-12 18:44:12 +053045/*
46 * Reference: RFC6020 and YANG ANTLR Grammar
47 *
48 * ABNF grammar as per RFC6020
49 * list-stmt = list-keyword sep identifier-arg-str optsep
50 * "{" stmtsep
51 * ;; these stmts can appear in any order
52 * [when-stmt stmtsep]
53 * *(if-feature-stmt stmtsep)
54 * *(must-stmt stmtsep)
55 * [key-stmt stmtsep]
56 * *(unique-stmt stmtsep)
57 * [config-stmt stmtsep]
58 * [min-elements-stmt stmtsep]
59 * [max-elements-stmt stmtsep]
60 * [ordered-by-stmt stmtsep]
61 * [status-stmt stmtsep]
62 * [description-stmt stmtsep]
63 * [reference-stmt stmtsep]
64 * *((typedef-stmt /
65 * grouping-stmt) stmtsep)
66 * 1*(data-def-stmt stmtsep)
67 * "}"
68 *
69 * ANTLR grammar rule
70 * listStatement : LIST_KEYWORD IDENTIFIER LEFT_CURLY_BRACE (whenStatement | ifFeatureStatement | mustStatement |
71 * keyStatement | uniqueStatement | configStatement | minElementsStatement | maxElementsStatement |
72 * orderedByStatement | statusStatement | descriptionStatement | referenceStatement | typedefStatement |
73 * groupingStatement| dataDefStatement)* RIGHT_CURLY_BRACE;
74 */
75
76/**
77 * Implements listener based call back function corresponding to the "list"
78 * rule defined in ANTLR grammar file for corresponding ABNF rule in RFC 6020.
79 */
80public final class ListListener {
81
Vidyashree Rama4f1f08b2016-02-13 21:47:58 +053082 private static ParsableDataType yangConstruct;
83
Vidyashree Rama92fc5562016-02-12 18:44:12 +053084 /**
85 * Creates a new list listener.
86 */
87 private ListListener() {
88 }
89
90 /**
91 * It is called when parser receives an input matching the grammar
92 * rule (list), performs validation and updates the data model
93 * tree.
94 *
95 * @param listener listener's object.
96 * @param ctx context object of the grammar rule.
97 */
98 public static void processListEntry(TreeWalkListener listener,
99 GeneratedYangParser.ListStatementContext ctx) {
Vidyashree Rama4f1f08b2016-02-13 21:47:58 +0530100
101 YangNode curNode;
102
Vidyashree Ramaf4c617c2016-02-24 12:28:22 +0530103 checkStackIsNotEmpty(listener, MISSING_HOLDER, LIST_DATA, ctx.IDENTIFIER().getText(), ENTRY);
Vidyashree Rama4f1f08b2016-02-13 21:47:58 +0530104
105 boolean result = validateSubStatementsCardinality(ctx);
106 if (!result) {
Vidyashree Ramaf4c617c2016-02-24 12:28:22 +0530107 throw new ParserException(constructListenerErrorMessage(INVALID_CARDINALITY, yangConstruct, "", ENTRY));
Vidyashree Rama4f1f08b2016-02-13 21:47:58 +0530108 }
109
110 YangList yangList = new YangList(YangNodeType.LIST_NODE);
111 yangList.setName(ctx.IDENTIFIER().getText());
112
Vidyashree Ramaf4c617c2016-02-24 12:28:22 +0530113 /* If "config" is not specified, the default is the same as the parent
114 schema node's "config" value. */
115 if (ctx.configStatement().isEmpty()) {
116 boolean parentConfig = ListenerValidation.getParentNodeConfig(listener);
117 yangList.setConfig(parentConfig);
118 }
119
Vidyashree Rama4f1f08b2016-02-13 21:47:58 +0530120 Parsable curData = listener.getParsedDataStack().peek();
Vidyashree Ramaf4c617c2016-02-24 12:28:22 +0530121 if ((curData instanceof YangModule) || (curData instanceof YangContainer)
122 || (curData instanceof YangList)) {
Vidyashree Rama4f1f08b2016-02-13 21:47:58 +0530123 curNode = (YangNode) curData;
124 try {
125 curNode.addChild(yangList);
126 } catch (DataModelException e) {
Vidyashree Ramaf4c617c2016-02-24 12:28:22 +0530127 throw new ParserException(constructExtendedListenerErrorMessage(UNHANDLED_PARSED_DATA,
128 LIST_DATA, ctx.IDENTIFIER().getText(), ENTRY, e.getMessage()));
Vidyashree Rama4f1f08b2016-02-13 21:47:58 +0530129 }
130 listener.getParsedDataStack().push(yangList);
131 } else {
Vidyashree Ramaf4c617c2016-02-24 12:28:22 +0530132 throw new ParserException(constructListenerErrorMessage(INVALID_HOLDER, LIST_DATA,
133 ctx.IDENTIFIER().getText(), ENTRY));
Vidyashree Rama4f1f08b2016-02-13 21:47:58 +0530134 }
Vidyashree Rama92fc5562016-02-12 18:44:12 +0530135 }
136
137 /**
138 * It is called when parser exits from grammar rule (list), it performs
139 * validation and updates the data model tree.
140 *
141 * @param listener listener's object.
142 * @param ctx context object of the grammar rule.
143 */
144 public static void processListExit(TreeWalkListener listener,
145 GeneratedYangParser.ListStatementContext ctx) {
Vidyashree Rama4f1f08b2016-02-13 21:47:58 +0530146
Vidyashree Ramaf4c617c2016-02-24 12:28:22 +0530147 checkStackIsNotEmpty(listener, MISSING_HOLDER, LIST_DATA, ctx.IDENTIFIER().getText(), EXIT);
Vidyashree Rama4f1f08b2016-02-13 21:47:58 +0530148
149 if (listener.getParsedDataStack().peek() instanceof YangList) {
Vidyashree Ramaf4c617c2016-02-24 12:28:22 +0530150 YangList yangList = (YangList) listener.getParsedDataStack().peek();
151 try {
152 yangList.validateDataOnExit();
153 } catch (DataModelException e) {
154 throw new ParserException(constructExtendedListenerErrorMessage(UNHANDLED_PARSED_DATA,
155 LIST_DATA, ctx.IDENTIFIER().getText(), EXIT, e.getMessage()));
156 }
Vidyashree Rama4f1f08b2016-02-13 21:47:58 +0530157 listener.getParsedDataStack().pop();
158 } else {
Vidyashree Ramaf4c617c2016-02-24 12:28:22 +0530159 throw new ParserException(constructListenerErrorMessage(MISSING_CURRENT_HOLDER, LIST_DATA,
160 ctx.IDENTIFIER().getText(), EXIT));
Vidyashree Rama4f1f08b2016-02-13 21:47:58 +0530161 }
162 }
163
164 /**
165 * Validates the cardinality of list sub-statements as per grammar.
166 *
167 * @param ctx context object of the grammar rule.
168 * @return true/false validation success or failure.
169 */
Vidyashree Ramaf4c617c2016-02-24 12:28:22 +0530170 private static boolean validateSubStatementsCardinality(GeneratedYangParser.ListStatementContext ctx) {
Vidyashree Rama4f1f08b2016-02-13 21:47:58 +0530171
172 if ((!ctx.keyStatement().isEmpty())
173 && (ctx.keyStatement().size() != YangUtilsParserManager.SUB_STATEMENT_CARDINALITY)) {
174 yangConstruct = ParsableDataType.KEY_DATA;
175 return false;
176 }
177
178 if ((!ctx.configStatement().isEmpty())
179 && (ctx.configStatement().size() != YangUtilsParserManager.SUB_STATEMENT_CARDINALITY)) {
180 yangConstruct = ParsableDataType.CONFIG_DATA;
181 return false;
182 }
183
184 if ((!ctx.maxElementsStatement().isEmpty())
185 && (ctx.maxElementsStatement().size() != YangUtilsParserManager.SUB_STATEMENT_CARDINALITY)) {
186 yangConstruct = ParsableDataType.MAX_ELEMENT_DATA;
187 return false;
188 }
189
190 if ((!ctx.minElementsStatement().isEmpty())
191 && (ctx.minElementsStatement().size() != YangUtilsParserManager.SUB_STATEMENT_CARDINALITY)) {
192 yangConstruct = ParsableDataType.MIN_ELEMENT_DATA;
193 return false;
194 }
195
196 if ((!ctx.descriptionStatement().isEmpty())
197 && (ctx.descriptionStatement().size() != YangUtilsParserManager.SUB_STATEMENT_CARDINALITY)) {
198 yangConstruct = ParsableDataType.DESCRIPTION_DATA;
199 return false;
200 }
201
202 if ((!ctx.referenceStatement().isEmpty())
203 && (ctx.referenceStatement().size() != YangUtilsParserManager.SUB_STATEMENT_CARDINALITY)) {
204 yangConstruct = ParsableDataType.REFERENCE_DATA;
205 return false;
206 }
207
208 if ((!ctx.statusStatement().isEmpty())
209 && (ctx.statusStatement().size() != YangUtilsParserManager.SUB_STATEMENT_CARDINALITY)) {
210 yangConstruct = ParsableDataType.STATUS_DATA;
211 return false;
212 }
213
214 if (ctx.dataDefStatement().isEmpty()) {
215 yangConstruct = ParsableDataType.LIST_DATA;
216 return false;
217 }
218
219 return true;
Vidyashree Rama92fc5562016-02-12 18:44:12 +0530220 }
221}