Vidyashree Rama
Committed by Gerrit Code Review

YANG augment listener

Change-Id: I11ece665a7627d784f82247d5a33e3453632d0f9
...@@ -22,6 +22,8 @@ import org.onosproject.yangutils.datamodel.exceptions.DataModelException; ...@@ -22,6 +22,8 @@ import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
22 import org.onosproject.yangutils.parser.Parsable; 22 import org.onosproject.yangutils.parser.Parsable;
23 import org.onosproject.yangutils.utils.YangConstructType; 23 import org.onosproject.yangutils.utils.YangConstructType;
24 24
25 +import static org.onosproject.yangutils.datamodel.utils.DataModelUtils.detectCollidingChildUtil;
26 +
25 /*- 27 /*-
26 * Reference RFC 6020. 28 * Reference RFC 6020.
27 * 29 *
...@@ -77,12 +79,12 @@ import org.onosproject.yangutils.utils.YangConstructType; ...@@ -77,12 +79,12 @@ import org.onosproject.yangutils.utils.YangConstructType;
77 * Data model node to maintain information defined in YANG augment. 79 * Data model node to maintain information defined in YANG augment.
78 */ 80 */
79 public class YangAugment extends YangNode 81 public class YangAugment extends YangNode
80 - implements YangLeavesHolder, YangCommonInfo, Parsable { 82 + implements YangLeavesHolder, YangCommonInfo, Parsable, CollisionDetector {
81 83
82 /** 84 /**
83 * Augment target node. 85 * Augment target node.
84 */ 86 */
85 - private String targetNode; 87 + private String name;
86 88
87 /** 89 /**
88 * Description of augment. 90 * Description of augment.
...@@ -100,6 +102,11 @@ public class YangAugment extends YangNode ...@@ -100,6 +102,11 @@ public class YangAugment extends YangNode
100 private List<YangLeafList> listOfLeafList; 102 private List<YangLeafList> listOfLeafList;
101 103
102 /** 104 /**
105 + * List of node identifiers.
106 + */
107 + private List<YangNodeIdentifier> targetNode;
108 +
109 + /**
103 * Reference of the YANG augment. 110 * Reference of the YANG augment.
104 */ 111 */
105 private String reference; 112 private String reference;
...@@ -121,17 +128,17 @@ public class YangAugment extends YangNode ...@@ -121,17 +128,17 @@ public class YangAugment extends YangNode
121 * 128 *
122 * @return the augmented node 129 * @return the augmented node
123 */ 130 */
124 - public String getTargetNode() { 131 + public List<YangNodeIdentifier> getTargetNode() {
125 return targetNode; 132 return targetNode;
126 } 133 }
127 134
128 /** 135 /**
129 * Set the augmented node. 136 * Set the augmented node.
130 * 137 *
131 - * @param targetNode the augmented node 138 + * @param nodeIdentifiers the augmented node
132 */ 139 */
133 - public void setTargetNode(String targetNode) { 140 + public void setTargetNode(List<YangNodeIdentifier> nodeIdentifiers) {
134 - this.targetNode = targetNode; 141 + this.targetNode = nodeIdentifiers;
135 } 142 }
136 143
137 /** 144 /**
...@@ -154,6 +161,20 @@ public class YangAugment extends YangNode ...@@ -154,6 +161,20 @@ public class YangAugment extends YangNode
154 this.description = description; 161 this.description = description;
155 } 162 }
156 163
164 + @Override
165 + public void detectCollidingChild(String identifierName, YangConstructType dataType) throws DataModelException {
166 + // Detect colliding child.
167 + detectCollidingChildUtil(identifierName, dataType, this);
168 + }
169 +
170 + @Override
171 + public void detectSelfCollision(String identifierName, YangConstructType dataType) throws DataModelException {
172 + if (this.getName().equals(identifierName)) {
173 + throw new DataModelException("YANG file error: Duplicate input identifier detected, same as input \""
174 + + this.getName() + "\"");
175 + }
176 + }
177 +
157 /** 178 /**
158 * Get the list of leaves. 179 * Get the list of leaves.
159 * 180 *
...@@ -297,7 +318,7 @@ public class YangAugment extends YangNode ...@@ -297,7 +318,7 @@ public class YangAugment extends YangNode
297 */ 318 */
298 @Override 319 @Override
299 public String getName() { 320 public String getName() {
300 - return targetNode; 321 + return name;
301 } 322 }
302 323
303 /** 324 /**
...@@ -307,7 +328,7 @@ public class YangAugment extends YangNode ...@@ -307,7 +328,7 @@ public class YangAugment extends YangNode
307 */ 328 */
308 @Override 329 @Override
309 public void setName(String name) { 330 public void setName(String name) {
310 - targetNode = name; 331 + this.name = name;
311 332
312 } 333 }
313 334
......
...@@ -25,6 +25,7 @@ import org.onosproject.yangutils.datamodel.YangNode; ...@@ -25,6 +25,7 @@ import org.onosproject.yangutils.datamodel.YangNode;
25 import org.onosproject.yangutils.parser.Parsable; 25 import org.onosproject.yangutils.parser.Parsable;
26 import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangListener; 26 import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangListener;
27 import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser; 27 import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser;
28 +import org.onosproject.yangutils.parser.impl.listeners.AugmentListener;
28 import org.onosproject.yangutils.parser.impl.listeners.BaseFileListener; 29 import org.onosproject.yangutils.parser.impl.listeners.BaseFileListener;
29 import org.onosproject.yangutils.parser.impl.listeners.BelongsToListener; 30 import org.onosproject.yangutils.parser.impl.listeners.BelongsToListener;
30 import org.onosproject.yangutils.parser.impl.listeners.BitListener; 31 import org.onosproject.yangutils.parser.impl.listeners.BitListener;
...@@ -1041,12 +1042,12 @@ public class TreeWalkListener implements GeneratedYangListener { ...@@ -1041,12 +1042,12 @@ public class TreeWalkListener implements GeneratedYangListener {
1041 1042
1042 @Override 1043 @Override
1043 public void enterAugmentStatement(GeneratedYangParser.AugmentStatementContext ctx) { 1044 public void enterAugmentStatement(GeneratedYangParser.AugmentStatementContext ctx) {
1044 - // TODO: implement the method. 1045 + AugmentListener.processAugmentEntry(this, ctx);
1045 } 1046 }
1046 1047
1047 @Override 1048 @Override
1048 public void exitAugmentStatement(GeneratedYangParser.AugmentStatementContext ctx) { 1049 public void exitAugmentStatement(GeneratedYangParser.AugmentStatementContext ctx) {
1049 - // TODO: implement the method. 1050 + AugmentListener.processAugmentExit(this, ctx);
1050 } 1051 }
1051 1052
1052 @Override 1053 @Override
......
1 +/*
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 +
17 +package org.onosproject.yangutils.parser.impl.listeners;
18 +
19 +import java.util.List;
20 +import org.onosproject.yangutils.datamodel.YangAugment;
21 +import org.onosproject.yangutils.datamodel.YangNode;
22 +import org.onosproject.yangutils.datamodel.YangModule;
23 +import org.onosproject.yangutils.datamodel.YangSubModule;
24 +import org.onosproject.yangutils.datamodel.YangNodeIdentifier;
25 +import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
26 +import org.onosproject.yangutils.parser.Parsable;
27 +import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser;
28 +import org.onosproject.yangutils.parser.exceptions.ParserException;
29 +import org.onosproject.yangutils.parser.impl.TreeWalkListener;
30 +
31 +import static org.onosproject.yangutils.datamodel.utils.GeneratedLanguage.JAVA_GENERATION;
32 +import static org.onosproject.yangutils.datamodel.utils.YangDataModelFactory.getYangAugmentNode;
33 +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerCollisionDetector.detectCollidingChildUtil;
34 +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.ENTRY;
35 +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.EXIT;
36 +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction.constructExtendedListenerErrorMessage;
37 +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction.constructListenerErrorMessage;
38 +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.MISSING_CURRENT_HOLDER;
39 +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.MISSING_HOLDER;
40 +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.UNHANDLED_PARSED_DATA;
41 +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.INVALID_HOLDER;
42 +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation.checkStackIsNotEmpty;
43 +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation.validateCardinalityMaxOne;
44 +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation.validateMutuallyExclusiveChilds;
45 +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerUtil.getValidAbsoluteSchemaNodeId;
46 +import static org.onosproject.yangutils.utils.YangConstructType.AUGMENT_DATA;
47 +import static org.onosproject.yangutils.utils.YangConstructType.DATA_DEF_DATA;
48 +import static org.onosproject.yangutils.utils.YangConstructType.STATUS_DATA;
49 +import static org.onosproject.yangutils.utils.YangConstructType.REFERENCE_DATA;
50 +import static org.onosproject.yangutils.utils.YangConstructType.DESCRIPTION_DATA;
51 +import static org.onosproject.yangutils.utils.YangConstructType.WHEN_DATA;
52 +import static org.onosproject.yangutils.utils.YangConstructType.CASE_DATA;
53 +
54 +/*
55 + * Reference: RFC6020 and YANG ANTLR Grammar
56 + *
57 + * ABNF grammar as per RFC6020
58 + * augment-stmt = augment-keyword sep augment-arg-str optsep
59 + * "{" stmtsep
60 + * ;; these stmts can appear in any order
61 + * [when-stmt stmtsep]
62 + * *(if-feature-stmt stmtsep)
63 + * [status-stmt stmtsep]
64 + * [description-stmt stmtsep]
65 + * [reference-stmt stmtsep]
66 + * 1*((data-def-stmt stmtsep) /
67 + * (case-stmt stmtsep))
68 + * "}"
69 + *
70 + * ANTLR grammar rule
71 + * augmentStatement : AUGMENT_KEYWORD augment LEFT_CURLY_BRACE (whenStatement | ifFeatureStatement | statusStatement
72 + * | descriptionStatement | referenceStatement | dataDefStatement | caseStatement)* RIGHT_CURLY_BRACE;
73 + */
74 +
75 +/**
76 + * Implements listener based call back function corresponding to the "augment"
77 + * rule defined in ANTLR grammar file for corresponding ABNF rule in RFC 6020.
78 + */
79 +public final class AugmentListener {
80 +
81 + /**
82 + * Creates a new augment listener.
83 + */
84 + private AugmentListener() {
85 + }
86 +
87 + /**
88 + * It is called when parser receives an input matching the grammar rule
89 + * (augment), performs validation and updates the data model tree.
90 + *
91 + * @param listener listener's object
92 + * @param ctx context object of the grammar rule
93 + */
94 + public static void processAugmentEntry(TreeWalkListener listener,
95 + GeneratedYangParser.AugmentStatementContext ctx) {
96 +
97 + // Check for stack to be non empty.
98 + checkStackIsNotEmpty(listener, MISSING_HOLDER, AUGMENT_DATA, ctx.augment().getText(), ENTRY);
99 +
100 + // Validate augment argument string
101 + List<YangNodeIdentifier> targetNodes = getValidAbsoluteSchemaNodeId(ctx.augment().getText(),
102 + AUGMENT_DATA, ctx);
103 +
104 + // Validate sub statement cardinality.
105 + validateSubStatementsCardinality(ctx);
106 +
107 + // Check for identifier collision
108 + int line = ctx.getStart().getLine();
109 + int charPositionInLine = ctx.getStart().getCharPositionInLine();
110 + detectCollidingChildUtil(listener, line, charPositionInLine, "", AUGMENT_DATA);
111 +
112 + Parsable curData = listener.getParsedDataStack().peek();
113 + if (curData instanceof YangModule || curData instanceof YangSubModule) {
114 +
115 + YangNode curNode = (YangNode) curData;
116 + YangAugment yangAugment = getYangAugmentNode(JAVA_GENERATION);
117 + yangAugment.setTargetNode(targetNodes);
118 + try {
119 + curNode.addChild(yangAugment);
120 + } catch (DataModelException e) {
121 + throw new ParserException(constructExtendedListenerErrorMessage(UNHANDLED_PARSED_DATA,
122 + AUGMENT_DATA, ctx.augment().getText(), ENTRY, e.getMessage()));
123 + }
124 + listener.getParsedDataStack().push(yangAugment);
125 + } else {
126 + throw new ParserException(constructListenerErrorMessage(INVALID_HOLDER, AUGMENT_DATA,
127 + ctx.augment().getText(), ENTRY));
128 + }
129 +
130 + }
131 +
132 + /**
133 + * It is called when parser exits from grammar rule (augment), it perform
134 + * validations and updates the data model tree.
135 + *
136 + * @param listener listener's object
137 + * @param ctx context object of the grammar rule
138 + */
139 + public static void processAugmentExit(TreeWalkListener listener,
140 + GeneratedYangParser.AugmentStatementContext ctx) {
141 +
142 + //Check for stack to be non empty.
143 + checkStackIsNotEmpty(listener, MISSING_HOLDER, AUGMENT_DATA, ctx.augment().getText(), EXIT);
144 +
145 + if (!(listener.getParsedDataStack().peek() instanceof YangAugment)) {
146 + throw new ParserException(constructListenerErrorMessage(MISSING_CURRENT_HOLDER, AUGMENT_DATA,
147 + ctx.augment().getText(), EXIT));
148 + }
149 + listener.getParsedDataStack().pop();
150 + }
151 +
152 + /**
153 + * Validates the cardinality of augment sub-statements as per grammar.
154 + *
155 + * @param ctx context object of the grammar rule
156 + */
157 + private static void validateSubStatementsCardinality(GeneratedYangParser.AugmentStatementContext ctx) {
158 +
159 + validateCardinalityMaxOne(ctx.statusStatement(), STATUS_DATA, AUGMENT_DATA, ctx.augment().getText());
160 + validateCardinalityMaxOne(ctx.descriptionStatement(), DESCRIPTION_DATA, AUGMENT_DATA, ctx.augment().getText());
161 + validateCardinalityMaxOne(ctx.referenceStatement(), REFERENCE_DATA, AUGMENT_DATA, ctx.augment().getText());
162 + validateCardinalityMaxOne(ctx.whenStatement(), WHEN_DATA, AUGMENT_DATA, ctx.augment().getText());
163 + validateMutuallyExclusiveChilds(ctx.dataDefStatement(), DATA_DEF_DATA, ctx.caseStatement(),
164 + CASE_DATA, AUGMENT_DATA, ctx.augment().getText());
165 + }
166 +}
...@@ -16,13 +16,14 @@ ...@@ -16,13 +16,14 @@
16 16
17 package org.onosproject.yangutils.parser.impl.parserutils; 17 package org.onosproject.yangutils.parser.impl.parserutils;
18 18
19 -import org.antlr.v4.runtime.ParserRuleContext;
20 -
21 import java.text.ParseException; 19 import java.text.ParseException;
22 import java.text.SimpleDateFormat; 20 import java.text.SimpleDateFormat;
23 import java.util.Calendar; 21 import java.util.Calendar;
22 +import java.util.LinkedList;
23 +import java.util.List;
24 import java.util.regex.Pattern; 24 import java.util.regex.Pattern;
25 25
26 +import org.antlr.v4.runtime.ParserRuleContext;
26 import org.onosproject.yangutils.datamodel.YangNodeIdentifier; 27 import org.onosproject.yangutils.datamodel.YangNodeIdentifier;
27 import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser; 28 import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser;
28 import org.onosproject.yangutils.utils.YangConstructType; 29 import org.onosproject.yangutils.utils.YangConstructType;
...@@ -45,6 +46,7 @@ public final class ListenerUtil { ...@@ -45,6 +46,7 @@ public final class ListenerUtil {
45 private static final String SLASH = "/"; 46 private static final String SLASH = "/";
46 private static final String SPACE = " "; 47 private static final String SPACE = " ";
47 private static final String COLON = ":"; 48 private static final String COLON = ":";
49 + private static final String CARET = "^";
48 50
49 /** 51 /**
50 * Creates a new listener util. 52 * Creates a new listener util.
...@@ -237,4 +239,36 @@ public final class ListenerUtil { ...@@ -237,4 +239,36 @@ public final class ListenerUtil {
237 throw parserException; 239 throw parserException;
238 } 240 }
239 } 241 }
242 +
243 + /**
244 + * Checks and return valid absolute schema node id.
245 + *
246 + * @param argumentString string from yang file
247 + * @param yangConstructType yang construct for creating error message
248 + * @param ctx yang construct's context to get the line number and character position
249 + * @return target nodes list of absolute schema node id
250 + */
251 + public static List<YangNodeIdentifier> getValidAbsoluteSchemaNodeId(String argumentString,
252 + YangConstructType yangConstructType, ParserRuleContext ctx) {
253 +
254 + List<YangNodeIdentifier> targetNodes = new LinkedList<>();
255 + YangNodeIdentifier yangNodeIdentifier;
256 + String tmpSchemaNodeId = removeQuotesAndHandleConcat(argumentString);
257 +
258 + // absolute-schema-nodeid = 1*("/" node-identifier)
259 + if (!tmpSchemaNodeId.startsWith(SLASH)) {
260 + ParserException parserException = new ParserException("YANG file error : " +
261 + YangConstructType.getYangConstructType(yangConstructType) + " name " + argumentString +
262 + "is not valid");
263 + parserException.setLine(ctx.getStart().getLine());
264 + parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
265 + throw parserException;
266 + }
267 + String[] tmpData = tmpSchemaNodeId.replaceFirst(CARET + SLASH, EMPTY_STRING).split(SLASH);
268 + for (String nodeIdentifiers : tmpData) {
269 + yangNodeIdentifier = getValidNodeIdentifier(nodeIdentifiers, yangConstructType, ctx);
270 + targetNodes.add(yangNodeIdentifier);
271 + }
272 + return targetNodes;
273 + }
240 } 274 }
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -1055,7 +1055,7 @@ package org.onosproject.yangutils.parser.antlrgencode; ...@@ -1055,7 +1055,7 @@ package org.onosproject.yangutils.parser.antlrgencode;
1055 * "}" 1055 * "}"
1056 * TODO : 0..1 occurance to be checked in listener 1056 * TODO : 0..1 occurance to be checked in listener
1057 */ 1057 */
1058 - augmentStatement : AUGMENT_KEYWORD string LEFT_CURLY_BRACE (whenStatement | ifFeatureStatement | statusStatement 1058 + augmentStatement : AUGMENT_KEYWORD augment LEFT_CURLY_BRACE (whenStatement | ifFeatureStatement | statusStatement
1059 | descriptionStatement | referenceStatement | dataDefStatement | caseStatement)* RIGHT_CURLY_BRACE; 1059 | descriptionStatement | referenceStatement | dataDefStatement | caseStatement)* RIGHT_CURLY_BRACE;
1060 1060
1061 /** 1061 /**
......
1 +/*
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 +
17 +package org.onosproject.yangutils.parser.impl.listeners;
18 +
19 +import java.io.IOException;
20 +import java.util.ListIterator;
21 +
22 +import org.junit.Test;
23 +import org.onosproject.yangutils.datamodel.YangNode;
24 +import org.onosproject.yangutils.datamodel.YangModule;
25 +import org.onosproject.yangutils.datamodel.YangAugment;
26 +import org.onosproject.yangutils.datamodel.YangLeaf;
27 +import org.onosproject.yangutils.datamodel.YangNodeIdentifier;
28 +import org.onosproject.yangutils.datamodel.YangDataTypes;
29 +import org.onosproject.yangutils.datamodel.YangNodeType;
30 +import org.onosproject.yangutils.parser.exceptions.ParserException;
31 +import org.onosproject.yangutils.parser.impl.YangUtilsParserManager;
32 +
33 +import static org.hamcrest.core.Is.is;
34 +import static org.junit.Assert.assertThat;
35 +
36 +/**
37 + * Test cases for testing augment listener functionality.
38 + */
39 +public class AugmentListenerTest {
40 +
41 + private final YangUtilsParserManager manager = new YangUtilsParserManager();
42 +
43 + /**
44 + * Checks valid augment statement.
45 + */
46 + @Test
47 + public void processValidAugmentStatement() throws IOException, ParserException {
48 +
49 + YangNode node = manager.getDataModel("src/test/resources/ValidAugmentStatement.yang");
50 +
51 + assertThat((node instanceof YangModule), is(true));
52 + assertThat(node.getNodeType(), is(YangNodeType.MODULE_NODE));
53 + YangModule yangNode = (YangModule) node;
54 + assertThat(yangNode.getName(), is("Test"));
55 +
56 + YangAugment yangAugment = (YangAugment) yangNode.getChild();
57 + if (yangAugment.getTargetNode().isEmpty()) {
58 + System.out.println("list is empty");
59 + }
60 + ListIterator<YangNodeIdentifier> nodeIdentifierIterator = yangAugment.getTargetNode().listIterator();
61 + YangNodeIdentifier yangNodeIdentifier = nodeIdentifierIterator.next();
62 + assertThat(yangNodeIdentifier.getPrefix(), is("if"));
63 + assertThat(yangNodeIdentifier.getName(), is("interfaces"));
64 +
65 + ListIterator<YangLeaf> leafIterator = yangAugment.getListOfLeaf().listIterator();
66 + YangLeaf leafInfo = leafIterator.next();
67 +
68 + assertThat(leafInfo.getLeafName(), is("ds0ChannelNumber"));
69 + assertThat(leafInfo.getDataType().getDataTypeName(), is("ChannelNumber"));
70 + assertThat(leafInfo.getDataType().getDataType(), is(YangDataTypes.DERIVED));
71 + }
72 +}
1 +module Test {
2 + yang-version 1;
3 + namespace http://example.com/schema/ds0;
4 + prefix On;
5 +
6 + import interface-module {
7 + prefix "if";
8 + }
9 + augment "/if:interfaces/if:ifEntry" {
10 + when "if:ifType='ds0'";
11 + leaf ds0ChannelNumber {
12 + type P:ChannelNumber;
13 + }
14 + }
15 +}