blob: b98bd12aec642ed1f1353b7525a75654a75eb3c7 [file] [log] [blame]
Gaurav Agrawale3ed0d92016-03-23 19:04:17 +05301/*
2 * Copyright 2014-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
19import org.onosproject.yangutils.datamodel.YangCase;
20import org.onosproject.yangutils.datamodel.YangChoice;
21import org.onosproject.yangutils.datamodel.YangNode;
22import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
23import org.onosproject.yangutils.parser.Parsable;
24import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser;
25import org.onosproject.yangutils.parser.exceptions.ParserException;
26import org.onosproject.yangutils.parser.impl.TreeWalkListener;
27
28import static org.onosproject.yangutils.datamodel.utils.GeneratedLanguage.JAVA_GENERATION;
29import static org.onosproject.yangutils.datamodel.utils.YangDataModelFactory.getYangCaseNode;
30import static org.onosproject.yangutils.parser.impl.parserutils.ListenerCollisionDetector.detectCollidingChildUtil;
31import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.ENTRY;
32import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.EXIT;
33import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction.constructExtendedListenerErrorMessage;
34import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction.constructListenerErrorMessage;
35import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.INVALID_HOLDER;
36import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.MISSING_CURRENT_HOLDER;
37import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.MISSING_HOLDER;
38import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.UNHANDLED_PARSED_DATA;
39import static org.onosproject.yangutils.parser.impl.parserutils.ListenerUtil.getValidIdentifier;
40import static org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation.checkStackIsNotEmpty;
41import static org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation.validateCardinalityMaxOne;
42import static org.onosproject.yangutils.utils.YangConstructType.CASE_DATA;
43import static org.onosproject.yangutils.utils.YangConstructType.DESCRIPTION_DATA;
44import static org.onosproject.yangutils.utils.YangConstructType.REFERENCE_DATA;
45import static org.onosproject.yangutils.utils.YangConstructType.STATUS_DATA;
46import static org.onosproject.yangutils.utils.YangConstructType.WHEN_DATA;
47
48/*
49 * Reference: RFC6020 and YANG ANTLR Grammar
50 *
51 * ABNF grammar as per RFC6020
52 * case-stmt = case-keyword sep identifier-arg-str optsep
53 * (";" /
54 * "{" stmtsep
55 * ;; these stmts can appear in any order
56 * [when-stmt stmtsep]
57 * *(if-feature-stmt stmtsep)
58 * [status-stmt stmtsep]
59 * [description-stmt stmtsep]
60 * [reference-stmt stmtsep]
61 * *(data-def-stmt stmtsep)
62 * "}")
63 *
64 * ANTLR grammar rule
65 * caseStatement : CASE_KEYWORD identifier (STMTEND | LEFT_CURLY_BRACE (whenStatement | ifFeatureStatement
66 * | statusStatement | descriptionStatement | referenceStatement | dataDefStatement)* RIGHT_CURLY_BRACE);
67 */
68
69/**
70 * Implements listener based call back function corresponding to the "case" rule
71 * defined in ANTLR grammar file for corresponding ABNF rule in RFC 6020.
72 */
73public final class CaseListener {
74
75 /**
76 * Create a new case listener.
77 */
78 private CaseListener() {
79 }
80
81 /**
82 * It is called when parser enters grammar rule (case), it perform
83 * validations and updates the data model tree.
84 *
85 * @param listener listener's object
86 * @param ctx context object of the grammar rule
87 */
88 public static void processCaseEntry(TreeWalkListener listener,
89 GeneratedYangParser.CaseStatementContext ctx) {
90
91 // Check for stack to be non empty.
92 checkStackIsNotEmpty(listener, MISSING_HOLDER, CASE_DATA, ctx.identifier().getText(), ENTRY);
93
94 // Check validity of identifier and remove double quotes.
95 String identifier = getValidIdentifier(ctx.identifier().getText(), CASE_DATA, ctx);
96
97 // Validate sub statement cardinality.
98 validateSubStatementsCardinality(ctx);
99
100 Parsable curData = listener.getParsedDataStack().peek();
101
102 // Check for identifier collision
103 int line = ctx.getStart().getLine();
104 int charPositionInLine = ctx.getStart().getCharPositionInLine();
105 detectCollidingChildUtil(listener, line, charPositionInLine, identifier, CASE_DATA);
106
107 if (curData instanceof YangChoice) {
108 YangCase caseNode = getYangCaseNode(JAVA_GENERATION);
109 caseNode.setName(identifier);
110 YangNode curNode = (YangNode) curData;
111 try {
112 curNode.addChild(caseNode);
113 } catch (DataModelException e) {
114 throw new ParserException(constructExtendedListenerErrorMessage(UNHANDLED_PARSED_DATA,
115 CASE_DATA, ctx.identifier().getText(), ENTRY, e.getMessage()));
116 }
117 listener.getParsedDataStack().push(caseNode);
118 } else {
119 throw new ParserException(constructListenerErrorMessage(INVALID_HOLDER, CASE_DATA,
120 ctx.identifier().getText(), ENTRY));
121 }
122 }
123
124 /**
125 * It is called when parser exits from grammar rule (case), it perform
126 * validations and update the data model tree.
127 *
128 * @param listener Listener's object
129 * @param ctx context object of the grammar rule
130 */
131 public static void processCaseExit(TreeWalkListener listener,
132 GeneratedYangParser.CaseStatementContext ctx) {
133
134 // Check for stack to be non empty.
135 checkStackIsNotEmpty(listener, MISSING_HOLDER, CASE_DATA, ctx.identifier().getText(), EXIT);
136
137 if (listener.getParsedDataStack().peek() instanceof YangCase) {
138 listener.getParsedDataStack().pop();
139 } else {
140 throw new ParserException(constructListenerErrorMessage(MISSING_CURRENT_HOLDER, CASE_DATA,
141 ctx.identifier().getText(), EXIT));
142 }
143 }
144
145 /**
146 * Validates the cardinality of case sub-statements as per grammar.
147 *
148 * @param ctx context object of the grammar rule
149 */
150 private static void validateSubStatementsCardinality(GeneratedYangParser.CaseStatementContext ctx) {
151
152 validateCardinalityMaxOne(ctx.whenStatement(), WHEN_DATA, CASE_DATA, ctx.identifier().getText());
153 validateCardinalityMaxOne(ctx.statusStatement(), STATUS_DATA, CASE_DATA, ctx.identifier().getText());
154 validateCardinalityMaxOne(ctx.descriptionStatement(), DESCRIPTION_DATA, CASE_DATA, ctx.identifier().getText());
155 validateCardinalityMaxOne(ctx.referenceStatement(), REFERENCE_DATA, CASE_DATA, ctx.identifier().getText());
156 }
157}