blob: f580da9c03cff18d8108012190b02ec9371c2bf6 [file] [log] [blame]
Vidyashree Ramad3221322016-03-04 19:08:35 +05301/*
Brian O'Connor0f7908b2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Vidyashree Ramad3221322016-03-04 19:08:35 +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.parserutils;
18
Bharat saraswale304c252016-08-16 20:56:20 +053019import java.text.ParseException;
20import java.text.SimpleDateFormat;
21import java.util.ArrayList;
22import java.util.Date;
23import java.util.HashMap;
24import java.util.Iterator;
25import java.util.LinkedList;
26import java.util.List;
27import java.util.regex.Pattern;
28
janani bebb143d2016-07-14 19:35:22 +053029import org.antlr.v4.runtime.ParserRuleContext;
Bharat saraswale304c252016-08-16 20:56:20 +053030import org.apache.commons.logging.Log;
31import org.apache.commons.logging.LogFactory;
janani bebb143d2016-07-14 19:35:22 +053032import org.onosproject.yangutils.datamodel.YangAtomicPath;
33import org.onosproject.yangutils.datamodel.YangImport;
34import org.onosproject.yangutils.datamodel.YangLeaf;
35import org.onosproject.yangutils.datamodel.YangLeafRef;
36import org.onosproject.yangutils.datamodel.YangLeavesHolder;
37import org.onosproject.yangutils.datamodel.YangList;
38import org.onosproject.yangutils.datamodel.YangModule;
39import org.onosproject.yangutils.datamodel.YangNode;
40import org.onosproject.yangutils.datamodel.YangNodeIdentifier;
41import org.onosproject.yangutils.datamodel.YangPathPredicate;
42import org.onosproject.yangutils.datamodel.YangReferenceResolver;
43import org.onosproject.yangutils.datamodel.YangRelativePath;
44import org.onosproject.yangutils.datamodel.YangSubModule;
45import org.onosproject.yangutils.datamodel.utils.YangConstructType;
46import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser;
47import org.onosproject.yangutils.parser.exceptions.ParserException;
48
janani b0e4e8ae2016-07-13 21:06:41 +053049import static org.onosproject.yangutils.datamodel.YangPathArgType.ABSOLUTE_PATH;
50import static org.onosproject.yangutils.datamodel.YangPathArgType.RELATIVE_PATH;
51import static org.onosproject.yangutils.datamodel.YangPathOperator.EQUALTO;
Bharat saraswale304c252016-08-16 20:56:20 +053052import static org.onosproject.yangutils.datamodel.utils.YangConstructType.getYangConstructType;
Vidyashree Ramab6248172016-05-17 16:16:15 +053053import static org.onosproject.yangutils.utils.UtilConstants.ADD;
janani b0e4e8ae2016-07-13 21:06:41 +053054import static org.onosproject.yangutils.utils.UtilConstants.ANCESTOR_ACCESSOR;
55import static org.onosproject.yangutils.utils.UtilConstants.ANCESTOR_ACCESSOR_IN_PATH;
Vidyashree Ramab6248172016-05-17 16:16:15 +053056import static org.onosproject.yangutils.utils.UtilConstants.CARET;
janani b0e4e8ae2016-07-13 21:06:41 +053057import static org.onosproject.yangutils.utils.UtilConstants.CHAR_OF_CLOSE_SQUARE_BRACKET;
58import static org.onosproject.yangutils.utils.UtilConstants.CHAR_OF_OPEN_SQUARE_BRACKET;
59import static org.onosproject.yangutils.utils.UtilConstants.CHAR_OF_SLASH;
60import static org.onosproject.yangutils.utils.UtilConstants.CLOSE_PARENTHESIS;
Vidyashree Rama13b4c552016-06-20 15:12:43 +053061import static org.onosproject.yangutils.utils.UtilConstants.COLON;
janani b0e4e8ae2016-07-13 21:06:41 +053062import static org.onosproject.yangutils.utils.UtilConstants.CURRENT;
Vidyashree Ramab6248172016-05-17 16:16:15 +053063import static org.onosproject.yangutils.utils.UtilConstants.EMPTY_STRING;
Vidyashree Ramab6248172016-05-17 16:16:15 +053064import static org.onosproject.yangutils.utils.UtilConstants.FALSE;
janani b0e4e8ae2016-07-13 21:06:41 +053065import static org.onosproject.yangutils.utils.UtilConstants.OPEN_SQUARE_BRACKET;
Vidyashree Rama13b4c552016-06-20 15:12:43 +053066import static org.onosproject.yangutils.utils.UtilConstants.QUOTES;
67import static org.onosproject.yangutils.utils.UtilConstants.SLASH;
janani b0e4e8ae2016-07-13 21:06:41 +053068import static org.onosproject.yangutils.utils.UtilConstants.SLASH_FOR_STRING;
Vidyashree Rama13b4c552016-06-20 15:12:43 +053069import static org.onosproject.yangutils.utils.UtilConstants.TRUE;
70import static org.onosproject.yangutils.utils.UtilConstants.YANG_FILE_ERROR;
Vidyashree Ramab6248172016-05-17 16:16:15 +053071
Vidyashree Ramad3221322016-03-04 19:08:35 +053072/**
Bharat saraswal63f26fb2016-04-05 15:13:44 +053073 * Represents an utility for listener.
Vidyashree Ramad3221322016-03-04 19:08:35 +053074 */
75public final class ListenerUtil {
Bharat saraswal63f26fb2016-04-05 15:13:44 +053076
Vidyashree Ramad3221322016-03-04 19:08:35 +053077 private static final Pattern IDENTIFIER_PATTERN = Pattern.compile("[a-zA-Z_][a-zA-Z0-9_.-]*");
Vidyashree Rama1ae576c2016-05-09 11:45:05 +053078 private static final String DATE_PATTERN = "[0-9]{4}-([0-9]{2}|[0-9])-([0-9]{2}|[0-9])";
Vidyashree Ramae68bb192016-03-15 10:18:25 +053079 private static final String NON_NEGATIVE_INTEGER_PATTERN = "[0-9]+";
Vidyashree Ramab6248172016-05-17 16:16:15 +053080 private static final Pattern INTEGER_PATTERN = Pattern.compile("[-][0-9]+|[0-9]+");
janani b0e4e8ae2016-07-13 21:06:41 +053081 private static final Pattern PATH_PREDICATE_PATTERN = Pattern.compile("\\[(.*?)\\]");
Vidyashree Rama5daea742016-05-20 16:29:25 +053082 private static final String XML = "xml";
Vidyashree Ramae68bb192016-03-15 10:18:25 +053083 private static final String ONE = "1";
Vidyashree Ramad3221322016-03-04 19:08:35 +053084 private static final int IDENTIFIER_LENGTH = 64;
janani ba3027492016-03-24 12:43:48 +053085 private static final String DATE_FORMAT = "yyyy-MM-dd";
Bharat saraswale304c252016-08-16 20:56:20 +053086 private static final Log log = LogFactory.getLog(ListenerUtil.class);
Vidyashree Ramad3221322016-03-04 19:08:35 +053087
88 /**
89 * Creates a new listener util.
90 */
91 private ListenerUtil() {
92 }
93
94 /**
95 * Removes doubles quotes and concatenates if string has plus symbol.
96 *
97 * @param yangStringData string from yang file
98 * @return concatenated string after removing double quotes
99 */
100 public static String removeQuotesAndHandleConcat(String yangStringData) {
101
janani ba3027492016-03-24 12:43:48 +0530102 yangStringData = yangStringData.replace("\"", EMPTY_STRING);
Vidyashree Ramab6248172016-05-17 16:16:15 +0530103 String[] tmpData = yangStringData.split(Pattern.quote(ADD));
Vidyashree Ramad3221322016-03-04 19:08:35 +0530104 StringBuilder builder = new StringBuilder();
105 for (String yangString : tmpData) {
106 builder.append(yangString);
107 }
108 return builder.toString();
109 }
110
111 /**
112 * Validates identifier and returns concatenated string if string contains plus symbol.
113 *
janani bebb143d2016-07-14 19:35:22 +0530114 * @param identifier string from yang file
Vidyashree Ramad3221322016-03-04 19:08:35 +0530115 * @param yangConstruct yang construct for creating error message
janani bebb143d2016-07-14 19:35:22 +0530116 * @param ctx yang construct's context to get the line number and character position
Vidyashree Ramad3221322016-03-04 19:08:35 +0530117 * @return concatenated string after removing double quotes
118 */
119 public static String getValidIdentifier(String identifier, YangConstructType yangConstruct, ParserRuleContext ctx) {
120
121 String identifierString = removeQuotesAndHandleConcat(identifier);
122 ParserException parserException;
123
124 if (identifierString.length() > IDENTIFIER_LENGTH) {
125 parserException = new ParserException("YANG file error : " +
Bharat saraswale304c252016-08-16 20:56:20 +0530126 getYangConstructType(yangConstruct) + " name " + identifierString + " is " +
Vidyashree Ramad3221322016-03-04 19:08:35 +0530127 "greater than 64 characters.");
128 } else if (!IDENTIFIER_PATTERN.matcher(identifierString).matches()) {
129 parserException = new ParserException("YANG file error : " +
Bharat saraswale304c252016-08-16 20:56:20 +0530130 getYangConstructType(yangConstruct) + " name " + identifierString + " is not " +
Vidyashree Ramad3221322016-03-04 19:08:35 +0530131 "valid.");
Vidyashree Rama5daea742016-05-20 16:29:25 +0530132 } else if (identifierString.toLowerCase().startsWith(XML)) {
133 parserException = new ParserException("YANG file error : " +
Bharat saraswale304c252016-08-16 20:56:20 +0530134 getYangConstructType(yangConstruct) + " identifier " + identifierString +
Vidyashree Rama5daea742016-05-20 16:29:25 +0530135 " must not start with (('X'|'x') ('M'|'m') ('L'|'l')).");
Vidyashree Ramad3221322016-03-04 19:08:35 +0530136 } else {
137 return identifierString;
138 }
139
140 parserException.setLine(ctx.getStart().getLine());
141 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
142 throw parserException;
143 }
144
145 /**
janani b0e4e8ae2016-07-13 21:06:41 +0530146 * Validates identifier and returns concatenated string if string contains plus symbol.
147 *
janani bebb143d2016-07-14 19:35:22 +0530148 * @param identifier string from yang file
janani b0e4e8ae2016-07-13 21:06:41 +0530149 * @param yangConstruct yang construct for creating error message
janani bebb143d2016-07-14 19:35:22 +0530150 * @param ctx yang construct's context to get the line number and character position
151 * @param yangLeafRef instance of leafref where the path argument has to be set
janani b0e4e8ae2016-07-13 21:06:41 +0530152 * @return concatenated string after removing double quotes
153 */
154 public static String getValidIdentifierForLeafref(String identifier, YangConstructType yangConstruct,
janani bebb143d2016-07-14 19:35:22 +0530155 ParserRuleContext ctx, YangLeafRef yangLeafRef) {
janani b0e4e8ae2016-07-13 21:06:41 +0530156
157 String identifierString = removeQuotesAndHandleConcat(identifier);
158 ParserException parserException;
159
160 if (identifierString.length() > IDENTIFIER_LENGTH) {
161 parserException = new ParserException("YANG file error : " + " identifier " + identifierString + " in " +
Bharat saraswale304c252016-08-16 20:56:20 +0530162 getYangConstructType(yangConstruct) + " " + yangLeafRef.getPath() + " is " +
janani b0e4e8ae2016-07-13 21:06:41 +0530163 "greater than 64 characters.");
164 } else if (!IDENTIFIER_PATTERN.matcher(identifierString).matches()) {
165 parserException = new ParserException("YANG file error : " + " identifier " + identifierString + " in " +
Bharat saraswale304c252016-08-16 20:56:20 +0530166 getYangConstructType(yangConstruct) + " " + yangLeafRef.getPath() + " is not " +
janani b0e4e8ae2016-07-13 21:06:41 +0530167 "valid.");
168 } else if (identifierString.toLowerCase().startsWith(XML)) {
169 parserException = new ParserException("YANG file error : " + " identifier " + identifierString + " in " +
Bharat saraswale304c252016-08-16 20:56:20 +0530170 getYangConstructType(yangConstruct) + " " + yangLeafRef.getPath() +
janani b0e4e8ae2016-07-13 21:06:41 +0530171 " must not start with (('X'|'x') ('M'|'m') ('L'|'l')).");
172 } else {
173 return identifierString;
174 }
175
176 parserException.setLine(ctx.getStart().getLine());
177 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
178 throw parserException;
179 }
180
181 /**
Vidyashree Ramad3221322016-03-04 19:08:35 +0530182 * Validates the revision date.
183 *
184 * @param dateToValidate input revision date
185 * @return validation result, true for success, false for failure
186 */
187 public static boolean isDateValid(String dateToValidate) {
Vidyashree Rama1ae576c2016-05-09 11:45:05 +0530188 if (dateToValidate == null || !dateToValidate.matches(DATE_PATTERN)) {
Vidyashree Ramad3221322016-03-04 19:08:35 +0530189 return false;
190 }
191
janani ba3027492016-03-24 12:43:48 +0530192 SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
Vidyashree Ramad3221322016-03-04 19:08:35 +0530193 sdf.setLenient(false);
194
195 try {
196 //if not valid, it will throw ParseException
197 sdf.parse(dateToValidate);
198 } catch (ParseException e) {
199 return false;
200 }
201
202 return true;
203 }
Vidyashree Ramae68bb192016-03-15 10:18:25 +0530204
205 /**
206 * Validates YANG version.
207 *
208 * @param ctx version context object of the grammar rule
209 * @return valid version
210 */
211 public static byte getValidVersion(GeneratedYangParser.YangVersionStatementContext ctx) {
212
213 String value = removeQuotesAndHandleConcat(ctx.version().getText());
214 if (!value.equals(ONE)) {
215 ParserException parserException = new ParserException("YANG file error: Input version not supported");
216 parserException.setLine(ctx.getStart().getLine());
217 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
218 throw parserException;
219 }
220
221 return Byte.valueOf(value);
222 }
223
224 /**
225 * Validates non negative integer value.
226 *
janani bebb143d2016-07-14 19:35:22 +0530227 * @param integerValue integer to be validated
Vidyashree Ramae68bb192016-03-15 10:18:25 +0530228 * @param yangConstruct yang construct for creating error message
janani bebb143d2016-07-14 19:35:22 +0530229 * @param ctx context object of the grammar rule
Vidyashree Ramae68bb192016-03-15 10:18:25 +0530230 * @return valid non negative integer value
231 */
232 public static int getValidNonNegativeIntegerValue(String integerValue, YangConstructType yangConstruct,
janani bebb143d2016-07-14 19:35:22 +0530233 ParserRuleContext ctx) {
Vidyashree Ramae68bb192016-03-15 10:18:25 +0530234
235 String value = removeQuotesAndHandleConcat(integerValue);
236 if (!value.matches(NON_NEGATIVE_INTEGER_PATTERN)) {
237 ParserException parserException = new ParserException("YANG file error : " +
Bharat saraswale304c252016-08-16 20:56:20 +0530238 getYangConstructType(yangConstruct) + " value " + value + " is not " +
Vidyashree Ramae68bb192016-03-15 10:18:25 +0530239 "valid.");
240 parserException.setLine(ctx.getStart().getLine());
241 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
242 throw parserException;
243 }
244
Vidyashree Rama5daea742016-05-20 16:29:25 +0530245 int valueInInteger;
246 try {
247 valueInInteger = Integer.parseInt(value);
248 } catch (NumberFormatException e) {
249 ParserException parserException = new ParserException("YANG file error : " +
Bharat saraswale304c252016-08-16 20:56:20 +0530250 getYangConstructType(yangConstruct) + " value " + value + " is not " +
Vidyashree Rama5daea742016-05-20 16:29:25 +0530251 "valid.");
252 parserException.setLine(ctx.getStart().getLine());
253 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
254 throw parserException;
255 }
256 return valueInInteger;
Vidyashree Ramae68bb192016-03-15 10:18:25 +0530257 }
258
259 /**
Vidyashree Ramab6248172016-05-17 16:16:15 +0530260 * Validates integer value.
261 *
janani bebb143d2016-07-14 19:35:22 +0530262 * @param integerValue integer to be validated
Vidyashree Ramab6248172016-05-17 16:16:15 +0530263 * @param yangConstruct yang construct for creating error message
janani bebb143d2016-07-14 19:35:22 +0530264 * @param ctx context object of the grammar rule
Vidyashree Ramab6248172016-05-17 16:16:15 +0530265 * @return valid integer value
266 */
267 public static int getValidIntegerValue(String integerValue, YangConstructType yangConstruct,
janani bebb143d2016-07-14 19:35:22 +0530268 ParserRuleContext ctx) {
Vidyashree Ramab6248172016-05-17 16:16:15 +0530269
270 String value = removeQuotesAndHandleConcat(integerValue);
271 if (!INTEGER_PATTERN.matcher(value).matches()) {
272 ParserException parserException = new ParserException("YANG file error : " +
Bharat saraswale304c252016-08-16 20:56:20 +0530273 getYangConstructType(yangConstruct) + " value " + value + " is not " +
Vidyashree Ramab6248172016-05-17 16:16:15 +0530274 "valid.");
275 parserException.setLine(ctx.getStart().getLine());
276 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
277 throw parserException;
278 }
279
280 int valueInInteger;
281 try {
282 valueInInteger = Integer.parseInt(value);
283 } catch (NumberFormatException e) {
284 ParserException parserException = new ParserException("YANG file error : " +
Bharat saraswale304c252016-08-16 20:56:20 +0530285 getYangConstructType(yangConstruct) + " value " + value + " is not " +
Vidyashree Ramab6248172016-05-17 16:16:15 +0530286 "valid.");
287 parserException.setLine(ctx.getStart().getLine());
288 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
289 throw parserException;
290 }
291 return valueInInteger;
292 }
293
294 /**
Vidyashree Ramae68bb192016-03-15 10:18:25 +0530295 * Validates boolean value.
296 *
janani bebb143d2016-07-14 19:35:22 +0530297 * @param booleanValue value to be validated
Vidyashree Ramae68bb192016-03-15 10:18:25 +0530298 * @param yangConstruct yang construct for creating error message
janani bebb143d2016-07-14 19:35:22 +0530299 * @param ctx context object of the grammar rule
Vidyashree Ramae68bb192016-03-15 10:18:25 +0530300 * @return boolean value either true or false
301 */
302 public static boolean getValidBooleanValue(String booleanValue, YangConstructType yangConstruct,
janani bebb143d2016-07-14 19:35:22 +0530303 ParserRuleContext ctx) {
Vidyashree Ramae68bb192016-03-15 10:18:25 +0530304
305 String value = removeQuotesAndHandleConcat(booleanValue);
Vidyashree Ramab6248172016-05-17 16:16:15 +0530306 if (value.equals(TRUE)) {
Vidyashree Ramae68bb192016-03-15 10:18:25 +0530307 return true;
Vidyashree Ramab6248172016-05-17 16:16:15 +0530308 } else if (value.equals(FALSE)) {
Vidyashree Ramae68bb192016-03-15 10:18:25 +0530309 return false;
310 } else {
311 ParserException parserException = new ParserException("YANG file error : " +
Bharat saraswale304c252016-08-16 20:56:20 +0530312 getYangConstructType(yangConstruct) + " value " + value + " is not " +
Vidyashree Ramae68bb192016-03-15 10:18:25 +0530313 "valid.");
314 parserException.setLine(ctx.getStart().getLine());
315 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
316 throw parserException;
317 }
318 }
janani ba3027492016-03-24 12:43:48 +0530319
320 /**
Vidyashree Rama13b4c552016-06-20 15:12:43 +0530321 * Returns current date and makes it in usable format for revision.
janani ba3027492016-03-24 12:43:48 +0530322 *
323 * @return usable current date format for revision
324 */
Vidyashree Rama13b4c552016-06-20 15:12:43 +0530325 public static Date getCurrentDateForRevision() {
janani ba3027492016-03-24 12:43:48 +0530326
janani ba3027492016-03-24 12:43:48 +0530327 SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
Vidyashree Rama13b4c552016-06-20 15:12:43 +0530328
329 Date date = new Date();
330 String dateInString = dateFormat.format(date);
331 try {
332 //if not valid, it will throw ParseException
333 Date now = dateFormat.parse(dateInString);
334 return date;
335 } catch (ParseException e) {
336 ParserException parserException = new ParserException("YANG file error: Input date is not correct");
337 throw parserException;
338 }
janani ba3027492016-03-24 12:43:48 +0530339 }
Gaurav Agrawalf6ccc972016-03-25 11:25:36 +0530340
341 /**
342 * Checks and return valid node identifier.
343 *
344 * @param nodeIdentifierString string from yang file
janani bebb143d2016-07-14 19:35:22 +0530345 * @param yangConstruct yang construct for creating error message
346 * @param ctx yang construct's context to get the line number and character position
Gaurav Agrawalf6ccc972016-03-25 11:25:36 +0530347 * @return valid node identifier
348 */
Vinod Kumar Sf677daf2016-04-15 18:08:57 +0530349 public static YangNodeIdentifier getValidNodeIdentifier(String nodeIdentifierString,
janani bebb143d2016-07-14 19:35:22 +0530350 YangConstructType yangConstruct, ParserRuleContext ctx) {
Gaurav Agrawalf6ccc972016-03-25 11:25:36 +0530351 String tmpIdentifierString = removeQuotesAndHandleConcat(nodeIdentifierString);
352 String[] tmpData = tmpIdentifierString.split(Pattern.quote(COLON));
353 if (tmpData.length == 1) {
354 YangNodeIdentifier nodeIdentifier = new YangNodeIdentifier();
355 nodeIdentifier.setName(getValidIdentifier(tmpData[0], yangConstruct, ctx));
356 return nodeIdentifier;
357 } else if (tmpData.length == 2) {
358 YangNodeIdentifier nodeIdentifier = new YangNodeIdentifier();
359 nodeIdentifier.setPrefix(getValidIdentifier(tmpData[0], yangConstruct, ctx));
360 nodeIdentifier.setName(getValidIdentifier(tmpData[1], yangConstruct, ctx));
361 return nodeIdentifier;
362 } else {
363 ParserException parserException = new ParserException("YANG file error : " +
Bharat saraswale304c252016-08-16 20:56:20 +0530364 getYangConstructType(yangConstruct) + " name " + nodeIdentifierString +
Gaurav Agrawalf6ccc972016-03-25 11:25:36 +0530365 " is not valid.");
366 parserException.setLine(ctx.getStart().getLine());
367 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
368 throw parserException;
369 }
370 }
Vidyashree Ramae2bd9ba2016-03-29 14:37:02 +0530371
372 /**
janani b0e4e8ae2016-07-13 21:06:41 +0530373 * Checks and return valid node identifier specific to nodes in leafref path.
374 *
375 * @param nodeIdentifierString string from yang file
janani bebb143d2016-07-14 19:35:22 +0530376 * @param yangConstruct yang construct for creating error message
377 * @param ctx yang construct's context to get the line number and character position
378 * @param yangLeafRef instance of leafref where the path argument has to be set
janani b0e4e8ae2016-07-13 21:06:41 +0530379 * @return valid node identifier
380 */
381 public static YangNodeIdentifier getValidNodeIdentifierForLeafref(String nodeIdentifierString,
janani bebb143d2016-07-14 19:35:22 +0530382 YangConstructType yangConstruct,
383 ParserRuleContext ctx, YangLeafRef yangLeafRef) {
janani b0e4e8ae2016-07-13 21:06:41 +0530384
385 String tmpIdentifierString = removeQuotesAndHandleConcat(nodeIdentifierString);
386 String[] tmpData = tmpIdentifierString.split(Pattern.quote(COLON));
387 if (tmpData.length == 1) {
388 YangNodeIdentifier nodeIdentifier = new YangNodeIdentifier();
janani b0e4e8ae2016-07-13 21:06:41 +0530389 nodeIdentifier.setName(getValidIdentifierForLeafref(tmpData[0], yangConstruct, ctx, yangLeafRef));
390 return nodeIdentifier;
391 } else if (tmpData.length == 2) {
392 YangNodeIdentifier nodeIdentifier = new YangNodeIdentifier();
393 nodeIdentifier.setPrefix(getValidIdentifierForLeafref(tmpData[0], yangConstruct, ctx, yangLeafRef));
394 nodeIdentifier.setName(getValidIdentifierForLeafref(tmpData[1], yangConstruct, ctx, yangLeafRef));
395 return nodeIdentifier;
396 } else {
397 ParserException parserException = new ParserException("YANG file error : " +
Bharat saraswale304c252016-08-16 20:56:20 +0530398 getYangConstructType(yangConstruct) + yangLeafRef.getPath() +
janani b0e4e8ae2016-07-13 21:06:41 +0530399 " is not valid.");
400 parserException.setLine(ctx.getStart().getLine());
401 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
402 throw parserException;
403 }
404 }
405
406 /**
407 * Validates the path argument. It can be either absolute or relative path.
408 *
janani bebb143d2016-07-14 19:35:22 +0530409 * @param pathString the path string from the path type
janani b0e4e8ae2016-07-13 21:06:41 +0530410 * @param yangConstruct yang construct for creating error message
janani bebb143d2016-07-14 19:35:22 +0530411 * @param ctx yang construct's context to get the line number and character position
412 * @param yangLeafRef instance of leafref where the path argument has to be set
janani b0e4e8ae2016-07-13 21:06:41 +0530413 */
414 public static void validatePathArgument(String pathString, YangConstructType yangConstruct,
janani bebb143d2016-07-14 19:35:22 +0530415 ParserRuleContext ctx, YangLeafRef yangLeafRef) {
janani b0e4e8ae2016-07-13 21:06:41 +0530416
417 String completePathString = removeQuotesAndHandleConcat(pathString);
418 yangLeafRef.setPath(completePathString);
419 if (completePathString.startsWith(SLASH)) {
420 yangLeafRef.setPathType(ABSOLUTE_PATH);
421 List<YangAtomicPath> yangAtomicPathListList = validateAbsolutePath(completePathString, yangConstruct, ctx,
422 yangLeafRef);
janani bebb143d2016-07-14 19:35:22 +0530423 validatePrefixAndYangNode(yangAtomicPathListList, yangLeafRef);
janani b0e4e8ae2016-07-13 21:06:41 +0530424 yangLeafRef.setAtomicPath(yangAtomicPathListList);
425 } else if (completePathString.startsWith(ANCESTOR_ACCESSOR)) {
426 yangLeafRef.setPathType(RELATIVE_PATH);
427 validateRelativePath(completePathString, yangConstruct, ctx, yangLeafRef);
428 } else {
429 ParserException parserException = new ParserException("YANG file error : " +
Bharat saraswale304c252016-08-16 20:56:20 +0530430 getYangConstructType(yangConstruct) + yangLeafRef.getPath() +
janani b0e4e8ae2016-07-13 21:06:41 +0530431 " does not follow valid path syntax");
432 parserException.setLine(ctx.getStart().getLine());
433 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
434 throw parserException;
435 }
436 }
437
438 /**
janani bebb143d2016-07-14 19:35:22 +0530439 * Validates the prefixes in the leafref and assigns them to the respective imported name in map.
440 *
441 * @param yangAtomicPathList list of atomic poth
Bharat saraswale304c252016-08-16 20:56:20 +0530442 * @param yangLeafRef instance YANG leafref
janani bebb143d2016-07-14 19:35:22 +0530443 */
444 private static void validatePrefixAndYangNode(List<YangAtomicPath> yangAtomicPathList, YangLeafRef yangLeafRef) {
445 Iterator<YangAtomicPath> yangAtomicPathIterator = yangAtomicPathList.listIterator();
446 while (yangAtomicPathIterator.hasNext()) {
447 YangAtomicPath atomicPath = yangAtomicPathIterator.next();
448 String prefix = atomicPath.getNodeIdentifier().getPrefix();
449 YangNode parentNodeOfLeafref = yangLeafRef.getParentNodeOfLeafref();
450 YangNode moduleOrSubModule = getModuleOrSubmoduleInFileOfTheCurrentNode(parentNodeOfLeafref);
451 YangModule moduleNode = null;
452 if (moduleOrSubModule instanceof YangModule) {
453 moduleNode = (YangModule) moduleOrSubModule;
454 }
455 if (moduleNode != null) {
456 updatePrefixWithTheImportedList(moduleNode, prefix, yangLeafRef);
457 }
458 }
459 }
460
461 /**
462 * Updates the prefix with the imported list in the module.
463 *
464 * @param moduleNode root node of the leafref
465 * @param prefixInPath prefix in the path
466 * @param yangLeafRef instance YANG leafref
467 */
468 private static void updatePrefixWithTheImportedList(YangModule moduleNode, String prefixInPath, YangLeafRef
469 yangLeafRef) {
470 if (prefixInPath != null && prefixInPath != EMPTY_STRING && !prefixInPath.equals(moduleNode.getPrefix())) {
471 List<YangImport> moduleImportList = moduleNode.getImportList();
472 if (moduleImportList != null && !moduleImportList.isEmpty()) {
473 Iterator<YangImport> yangImportIterator = moduleImportList.listIterator();
474 while (yangImportIterator.hasNext()) {
475 YangImport yangImport = yangImportIterator.next();
476 if (yangImport.getPrefixId().equals(prefixInPath)) {
477 HashMap prefixMap = new HashMap();
478 prefixMap.put(prefixInPath, yangImport.getModuleName());
479 yangLeafRef.setPrefixAndItsImportedModule(prefixMap);
480 }
481 }
482 }
483 } else {
484 HashMap prefixMap = new HashMap();
485 prefixMap.put(prefixInPath, moduleNode.getName());
486 yangLeafRef.setPrefixAndItsImportedModule(prefixMap);
487 }
488 }
489
490 /**
491 * Returns module or submodule node from the current node.
492 *
493 * @param node current node
494 * @return root node
495 */
496 private static YangNode getModuleOrSubmoduleInFileOfTheCurrentNode(YangNode node) {
497 while (!(node instanceof YangModule) && !(node instanceof YangSubModule)) {
498 if (node == null) {
499 throw new ParserException("Internal datamodel error: Datamodel tree is not correct");
500 }
501 node = node.getParent();
502 }
503 return node;
504 }
505
506 /**
507 * Validates the unique syntax from the reference path.
508 *
509 * @param uniquePath path of unique
510 * @param prefixOfFile current file's prefix
511 * @param ctx yang construct's context to get the line number and character position
512 * @return list of absolute path
513 */
514 private static List<YangAtomicPath> validateUniqueValues(String uniquePath, String prefixOfFile,
Bharat saraswale304c252016-08-16 20:56:20 +0530515 ParserRuleContext ctx) {
janani bebb143d2016-07-14 19:35:22 +0530516 List<YangAtomicPath> atomicPath = new LinkedList<>();
517 String[] pathInUnique = uniquePath.split(SLASH_FOR_STRING);
518 for (String uniqueValue : pathInUnique) {
519 YangAtomicPath yangAtomicPathPath = new YangAtomicPath();
520 YangNodeIdentifier nodeIdentifier = getValidNodeIdentifier(uniqueValue, YangConstructType.UNIQUE_DATA, ctx);
521 yangAtomicPathPath.setNodeIdentifier(nodeIdentifier);
522 atomicPath.add(yangAtomicPathPath);
523 if (nodeIdentifier.getPrefix() != null && nodeIdentifier.getPrefix() != prefixOfFile) {
524 ParserException parserException = new ParserException("YANG file error : A leaf reference, in unique," +
525 " must refer to a leaf in the list");
526 parserException.setLine(ctx.getStart().getLine());
527 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
528 throw parserException;
529 }
530 }
531 return atomicPath;
532 }
533
534 /**
535 * Validates unique field from the list.
536 *
537 * @param yangList instance of YANG list
538 * @param ctx yang construct's context to get the line number and character position
539 */
540 public static void validateUniqueInList(YangList yangList, ParserRuleContext ctx) {
541 YangLeaf leaf;
542 // Returns the prefix for the file where unique is present.
543 String prefixOfTheFile = getPrefixInFileOfTheCurrentNode(yangList);
544 List<String> uniques = yangList.getUniqueList();
545 if (uniques != null && !uniques.isEmpty()) {
546 Iterator<String> uniqueList = uniques.listIterator();
547 while (uniqueList.hasNext()) {
548 String pathInUnique = uniqueList.next();
549 List<YangAtomicPath> atomicPathInUnique = validateUniqueValues(pathInUnique, prefixOfTheFile, ctx);
550 YangAtomicPath leafInPath = atomicPathInUnique.get(atomicPathInUnique.size() - 1);
551 if (atomicPathInUnique.size() == 1) {
552 leaf = getReferenceLeafFromUnique(yangList, leafInPath);
553 } else {
554 atomicPathInUnique.remove(atomicPathInUnique.size() - 1);
555 YangNode holderOfLeaf = getNodeUnderListFromPath(atomicPathInUnique, yangList, ctx);
556 leaf = getReferenceLeafFromUnique(holderOfLeaf, leafInPath);
557 }
558 if (leaf == null) {
559 ParserException parserException = new ParserException("YANG file error : A leaf reference, in " +
560 "unique," +
561 " must refer to a leaf under the list");
562 parserException.setLine(ctx.getStart().getLine());
563 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
564 throw parserException;
565 }
566 }
567 }
568 }
569
570 /**
571 * Returns the last node under the unique path.
572 *
573 * @param uniquePath atomic path list
574 * @param node root node from where it starts searching
575 * @param ctx yang construct's context to get the line number and character position
576 * @return last node in the list
577 */
578 private static YangNode getNodeUnderListFromPath(List<YangAtomicPath> uniquePath, YangNode node,
579 ParserRuleContext ctx) {
580 Iterator<YangAtomicPath> nodesInReference = uniquePath.listIterator();
581 YangNode potentialReferredNode = node.getChild();
582 while (nodesInReference.hasNext()) {
583 YangAtomicPath nodeInUnique = nodesInReference.next();
584 YangNode referredNode = getReferredNodeFromTheUniqueNodes(nodeInUnique.getNodeIdentifier(),
585 potentialReferredNode);
586 if (referredNode == null) {
587 ParserException parserException = new ParserException("YANG file error : The target node in unique " +
588 "reference path is invalid");
589 parserException.setLine(ctx.getStart().getLine());
590 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
591 throw parserException;
592 } else {
593 potentialReferredNode = referredNode.getChild();
594 }
595 }
596 return potentialReferredNode;
597 }
598
599 /**
600 * Returns the node that matches with the name of the node in path.
601 *
602 * @param nodeInUnique node name in path
603 * @param potentialReferredNode node under which it has to match
604 * @return referred node
605 */
606 private static YangNode getReferredNodeFromTheUniqueNodes(YangNodeIdentifier nodeInUnique, YangNode
607 potentialReferredNode) {
608 while (potentialReferredNode != null) {
609 // Check if the potential referred node is the actual referred node
610 if (potentialReferredNode.getName().equals(nodeInUnique.getName())) {
611 return potentialReferredNode;
612 }
613 potentialReferredNode = potentialReferredNode.getNextSibling();
614 }
615 return null;
616 }
617
618 /**
619 * Returns the leaf which unique refers.
620 *
621 * @param nodeForLeaf last node where leaf is referred
622 * @param leafInUnique leaf in unique path
623 * @return YANG leaf
624 */
625 private static YangLeaf getReferenceLeafFromUnique(YangNode nodeForLeaf, YangAtomicPath leafInUnique) {
626 YangLeavesHolder leavesHolder = (YangLeavesHolder) nodeForLeaf;
627 List<YangLeaf> leaves = leavesHolder.getListOfLeaf();
628 if (leaves != null && !leaves.isEmpty()) {
629 for (YangLeaf leaf : leaves) {
630 if (leafInUnique.getNodeIdentifier().getName().equals(leaf.getName())) {
631 return leaf;
632 }
633 }
634 }
635 return null;
636 }
637
638 /**
639 * Returns the prefix of the current file.
640 *
641 * @param node node where it needs to find the root node
642 * @return prefix of root node
643 */
644 public static String getPrefixInFileOfTheCurrentNode(YangNode node) {
645 String prefixInFile;
646 while (!(node instanceof YangReferenceResolver)) {
647 node = node.getParent();
648 if (node == null) {
649 throw new ParserException("Internal datamodel error: Datamodel tree is not correct");
650 }
651 }
652 if (node instanceof YangModule) {
653 YangModule yangModule = (YangModule) node;
654 prefixInFile = yangModule.getPrefix();
655 } else {
656 YangSubModule yangSubModule = (YangSubModule) node;
657 prefixInFile = yangSubModule.getPrefix();
658 }
659 return prefixInFile;
660 }
661
662 /**
janani b0e4e8ae2016-07-13 21:06:41 +0530663 * Validates the relative path.
664 *
665 * @param completePathString the path string of relative path
janani bebb143d2016-07-14 19:35:22 +0530666 * @param yangConstruct yang construct for creating error message
667 * @param ctx yang construct's context to get the line number and character position
668 * @param yangLeafRef instance of leafref where the path argument has to be set
janani b0e4e8ae2016-07-13 21:06:41 +0530669 */
670 private static void validateRelativePath(String completePathString, YangConstructType yangConstruct,
janani bebb143d2016-07-14 19:35:22 +0530671 ParserRuleContext ctx, YangLeafRef yangLeafRef) {
janani b0e4e8ae2016-07-13 21:06:41 +0530672
673 YangRelativePath relativePath = new YangRelativePath();
674 int numberOfAncestors = 0;
675 while (completePathString.startsWith(ANCESTOR_ACCESSOR_IN_PATH)) {
676 completePathString = completePathString.replaceFirst(ANCESTOR_ACCESSOR_IN_PATH, EMPTY_STRING);
677 numberOfAncestors = numberOfAncestors + 1;
678 }
679 if (completePathString == null || completePathString.length() == 0) {
680 ParserException parserException = new ParserException("YANG file error : "
Bharat saraswale304c252016-08-16 20:56:20 +0530681 + getYangConstructType(yangConstruct) + yangLeafRef.getPath() +
janani b0e4e8ae2016-07-13 21:06:41 +0530682 " does not follow valid path syntax");
683 parserException.setLine(ctx.getStart().getLine());
684 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
685 throw parserException;
686 }
687 relativePath.setAncestorNodeCount(numberOfAncestors);
688 List<YangAtomicPath> atomicPath = validateAbsolutePath(SLASH_FOR_STRING + completePathString,
689 yangConstruct,
690 ctx, yangLeafRef);
janani bebb143d2016-07-14 19:35:22 +0530691 validatePrefixAndYangNode(atomicPath, yangLeafRef);
janani b0e4e8ae2016-07-13 21:06:41 +0530692 relativePath.setAtomicPathList(atomicPath);
693 yangLeafRef.setRelativePath(relativePath);
694 }
695
696 /**
697 * Validates the absolute path.
698 *
699 * @param completePathString the path string of absolute path
janani bebb143d2016-07-14 19:35:22 +0530700 * @param yangConstruct yang construct for creating error message
701 * @param ctx yang construct's context to get the line number and character position
702 * @param yangLeafRef instance of leafref where the path argument has to be set
janani b0e4e8ae2016-07-13 21:06:41 +0530703 * @return list of object of node in absolute path
704 */
705 private static List<YangAtomicPath> validateAbsolutePath(String completePathString,
Bharat saraswale304c252016-08-16 20:56:20 +0530706 YangConstructType yangConstruct, ParserRuleContext
707 ctx, YangLeafRef yangLeafRef) {
janani b0e4e8ae2016-07-13 21:06:41 +0530708
709 List<YangAtomicPath> absolutePathList = new LinkedList<>();
710 YangPathPredicate yangPathPredicate = new YangPathPredicate();
711 YangNodeIdentifier yangNodeIdentifier;
712
713 while (completePathString != null) {
714 String path = completePathString.replaceFirst(SLASH_FOR_STRING, EMPTY_STRING);
715 if (path == null || path.length() == 0) {
716 ParserException parserException = new ParserException("YANG file error : "
Bharat saraswale304c252016-08-16 20:56:20 +0530717 + getYangConstructType(yangConstruct) + " " + yangLeafRef.getPath() +
janani b0e4e8ae2016-07-13 21:06:41 +0530718 " does not follow valid path syntax");
719 parserException.setLine(ctx.getStart().getLine());
720 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
721 throw parserException;
722 }
723 String matchedPathPredicate;
724 String nodeIdentifier;
725 String[] differentiate = new String[2];
726 int forNodeIdentifier = path.indexOf(CHAR_OF_SLASH);
727 int forPathPredicate = path.indexOf(CHAR_OF_OPEN_SQUARE_BRACKET);
728
729 // Checks if path predicate is present for the node.
730 if ((forPathPredicate < forNodeIdentifier) && (forPathPredicate != -1)) {
731 List<String> pathPredicate = new ArrayList<>();
732 matchedPathPredicate = matchForPathPredicate(path);
733
734 if (matchedPathPredicate == null || matchedPathPredicate.length() == 0) {
735 ParserException parserException = new ParserException("YANG file error : "
Bharat saraswale304c252016-08-16 20:56:20 +0530736 + getYangConstructType(yangConstruct) + " " + yangLeafRef.getPath() +
janani b0e4e8ae2016-07-13 21:06:41 +0530737 " does not follow valid path syntax");
738 parserException.setLine(ctx.getStart().getLine());
739 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
740 throw parserException;
741 }
742 int indexOfMatchedFirstOpenBrace = path.indexOf(CHAR_OF_OPEN_SQUARE_BRACKET);
743 differentiate[0] = path.substring(0, indexOfMatchedFirstOpenBrace);
744 differentiate[1] = path.substring(indexOfMatchedFirstOpenBrace);
745 pathPredicate.add(matchedPathPredicate);
746 nodeIdentifier = differentiate[0];
747 // Starts adding all path predicates of a node into the list.
748 if (!differentiate[1].isEmpty()) {
749 while (differentiate[1].startsWith(OPEN_SQUARE_BRACKET)) {
750 matchedPathPredicate = matchForPathPredicate(differentiate[1]);
751 if (matchedPathPredicate == null || matchedPathPredicate.length() == 0) {
752 ParserException parserException = new ParserException(
Bharat saraswale304c252016-08-16 20:56:20 +0530753 "YANG file error : " + getYangConstructType(yangConstruct) + " "
janani b0e4e8ae2016-07-13 21:06:41 +0530754 + yangLeafRef.getPath() +
755 " does not follow valid path syntax");
756 parserException.setLine(ctx.getStart().getLine());
757 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
758 throw parserException;
759 }
760 pathPredicate.add(matchedPathPredicate);
761 differentiate[1] = differentiate[1].substring(matchedPathPredicate.length());
762 }
763 }
764
765 List<YangPathPredicate> pathPredicateList = validatePathPredicate(pathPredicate, yangConstruct, ctx,
766 yangPathPredicate, yangLeafRef);
767 YangAtomicPath atomicPath = new YangAtomicPath();
768 yangNodeIdentifier = getValidNodeIdentifierForLeafref(nodeIdentifier, yangConstruct, ctx, yangLeafRef);
769 atomicPath.setNodeIdentifier(yangNodeIdentifier);
770 atomicPath.setPathPredicatesList(pathPredicateList);
771 absolutePathList.add(atomicPath);
772 } else {
773 if (path.contains(SLASH_FOR_STRING)) {
774 nodeIdentifier = path.substring(0, path.indexOf(CHAR_OF_SLASH));
775 differentiate[1] = path.substring(path.indexOf(CHAR_OF_SLASH));
776 } else {
777 nodeIdentifier = path;
778 differentiate[1] = null;
779 }
780 yangNodeIdentifier = getValidNodeIdentifierForLeafref(nodeIdentifier, yangConstruct, ctx, yangLeafRef);
781
782 YangAtomicPath atomicPath = new YangAtomicPath();
783 atomicPath.setNodeIdentifier(yangNodeIdentifier);
784 atomicPath.setPathPredicatesList(null);
785 absolutePathList.add(atomicPath);
786 }
787 if (differentiate[1] == null || differentiate[1].length() == 0) {
788 completePathString = null;
789 } else {
790 completePathString = differentiate[1];
791 }
792 }
793 return absolutePathList;
794 }
795
796 /**
797 * Validates path predicate in the absolute path's node.
798 *
janani bebb143d2016-07-14 19:35:22 +0530799 * @param pathPredicate list of path predicates in the node of absolute path
800 * @param yangConstruct yang construct for creating error message
801 * @param ctx yang construct's context to get the line number and character position
janani b0e4e8ae2016-07-13 21:06:41 +0530802 * @param yangPathPredicate instance of path predicate where it has to be set
janani bebb143d2016-07-14 19:35:22 +0530803 * @param yangLeafRef instance of leafref where the path argument has to be set
janani b0e4e8ae2016-07-13 21:06:41 +0530804 * @return list of object of path predicates in absolute path's node
805 */
806 private static List<YangPathPredicate> validatePathPredicate(List<String> pathPredicate,
janani bebb143d2016-07-14 19:35:22 +0530807 YangConstructType yangConstruct, ParserRuleContext
808 ctx, YangPathPredicate yangPathPredicate,
809 YangLeafRef yangLeafRef) {
janani b0e4e8ae2016-07-13 21:06:41 +0530810
811 Iterator<String> pathPredicateString = pathPredicate.iterator();
812 List<String> pathEqualityExpression = new ArrayList<>();
813
814 while (pathPredicateString.hasNext()) {
815 String pathPredicateForNode = pathPredicateString.next();
816 pathPredicateForNode = (pathPredicateForNode.substring(1)).trim();
817 pathPredicateForNode = pathPredicateForNode.substring(0,
818 pathPredicateForNode.indexOf(CHAR_OF_CLOSE_SQUARE_BRACKET));
819 pathEqualityExpression.add(pathPredicateForNode);
820 }
821 List<YangPathPredicate> validatedPathPredicateList = validatePathEqualityExpression(pathEqualityExpression,
822 yangConstruct, ctx, yangPathPredicate, yangLeafRef);
823 return validatedPathPredicateList;
824 }
825
826 /**
827 * Validates the path equality expression.
828 *
829 * @param pathEqualityExpression list of path equality expression in the path predicates of the node
janani bebb143d2016-07-14 19:35:22 +0530830 * @param yangConstruct yang construct for creating error message
831 * @param ctx yang construct's context to get the line number and character position
832 * @param yangPathPredicate instance of path predicate where it has to be set
833 * @param yangLeafRef instance of leafref where the path argument has to be set
janani b0e4e8ae2016-07-13 21:06:41 +0530834 * @return list of object of path predicates in absolute path's node
835 */
836 private static List<YangPathPredicate> validatePathEqualityExpression(List<String> pathEqualityExpression,
janani bebb143d2016-07-14 19:35:22 +0530837 YangConstructType yangConstruct,
838 ParserRuleContext ctx, YangPathPredicate
839 yangPathPredicate,
840 YangLeafRef yangLeafRef) {
janani b0e4e8ae2016-07-13 21:06:41 +0530841
842 Iterator<String> pathEqualityExpressionString = pathEqualityExpression.iterator();
843 List<YangPathPredicate> yangPathPredicateList = new ArrayList<>();
844
845 while (pathEqualityExpressionString.hasNext()) {
846 String pathEqualityExpressionForNode = pathEqualityExpressionString.next();
847 String[] pathEqualityExpressionArray = pathEqualityExpressionForNode.split("[=]");
848
849 YangNodeIdentifier yangNodeIdentifierForPredicate;
850 YangRelativePath yangRelativePath;
851 yangNodeIdentifierForPredicate = getValidNodeIdentifierForLeafref(pathEqualityExpressionArray[0].trim(),
852 yangConstruct, ctx, yangLeafRef);
853 yangRelativePath = validatePathKeyExpression(pathEqualityExpressionArray[1].trim(), yangConstruct, ctx,
854 yangLeafRef);
855 yangPathPredicate.setNodeIdentifier(yangNodeIdentifierForPredicate);
856 yangPathPredicate.setPathOperator(EQUALTO);
857 yangPathPredicate.setRightRelativePath(yangRelativePath);
858 yangPathPredicateList.add(yangPathPredicate);
859 }
860 return yangPathPredicateList;
861 }
862
863 /**
864 * Validate the path key expression.
865 *
866 * @param rightRelativePath relative path in the path predicate
janani bebb143d2016-07-14 19:35:22 +0530867 * @param yangConstruct yang construct for creating error message
868 * @param ctx yang construct's context to get the line number and character position
869 * @param yangLeafRef instance of leafref where the path argument has to be set
janani b0e4e8ae2016-07-13 21:06:41 +0530870 * @return object of right relative path in path predicate
871 */
872 private static YangRelativePath validatePathKeyExpression(String rightRelativePath,
janani bebb143d2016-07-14 19:35:22 +0530873 YangConstructType yangConstruct, ParserRuleContext ctx,
874 YangLeafRef yangLeafRef) {
janani b0e4e8ae2016-07-13 21:06:41 +0530875
876 YangRelativePath yangRelativePath = new YangRelativePath();
877 String[] relativePath = rightRelativePath.split(SLASH_FOR_STRING);
878 List<String> rightAbsolutePath = new ArrayList<>();
879 int accessAncestor = 0;
880 for (String path : relativePath) {
881 if (path.trim().equals(ANCESTOR_ACCESSOR)) {
882 accessAncestor = accessAncestor + 1;
883 } else {
884 rightAbsolutePath.add(path);
885 }
886 }
887 List<YangAtomicPath> atomicPathInRelativePath = validateRelativePathKeyExpression(rightAbsolutePath,
888 yangConstruct, ctx, yangLeafRef);
889 yangRelativePath.setAtomicPathList(atomicPathInRelativePath);
890 yangRelativePath.setAncestorNodeCount(accessAncestor);
891 return yangRelativePath;
892 }
893
894 /**
895 * Validates the relative path key expression.
896 *
897 * @param rightAbsolutePath absolute path nodes present in the relative path
janani bebb143d2016-07-14 19:35:22 +0530898 * @param yangConstruct yang construct for creating error message
899 * @param ctx yang construct's context to get the line number and character position
900 * @param yangLeafRef instance of leafref where the path argument has to be set
janani b0e4e8ae2016-07-13 21:06:41 +0530901 * @return list of object of absolute path nodes present in the relative path
902 */
903 private static List<YangAtomicPath> validateRelativePathKeyExpression(List<String> rightAbsolutePath,
Bharat saraswale304c252016-08-16 20:56:20 +0530904 YangConstructType yangConstruct,
905 ParserRuleContext ctx, YangLeafRef
906 yangLeafRef) {
janani b0e4e8ae2016-07-13 21:06:41 +0530907
908 List<YangAtomicPath> atomicPathList = new ArrayList<>();
909 YangNodeIdentifier yangNodeIdentifier;
910
911 Iterator<String> nodes = rightAbsolutePath.iterator();
912 String currentInvocationFunction = nodes.next();
913 currentInvocationFunction = currentInvocationFunction.trim();
914 String[] currentFunction = currentInvocationFunction.split("[(]");
915
916 if (!(currentFunction[0].trim().equals(CURRENT)) || !(currentFunction[1].trim().equals(CLOSE_PARENTHESIS))) {
917 ParserException parserException = new ParserException("YANG file error : "
Bharat saraswale304c252016-08-16 20:56:20 +0530918 + getYangConstructType(yangConstruct) + " " + yangLeafRef.getPath() +
janani b0e4e8ae2016-07-13 21:06:41 +0530919 " does not follow valid path syntax");
920 parserException.setLine(ctx.getStart().getLine());
921 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
922 throw parserException;
923 }
924
925 while (nodes.hasNext()) {
926 YangAtomicPath atomicPath = new YangAtomicPath();
927 String node = nodes.next();
928 yangNodeIdentifier = getValidNodeIdentifierForLeafref(node.trim(), yangConstruct, ctx, yangLeafRef);
929 atomicPath.setNodeIdentifier(yangNodeIdentifier);
930 atomicPathList.add(atomicPath);
931 }
932 return atomicPathList;
933 }
934
935 /**
936 * Validates the match for first path predicate in a given string.
937 *
938 * @param matchRequiredString string for which match has to be done
939 * @return the matched string
940 */
941 private static String matchForPathPredicate(String matchRequiredString) {
942
943 String matchedString = null;
944 java.util.regex.Matcher matcher = PATH_PREDICATE_PATTERN.matcher(matchRequiredString);
945 if (matcher.find()) {
946 matchedString = matcher.group(0);
947 }
948 return matchedString;
949 }
950
951 /**
Vidyashree Ramae2bd9ba2016-03-29 14:37:02 +0530952 * Checks and return valid absolute schema node id.
953 *
janani bebb143d2016-07-14 19:35:22 +0530954 * @param argumentString string from yang file
Vidyashree Ramae2bd9ba2016-03-29 14:37:02 +0530955 * @param yangConstructType yang construct for creating error message
janani bebb143d2016-07-14 19:35:22 +0530956 * @param ctx yang construct's context to get the line number and character position
Vidyashree Ramae2bd9ba2016-03-29 14:37:02 +0530957 * @return target nodes list of absolute schema node id
958 */
Bharat saraswald14cbe82016-07-14 13:26:18 +0530959 public static List<YangAtomicPath> getValidAbsoluteSchemaNodeId(String argumentString,
Bharat saraswale304c252016-08-16 20:56:20 +0530960 YangConstructType yangConstructType,
961 ParserRuleContext ctx) {
Vidyashree Ramae2bd9ba2016-03-29 14:37:02 +0530962
Bharat saraswald14cbe82016-07-14 13:26:18 +0530963 List<YangAtomicPath> targetNodes = new ArrayList<>();
Vidyashree Ramae2bd9ba2016-03-29 14:37:02 +0530964 YangNodeIdentifier yangNodeIdentifier;
965 String tmpSchemaNodeId = removeQuotesAndHandleConcat(argumentString);
966
967 // absolute-schema-nodeid = 1*("/" node-identifier)
968 if (!tmpSchemaNodeId.startsWith(SLASH)) {
969 ParserException parserException = new ParserException("YANG file error : " +
Bharat saraswale304c252016-08-16 20:56:20 +0530970 getYangConstructType(yangConstructType) + " name " + argumentString +
Vidyashree Ramae2bd9ba2016-03-29 14:37:02 +0530971 "is not valid");
972 parserException.setLine(ctx.getStart().getLine());
973 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
974 throw parserException;
975 }
976 String[] tmpData = tmpSchemaNodeId.replaceFirst(CARET + SLASH, EMPTY_STRING).split(SLASH);
977 for (String nodeIdentifiers : tmpData) {
978 yangNodeIdentifier = getValidNodeIdentifier(nodeIdentifiers, yangConstructType, ctx);
Bharat saraswald14cbe82016-07-14 13:26:18 +0530979 YangAtomicPath yangAbsPath = new YangAtomicPath();
980 yangAbsPath.setNodeIdentifier(yangNodeIdentifier);
981 targetNodes.add(yangAbsPath);
Vidyashree Ramae2bd9ba2016-03-29 14:37:02 +0530982 }
983 return targetNodes;
984 }
Vidyashree Ramab6248172016-05-17 16:16:15 +0530985
986 /**
987 * Throws parser exception for unsupported YANG constructs.
988 *
989 * @param yangConstructType yang construct for creating error message
janani bebb143d2016-07-14 19:35:22 +0530990 * @param ctx yang construct's context to get the line number and character position
991 * @param errorInfo error information
Bharat saraswale304c252016-08-16 20:56:20 +0530992 * @param fileName YANG file name
Vidyashree Ramab6248172016-05-17 16:16:15 +0530993 */
994 public static void handleUnsupportedYangConstruct(YangConstructType yangConstructType,
Bharat saraswale304c252016-08-16 20:56:20 +0530995 ParserRuleContext ctx, String errorInfo, String fileName) {
Vidyashree Ramab6248172016-05-17 16:16:15 +0530996 ParserException parserException = new ParserException(YANG_FILE_ERROR
Bharat saraswale304c252016-08-16 20:56:20 +0530997 + QUOTES + getYangConstructType(yangConstructType) + QUOTES
Vidyashree Ramab6248172016-05-17 16:16:15 +0530998 + errorInfo);
999 parserException.setLine(ctx.getStart().getLine());
1000 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
Bharat saraswale304c252016-08-16 20:56:20 +05301001 log.info(parserException.getMessage() + " at position " + parserException.getCharPositionInLine() +
1002 " in line " + parserException.getLineNumber() + " of yang file " + fileName);
Vidyashree Ramab6248172016-05-17 16:16:15 +05301003 }
Vidyashree Rama13b4c552016-06-20 15:12:43 +05301004
1005 /**
1006 * Returns date and makes it in usable format for revision.
1007 *
1008 * @param dateInString date argument string from yang file
1009 * @param ctx yang construct's context to get the line number and character position
1010 * @return date format for revision
1011 */
1012 public static Date getValidDateFromString(String dateInString, ParserRuleContext ctx) {
1013 String dateArgument = removeQuotesAndHandleConcat(dateInString);
1014 if (dateArgument == null || !dateArgument.matches(DATE_PATTERN)) {
1015 ParserException parserException = new ParserException("YANG file error: Input date is not correct");
1016 parserException.setLine(ctx.getStart().getLine());
1017 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
1018 throw parserException;
1019 }
1020
1021 SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
1022 sdf.setLenient(false);
1023
1024 try {
1025 //if not valid, it will throw ParseException
1026 Date date = sdf.parse(dateArgument);
1027 return date;
1028 } catch (ParseException e) {
1029 ParserException parserException = new ParserException("YANG file error: Input date is not correct");
1030 parserException.setLine(ctx.getStart().getLine());
1031 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
1032 throw parserException;
1033 }
1034 }
Vidyashree Rama918f1622016-07-28 17:33:15 +05301035
1036 /**
1037 * Checks and return valid prefix.
1038 *
1039 * @param inputString string from yang file
1040 * @param yangConstruct yang construct for creating error message
1041 * @param ctx yang construct's context to get the line number and character position
1042 * @return valid prefix
1043 */
1044 public static String getValidPrefix(String inputString,
1045 YangConstructType yangConstruct, ParserRuleContext ctx) {
1046 String tmpPrefixString = removeQuotesAndHandleConcat(inputString);
1047 String[] tmpData = tmpPrefixString.split(Pattern.quote(COLON));
1048 if (tmpData.length == 2) {
1049 return tmpData[0];
1050 } else {
1051 ParserException parserException = new ParserException("YANG file error : " +
Bharat saraswale304c252016-08-16 20:56:20 +05301052 getYangConstructType(yangConstruct) + " name " + inputString +
Vidyashree Rama918f1622016-07-28 17:33:15 +05301053 " is not valid.");
1054 parserException.setLine(ctx.getStart().getLine());
1055 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
1056 throw parserException;
1057 }
1058 }
Bharat saraswald14cbe82016-07-14 13:26:18 +05301059}