blob: 82d69cbb41b4ad1f8cb46b30c5f6ef51e9abeb58 [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;
20import org.onosproject.yangutils.datamodel.YangNode;
21import org.onosproject.yangutils.datamodel.YangNodeType;
22import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
23import org.onosproject.yangutils.parser.Parsable;
24import org.onosproject.yangutils.parser.ParsableDataType;
Vidyashree Rama92fc5562016-02-12 18:44:12 +053025import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser;
Vidyashree Rama4f1f08b2016-02-13 21:47:58 +053026import org.onosproject.yangutils.parser.exceptions.ParserException;
Vidyashree Rama92fc5562016-02-12 18:44:12 +053027import org.onosproject.yangutils.parser.impl.TreeWalkListener;
Vidyashree Rama4f1f08b2016-02-13 21:47:58 +053028import org.onosproject.yangutils.parser.impl.YangUtilsParserManager;
29import org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation;
30import org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction;
31import org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType;
32import org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation;
Vidyashree Rama92fc5562016-02-12 18:44:12 +053033
34/*
35 * Reference: RFC6020 and YANG ANTLR Grammar
36 *
37 * ABNF grammar as per RFC6020
38 * list-stmt = list-keyword sep identifier-arg-str optsep
39 * "{" stmtsep
40 * ;; these stmts can appear in any order
41 * [when-stmt stmtsep]
42 * *(if-feature-stmt stmtsep)
43 * *(must-stmt stmtsep)
44 * [key-stmt stmtsep]
45 * *(unique-stmt stmtsep)
46 * [config-stmt stmtsep]
47 * [min-elements-stmt stmtsep]
48 * [max-elements-stmt stmtsep]
49 * [ordered-by-stmt stmtsep]
50 * [status-stmt stmtsep]
51 * [description-stmt stmtsep]
52 * [reference-stmt stmtsep]
53 * *((typedef-stmt /
54 * grouping-stmt) stmtsep)
55 * 1*(data-def-stmt stmtsep)
56 * "}"
57 *
58 * ANTLR grammar rule
59 * listStatement : LIST_KEYWORD IDENTIFIER LEFT_CURLY_BRACE (whenStatement | ifFeatureStatement | mustStatement |
60 * keyStatement | uniqueStatement | configStatement | minElementsStatement | maxElementsStatement |
61 * orderedByStatement | statusStatement | descriptionStatement | referenceStatement | typedefStatement |
62 * groupingStatement| dataDefStatement)* RIGHT_CURLY_BRACE;
63 */
64
65/**
66 * Implements listener based call back function corresponding to the "list"
67 * rule defined in ANTLR grammar file for corresponding ABNF rule in RFC 6020.
68 */
69public final class ListListener {
70
Vidyashree Rama4f1f08b2016-02-13 21:47:58 +053071 private static ParsableDataType yangConstruct;
72
Vidyashree Rama92fc5562016-02-12 18:44:12 +053073 /**
74 * Creates a new list listener.
75 */
76 private ListListener() {
77 }
78
79 /**
80 * It is called when parser receives an input matching the grammar
81 * rule (list), performs validation and updates the data model
82 * tree.
83 *
84 * @param listener listener's object.
85 * @param ctx context object of the grammar rule.
86 */
87 public static void processListEntry(TreeWalkListener listener,
88 GeneratedYangParser.ListStatementContext ctx) {
Vidyashree Rama4f1f08b2016-02-13 21:47:58 +053089
90 YangNode curNode;
91
92 ListenerValidation.checkStackIsNotEmpty(listener, ListenerErrorType.MISSING_HOLDER,
93 ParsableDataType.LIST_DATA, String.valueOf(ctx.IDENTIFIER().getText()),
94 ListenerErrorLocation.ENTRY);
95
96 boolean result = validateSubStatementsCardinality(ctx);
97 if (!result) {
98 throw new ParserException(ListenerErrorMessageConstruction
99 .constructListenerErrorMessage(ListenerErrorType.INVALID_CARDINALITY,
100 yangConstruct, "", ListenerErrorLocation.ENTRY));
101 }
102
103 YangList yangList = new YangList(YangNodeType.LIST_NODE);
104 yangList.setName(ctx.IDENTIFIER().getText());
105
106 Parsable curData = listener.getParsedDataStack().peek();
107 if (curData instanceof YangNode) {
108 curNode = (YangNode) curData;
109 try {
110 curNode.addChild(yangList);
111 } catch (DataModelException e) {
112 throw new ParserException(ListenerErrorMessageConstruction
113 .constructExtendedListenerErrorMessage(ListenerErrorType.UNHANDLED_PARSED_DATA,
114 ParsableDataType.LIST_DATA,
115 String.valueOf(ctx.IDENTIFIER().getText()),
116 ListenerErrorLocation.ENTRY,
117 e.getMessage()));
118 }
119 listener.getParsedDataStack().push(yangList);
120 } else {
121 throw new ParserException(ListenerErrorMessageConstruction
122 .constructListenerErrorMessage(ListenerErrorType.INVALID_HOLDER,
123 ParsableDataType.LIST_DATA,
124 String.valueOf(ctx.IDENTIFIER().getText()),
125 ListenerErrorLocation.ENTRY));
126 }
Vidyashree Rama92fc5562016-02-12 18:44:12 +0530127 }
128
129 /**
130 * It is called when parser exits from grammar rule (list), it performs
131 * validation and updates the data model tree.
132 *
133 * @param listener listener's object.
134 * @param ctx context object of the grammar rule.
135 */
136 public static void processListExit(TreeWalkListener listener,
137 GeneratedYangParser.ListStatementContext ctx) {
Vidyashree Rama4f1f08b2016-02-13 21:47:58 +0530138
139 ListenerValidation.checkStackIsNotEmpty(listener, ListenerErrorType.MISSING_HOLDER,
140 ParsableDataType.LIST_DATA, String.valueOf(ctx.IDENTIFIER().getText()),
141 ListenerErrorLocation.EXIT);
142
143 if (listener.getParsedDataStack().peek() instanceof YangList) {
144 listener.getParsedDataStack().pop();
145 } else {
146 throw new ParserException(ListenerErrorMessageConstruction
147 .constructListenerErrorMessage(ListenerErrorType.INVALID_HOLDER,
148 ParsableDataType.LIST_DATA,
149 String.valueOf(ctx.IDENTIFIER().getText()),
150 ListenerErrorLocation.EXIT));
151 }
152 }
153
154 /**
155 * Validates the cardinality of list sub-statements as per grammar.
156 *
157 * @param ctx context object of the grammar rule.
158 * @return true/false validation success or failure.
159 */
160 public static boolean validateSubStatementsCardinality(GeneratedYangParser.ListStatementContext ctx) {
161
162 if ((!ctx.keyStatement().isEmpty())
163 && (ctx.keyStatement().size() != YangUtilsParserManager.SUB_STATEMENT_CARDINALITY)) {
164 yangConstruct = ParsableDataType.KEY_DATA;
165 return false;
166 }
167
168 if ((!ctx.configStatement().isEmpty())
169 && (ctx.configStatement().size() != YangUtilsParserManager.SUB_STATEMENT_CARDINALITY)) {
170 yangConstruct = ParsableDataType.CONFIG_DATA;
171 return false;
172 }
173
174 if ((!ctx.maxElementsStatement().isEmpty())
175 && (ctx.maxElementsStatement().size() != YangUtilsParserManager.SUB_STATEMENT_CARDINALITY)) {
176 yangConstruct = ParsableDataType.MAX_ELEMENT_DATA;
177 return false;
178 }
179
180 if ((!ctx.minElementsStatement().isEmpty())
181 && (ctx.minElementsStatement().size() != YangUtilsParserManager.SUB_STATEMENT_CARDINALITY)) {
182 yangConstruct = ParsableDataType.MIN_ELEMENT_DATA;
183 return false;
184 }
185
186 if ((!ctx.descriptionStatement().isEmpty())
187 && (ctx.descriptionStatement().size() != YangUtilsParserManager.SUB_STATEMENT_CARDINALITY)) {
188 yangConstruct = ParsableDataType.DESCRIPTION_DATA;
189 return false;
190 }
191
192 if ((!ctx.referenceStatement().isEmpty())
193 && (ctx.referenceStatement().size() != YangUtilsParserManager.SUB_STATEMENT_CARDINALITY)) {
194 yangConstruct = ParsableDataType.REFERENCE_DATA;
195 return false;
196 }
197
198 if ((!ctx.statusStatement().isEmpty())
199 && (ctx.statusStatement().size() != YangUtilsParserManager.SUB_STATEMENT_CARDINALITY)) {
200 yangConstruct = ParsableDataType.STATUS_DATA;
201 return false;
202 }
203
204 if (ctx.dataDefStatement().isEmpty()) {
205 yangConstruct = ParsableDataType.LIST_DATA;
206 return false;
207 }
208
209 return true;
Vidyashree Rama92fc5562016-02-12 18:44:12 +0530210 }
211}