blob: 5ad6133a3e6b4678274ca0960ecf33b1263a5bdf [file] [log] [blame]
Vidyashree Rama468f8282016-03-04 19:08:35 +05301/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Vidyashree Rama468f8282016-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
Vidyashree Rama468f8282016-03-04 19:08:35 +053019import java.text.ParseException;
20import java.text.SimpleDateFormat;
janani be18b5342016-07-13 21:06:41 +053021import java.util.ArrayList;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053022import java.util.Date;
janani be18b5342016-07-13 21:06:41 +053023import java.util.Iterator;
Vidyashree Rama25bf4d02016-03-29 14:37:02 +053024import java.util.LinkedList;
25import java.util.List;
Vidyashree Rama468f8282016-03-04 19:08:35 +053026import java.util.regex.Pattern;
Vidyashree Rama8a6b1282016-03-15 10:18:25 +053027
Vidyashree Rama25bf4d02016-03-29 14:37:02 +053028import org.antlr.v4.runtime.ParserRuleContext;
janani be18b5342016-07-13 21:06:41 +053029import org.onosproject.yangutils.datamodel.YangAtomicPath;
30import org.onosproject.yangutils.datamodel.YangLeafRef;
Gaurav Agrawalbd804472016-03-25 11:25:36 +053031import org.onosproject.yangutils.datamodel.YangNodeIdentifier;
janani be18b5342016-07-13 21:06:41 +053032import org.onosproject.yangutils.datamodel.YangPathPredicate;
33import org.onosproject.yangutils.datamodel.YangRelativePath;
Bharat saraswal96dfef02016-06-16 00:29:12 +053034import org.onosproject.yangutils.datamodel.utils.YangConstructType;
Vidyashree Rama8a6b1282016-03-15 10:18:25 +053035import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser;
Vidyashree Rama468f8282016-03-04 19:08:35 +053036import org.onosproject.yangutils.parser.exceptions.ParserException;
37
janani be18b5342016-07-13 21:06:41 +053038import static org.onosproject.yangutils.datamodel.YangPathArgType.ABSOLUTE_PATH;
39import static org.onosproject.yangutils.datamodel.YangPathArgType.RELATIVE_PATH;
40import static org.onosproject.yangutils.datamodel.YangPathOperator.EQUALTO;
Vidyashree Rama1db15562016-05-17 16:16:15 +053041import static org.onosproject.yangutils.utils.UtilConstants.ADD;
janani be18b5342016-07-13 21:06:41 +053042import static org.onosproject.yangutils.utils.UtilConstants.ANCESTOR_ACCESSOR;
43import static org.onosproject.yangutils.utils.UtilConstants.ANCESTOR_ACCESSOR_IN_PATH;
Vidyashree Rama1db15562016-05-17 16:16:15 +053044import static org.onosproject.yangutils.utils.UtilConstants.CARET;
janani be18b5342016-07-13 21:06:41 +053045import static org.onosproject.yangutils.utils.UtilConstants.CHAR_OF_CLOSE_SQUARE_BRACKET;
46import static org.onosproject.yangutils.utils.UtilConstants.CHAR_OF_OPEN_SQUARE_BRACKET;
47import static org.onosproject.yangutils.utils.UtilConstants.CHAR_OF_SLASH;
48import static org.onosproject.yangutils.utils.UtilConstants.CLOSE_PARENTHESIS;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053049import static org.onosproject.yangutils.utils.UtilConstants.COLON;
janani be18b5342016-07-13 21:06:41 +053050import static org.onosproject.yangutils.utils.UtilConstants.CURRENT;
Vidyashree Rama1db15562016-05-17 16:16:15 +053051import static org.onosproject.yangutils.utils.UtilConstants.EMPTY_STRING;
Vidyashree Rama1db15562016-05-17 16:16:15 +053052import static org.onosproject.yangutils.utils.UtilConstants.FALSE;
janani be18b5342016-07-13 21:06:41 +053053import static org.onosproject.yangutils.utils.UtilConstants.OPEN_SQUARE_BRACKET;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053054import static org.onosproject.yangutils.utils.UtilConstants.QUOTES;
55import static org.onosproject.yangutils.utils.UtilConstants.SLASH;
janani be18b5342016-07-13 21:06:41 +053056import static org.onosproject.yangutils.utils.UtilConstants.SLASH_FOR_STRING;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053057import static org.onosproject.yangutils.utils.UtilConstants.TRUE;
58import static org.onosproject.yangutils.utils.UtilConstants.YANG_FILE_ERROR;
Vidyashree Rama1db15562016-05-17 16:16:15 +053059
Vidyashree Rama468f8282016-03-04 19:08:35 +053060/**
Bharat saraswald9822e92016-04-05 15:13:44 +053061 * Represents an utility for listener.
Vidyashree Rama468f8282016-03-04 19:08:35 +053062 */
63public final class ListenerUtil {
Bharat saraswald9822e92016-04-05 15:13:44 +053064
Vidyashree Rama468f8282016-03-04 19:08:35 +053065 private static final Pattern IDENTIFIER_PATTERN = Pattern.compile("[a-zA-Z_][a-zA-Z0-9_.-]*");
Vidyashree Ramabe0f6da2016-05-09 11:45:05 +053066 private static final String DATE_PATTERN = "[0-9]{4}-([0-9]{2}|[0-9])-([0-9]{2}|[0-9])";
Vidyashree Rama8a6b1282016-03-15 10:18:25 +053067 private static final String NON_NEGATIVE_INTEGER_PATTERN = "[0-9]+";
Vidyashree Rama1db15562016-05-17 16:16:15 +053068 private static final Pattern INTEGER_PATTERN = Pattern.compile("[-][0-9]+|[0-9]+");
janani be18b5342016-07-13 21:06:41 +053069 private static final Pattern PATH_PREDICATE_PATTERN = Pattern.compile("\\[(.*?)\\]");
Vidyashree Rama210c01d2016-05-20 16:29:25 +053070 private static final String XML = "xml";
Vidyashree Rama8a6b1282016-03-15 10:18:25 +053071 private static final String ONE = "1";
Vidyashree Rama468f8282016-03-04 19:08:35 +053072 private static final int IDENTIFIER_LENGTH = 64;
janani bcc9ac302016-03-24 12:43:48 +053073 private static final String DATE_FORMAT = "yyyy-MM-dd";
Vidyashree Rama468f8282016-03-04 19:08:35 +053074
75 /**
76 * Creates a new listener util.
77 */
78 private ListenerUtil() {
79 }
80
81 /**
82 * Removes doubles quotes and concatenates if string has plus symbol.
83 *
84 * @param yangStringData string from yang file
85 * @return concatenated string after removing double quotes
86 */
87 public static String removeQuotesAndHandleConcat(String yangStringData) {
88
janani bcc9ac302016-03-24 12:43:48 +053089 yangStringData = yangStringData.replace("\"", EMPTY_STRING);
Vidyashree Rama1db15562016-05-17 16:16:15 +053090 String[] tmpData = yangStringData.split(Pattern.quote(ADD));
Vidyashree Rama468f8282016-03-04 19:08:35 +053091 StringBuilder builder = new StringBuilder();
92 for (String yangString : tmpData) {
93 builder.append(yangString);
94 }
95 return builder.toString();
96 }
97
98 /**
99 * Validates identifier and returns concatenated string if string contains plus symbol.
100 *
101 * @param identifier string from yang file
102 * @param yangConstruct yang construct for creating error message
103 * @param ctx yang construct's context to get the line number and character position
104 * @return concatenated string after removing double quotes
105 */
106 public static String getValidIdentifier(String identifier, YangConstructType yangConstruct, ParserRuleContext ctx) {
107
108 String identifierString = removeQuotesAndHandleConcat(identifier);
109 ParserException parserException;
110
111 if (identifierString.length() > IDENTIFIER_LENGTH) {
112 parserException = new ParserException("YANG file error : " +
113 YangConstructType.getYangConstructType(yangConstruct) + " name " + identifierString + " is " +
114 "greater than 64 characters.");
115 } else if (!IDENTIFIER_PATTERN.matcher(identifierString).matches()) {
116 parserException = new ParserException("YANG file error : " +
117 YangConstructType.getYangConstructType(yangConstruct) + " name " + identifierString + " is not " +
118 "valid.");
Vidyashree Rama210c01d2016-05-20 16:29:25 +0530119 } else if (identifierString.toLowerCase().startsWith(XML)) {
120 parserException = new ParserException("YANG file error : " +
121 YangConstructType.getYangConstructType(yangConstruct) + " identifier " + identifierString +
122 " must not start with (('X'|'x') ('M'|'m') ('L'|'l')).");
Vidyashree Rama468f8282016-03-04 19:08:35 +0530123 } else {
124 return identifierString;
125 }
126
127 parserException.setLine(ctx.getStart().getLine());
128 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
129 throw parserException;
130 }
131
132 /**
janani be18b5342016-07-13 21:06:41 +0530133 * Validates identifier and returns concatenated string if string contains plus symbol.
134 *
135 * @param identifier string from yang file
136 * @param yangConstruct yang construct for creating error message
137 * @param ctx yang construct's context to get the line number and character position
138 * @param yangLeafRef instance of leafref where the path argument has to be set
139 * @return concatenated string after removing double quotes
140 */
141 public static String getValidIdentifierForLeafref(String identifier, YangConstructType yangConstruct,
142 ParserRuleContext ctx, YangLeafRef yangLeafRef) {
143
144 String identifierString = removeQuotesAndHandleConcat(identifier);
145 ParserException parserException;
146
147 if (identifierString.length() > IDENTIFIER_LENGTH) {
148 parserException = new ParserException("YANG file error : " + " identifier " + identifierString + " in " +
149 YangConstructType.getYangConstructType(yangConstruct) + " " + yangLeafRef.getPath() + " is " +
150 "greater than 64 characters.");
151 } else if (!IDENTIFIER_PATTERN.matcher(identifierString).matches()) {
152 parserException = new ParserException("YANG file error : " + " identifier " + identifierString + " in " +
153 YangConstructType.getYangConstructType(yangConstruct) + " " + yangLeafRef.getPath() + " is not " +
154 "valid.");
155 } else if (identifierString.toLowerCase().startsWith(XML)) {
156 parserException = new ParserException("YANG file error : " + " identifier " + identifierString + " in " +
157 YangConstructType.getYangConstructType(yangConstruct) + " " + yangLeafRef.getPath() +
158 " must not start with (('X'|'x') ('M'|'m') ('L'|'l')).");
159 } else {
160 return identifierString;
161 }
162
163 parserException.setLine(ctx.getStart().getLine());
164 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
165 throw parserException;
166 }
167
168 /**
Vidyashree Rama468f8282016-03-04 19:08:35 +0530169 * Validates the revision date.
170 *
171 * @param dateToValidate input revision date
172 * @return validation result, true for success, false for failure
173 */
174 public static boolean isDateValid(String dateToValidate) {
Vidyashree Ramabe0f6da2016-05-09 11:45:05 +0530175 if (dateToValidate == null || !dateToValidate.matches(DATE_PATTERN)) {
Vidyashree Rama468f8282016-03-04 19:08:35 +0530176 return false;
177 }
178
janani bcc9ac302016-03-24 12:43:48 +0530179 SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
Vidyashree Rama468f8282016-03-04 19:08:35 +0530180 sdf.setLenient(false);
181
182 try {
183 //if not valid, it will throw ParseException
184 sdf.parse(dateToValidate);
185 } catch (ParseException e) {
186 return false;
187 }
188
189 return true;
190 }
Vidyashree Rama8a6b1282016-03-15 10:18:25 +0530191
192 /**
193 * Validates YANG version.
194 *
195 * @param ctx version context object of the grammar rule
196 * @return valid version
197 */
198 public static byte getValidVersion(GeneratedYangParser.YangVersionStatementContext ctx) {
199
200 String value = removeQuotesAndHandleConcat(ctx.version().getText());
201 if (!value.equals(ONE)) {
202 ParserException parserException = new ParserException("YANG file error: Input version not supported");
203 parserException.setLine(ctx.getStart().getLine());
204 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
205 throw parserException;
206 }
207
208 return Byte.valueOf(value);
209 }
210
211 /**
212 * Validates non negative integer value.
213 *
214 * @param integerValue integer to be validated
215 * @param yangConstruct yang construct for creating error message
216 * @param ctx context object of the grammar rule
217 * @return valid non negative integer value
218 */
219 public static int getValidNonNegativeIntegerValue(String integerValue, YangConstructType yangConstruct,
Bharat saraswald9822e92016-04-05 15:13:44 +0530220 ParserRuleContext ctx) {
Vidyashree Rama8a6b1282016-03-15 10:18:25 +0530221
222 String value = removeQuotesAndHandleConcat(integerValue);
223 if (!value.matches(NON_NEGATIVE_INTEGER_PATTERN)) {
224 ParserException parserException = new ParserException("YANG file error : " +
225 YangConstructType.getYangConstructType(yangConstruct) + " value " + value + " is not " +
226 "valid.");
227 parserException.setLine(ctx.getStart().getLine());
228 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
229 throw parserException;
230 }
231
Vidyashree Rama210c01d2016-05-20 16:29:25 +0530232 int valueInInteger;
233 try {
234 valueInInteger = Integer.parseInt(value);
235 } catch (NumberFormatException e) {
236 ParserException parserException = new ParserException("YANG file error : " +
237 YangConstructType.getYangConstructType(yangConstruct) + " value " + value + " is not " +
238 "valid.");
239 parserException.setLine(ctx.getStart().getLine());
240 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
241 throw parserException;
242 }
243 return valueInInteger;
Vidyashree Rama8a6b1282016-03-15 10:18:25 +0530244 }
245
246 /**
Vidyashree Rama1db15562016-05-17 16:16:15 +0530247 * Validates integer value.
248 *
249 * @param integerValue integer to be validated
250 * @param yangConstruct yang construct for creating error message
251 * @param ctx context object of the grammar rule
252 * @return valid integer value
253 */
254 public static int getValidIntegerValue(String integerValue, YangConstructType yangConstruct,
255 ParserRuleContext ctx) {
256
257 String value = removeQuotesAndHandleConcat(integerValue);
258 if (!INTEGER_PATTERN.matcher(value).matches()) {
259 ParserException parserException = new ParserException("YANG file error : " +
260 YangConstructType.getYangConstructType(yangConstruct) + " value " + value + " is not " +
261 "valid.");
262 parserException.setLine(ctx.getStart().getLine());
263 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
264 throw parserException;
265 }
266
267 int valueInInteger;
268 try {
269 valueInInteger = Integer.parseInt(value);
270 } catch (NumberFormatException e) {
271 ParserException parserException = new ParserException("YANG file error : " +
272 YangConstructType.getYangConstructType(yangConstruct) + " value " + value + " is not " +
273 "valid.");
274 parserException.setLine(ctx.getStart().getLine());
275 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
276 throw parserException;
277 }
278 return valueInInteger;
279 }
280
281 /**
Vidyashree Rama8a6b1282016-03-15 10:18:25 +0530282 * Validates boolean value.
283 *
284 * @param booleanValue value to be validated
285 * @param yangConstruct yang construct for creating error message
286 * @param ctx context object of the grammar rule
287 * @return boolean value either true or false
288 */
289 public static boolean getValidBooleanValue(String booleanValue, YangConstructType yangConstruct,
Bharat saraswald9822e92016-04-05 15:13:44 +0530290 ParserRuleContext ctx) {
Vidyashree Rama8a6b1282016-03-15 10:18:25 +0530291
292 String value = removeQuotesAndHandleConcat(booleanValue);
Vidyashree Rama1db15562016-05-17 16:16:15 +0530293 if (value.equals(TRUE)) {
Vidyashree Rama8a6b1282016-03-15 10:18:25 +0530294 return true;
Vidyashree Rama1db15562016-05-17 16:16:15 +0530295 } else if (value.equals(FALSE)) {
Vidyashree Rama8a6b1282016-03-15 10:18:25 +0530296 return false;
297 } else {
298 ParserException parserException = new ParserException("YANG file error : " +
299 YangConstructType.getYangConstructType(yangConstruct) + " value " + value + " is not " +
300 "valid.");
301 parserException.setLine(ctx.getStart().getLine());
302 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
303 throw parserException;
304 }
305 }
janani bcc9ac302016-03-24 12:43:48 +0530306
307 /**
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530308 * Returns current date and makes it in usable format for revision.
janani bcc9ac302016-03-24 12:43:48 +0530309 *
310 * @return usable current date format for revision
311 */
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530312 public static Date getCurrentDateForRevision() {
janani bcc9ac302016-03-24 12:43:48 +0530313
janani bcc9ac302016-03-24 12:43:48 +0530314 SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530315
316 Date date = new Date();
317 String dateInString = dateFormat.format(date);
318 try {
319 //if not valid, it will throw ParseException
320 Date now = dateFormat.parse(dateInString);
321 return date;
322 } catch (ParseException e) {
323 ParserException parserException = new ParserException("YANG file error: Input date is not correct");
324 throw parserException;
325 }
janani bcc9ac302016-03-24 12:43:48 +0530326 }
Gaurav Agrawalbd804472016-03-25 11:25:36 +0530327
328 /**
329 * Checks and return valid node identifier.
330 *
331 * @param nodeIdentifierString string from yang file
332 * @param yangConstruct yang construct for creating error message
333 * @param ctx yang construct's context to get the line number and character position
334 * @return valid node identifier
335 */
Vinod Kumar Sd4deb062016-04-15 18:08:57 +0530336 public static YangNodeIdentifier getValidNodeIdentifier(String nodeIdentifierString,
337 YangConstructType yangConstruct, ParserRuleContext ctx) {
Gaurav Agrawalbd804472016-03-25 11:25:36 +0530338 String tmpIdentifierString = removeQuotesAndHandleConcat(nodeIdentifierString);
339 String[] tmpData = tmpIdentifierString.split(Pattern.quote(COLON));
340 if (tmpData.length == 1) {
341 YangNodeIdentifier nodeIdentifier = new YangNodeIdentifier();
342 nodeIdentifier.setName(getValidIdentifier(tmpData[0], yangConstruct, ctx));
343 return nodeIdentifier;
344 } else if (tmpData.length == 2) {
345 YangNodeIdentifier nodeIdentifier = new YangNodeIdentifier();
346 nodeIdentifier.setPrefix(getValidIdentifier(tmpData[0], yangConstruct, ctx));
347 nodeIdentifier.setName(getValidIdentifier(tmpData[1], yangConstruct, ctx));
348 return nodeIdentifier;
349 } else {
350 ParserException parserException = new ParserException("YANG file error : " +
351 YangConstructType.getYangConstructType(yangConstruct) + " name " + nodeIdentifierString +
352 " is not valid.");
353 parserException.setLine(ctx.getStart().getLine());
354 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
355 throw parserException;
356 }
357 }
Vidyashree Rama25bf4d02016-03-29 14:37:02 +0530358
359 /**
janani be18b5342016-07-13 21:06:41 +0530360 * Checks and return valid node identifier specific to nodes in leafref path.
361 *
362 * @param nodeIdentifierString string from yang file
363 * @param yangConstruct yang construct for creating error message
364 * @param ctx yang construct's context to get the line number and character position
365 * @param yangLeafRef instance of leafref where the path argument has to be set
366 * @return valid node identifier
367 */
368 public static YangNodeIdentifier getValidNodeIdentifierForLeafref(String nodeIdentifierString,
369 YangConstructType yangConstruct, ParserRuleContext ctx, YangLeafRef yangLeafRef) {
370
371 String tmpIdentifierString = removeQuotesAndHandleConcat(nodeIdentifierString);
372 String[] tmpData = tmpIdentifierString.split(Pattern.quote(COLON));
373 if (tmpData.length == 1) {
374 YangNodeIdentifier nodeIdentifier = new YangNodeIdentifier();
janani be18b5342016-07-13 21:06:41 +0530375 nodeIdentifier.setName(getValidIdentifierForLeafref(tmpData[0], yangConstruct, ctx, yangLeafRef));
376 return nodeIdentifier;
377 } else if (tmpData.length == 2) {
378 YangNodeIdentifier nodeIdentifier = new YangNodeIdentifier();
379 nodeIdentifier.setPrefix(getValidIdentifierForLeafref(tmpData[0], yangConstruct, ctx, yangLeafRef));
380 nodeIdentifier.setName(getValidIdentifierForLeafref(tmpData[1], yangConstruct, ctx, yangLeafRef));
381 return nodeIdentifier;
382 } else {
383 ParserException parserException = new ParserException("YANG file error : " +
384 YangConstructType.getYangConstructType(yangConstruct) + yangLeafRef.getPath() +
385 " is not valid.");
386 parserException.setLine(ctx.getStart().getLine());
387 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
388 throw parserException;
389 }
390 }
391
392 /**
393 * Validates the path argument. It can be either absolute or relative path.
394 *
395 * @param pathString the path string from the path type
396 * @param yangConstruct yang construct for creating error message
397 * @param ctx yang construct's context to get the line number and character position
398 * @param yangLeafRef instance of leafref where the path argument has to be set
399 */
400 public static void validatePathArgument(String pathString, YangConstructType yangConstruct,
401 ParserRuleContext ctx, YangLeafRef yangLeafRef) {
402
403 String completePathString = removeQuotesAndHandleConcat(pathString);
404 yangLeafRef.setPath(completePathString);
405 if (completePathString.startsWith(SLASH)) {
406 yangLeafRef.setPathType(ABSOLUTE_PATH);
407 List<YangAtomicPath> yangAtomicPathListList = validateAbsolutePath(completePathString, yangConstruct, ctx,
408 yangLeafRef);
409 yangLeafRef.setAtomicPath(yangAtomicPathListList);
410 } else if (completePathString.startsWith(ANCESTOR_ACCESSOR)) {
411 yangLeafRef.setPathType(RELATIVE_PATH);
412 validateRelativePath(completePathString, yangConstruct, ctx, yangLeafRef);
413 } else {
414 ParserException parserException = new ParserException("YANG file error : " +
415 YangConstructType.getYangConstructType(yangConstruct) + yangLeafRef.getPath() +
416 " does not follow valid path syntax");
417 parserException.setLine(ctx.getStart().getLine());
418 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
419 throw parserException;
420 }
421 }
422
423 /**
424 * Validates the relative path.
425 *
426 * @param completePathString the path string of relative path
427 * @param yangConstruct yang construct for creating error message
428 * @param ctx yang construct's context to get the line number and character position
429 * @param yangLeafRef instance of leafref where the path argument has to be set
430 */
431 private static void validateRelativePath(String completePathString, YangConstructType yangConstruct,
432 ParserRuleContext ctx, YangLeafRef yangLeafRef) {
433
434 YangRelativePath relativePath = new YangRelativePath();
435 int numberOfAncestors = 0;
436 while (completePathString.startsWith(ANCESTOR_ACCESSOR_IN_PATH)) {
437 completePathString = completePathString.replaceFirst(ANCESTOR_ACCESSOR_IN_PATH, EMPTY_STRING);
438 numberOfAncestors = numberOfAncestors + 1;
439 }
440 if (completePathString == null || completePathString.length() == 0) {
441 ParserException parserException = new ParserException("YANG file error : "
442 + YangConstructType.getYangConstructType(yangConstruct) + yangLeafRef.getPath() +
443 " does not follow valid path syntax");
444 parserException.setLine(ctx.getStart().getLine());
445 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
446 throw parserException;
447 }
448 relativePath.setAncestorNodeCount(numberOfAncestors);
449 List<YangAtomicPath> atomicPath = validateAbsolutePath(SLASH_FOR_STRING + completePathString,
450 yangConstruct,
451 ctx, yangLeafRef);
452 relativePath.setAtomicPathList(atomicPath);
453 yangLeafRef.setRelativePath(relativePath);
454 }
455
456 /**
457 * Validates the absolute path.
458 *
459 * @param completePathString the path string of absolute path
460 * @param yangConstruct yang construct for creating error message
461 * @param ctx yang construct's context to get the line number and character position
462 * @param yangLeafRef instance of leafref where the path argument has to be set
463 * @return list of object of node in absolute path
464 */
465 private static List<YangAtomicPath> validateAbsolutePath(String completePathString,
466 YangConstructType yangConstruct, ParserRuleContext ctx, YangLeafRef yangLeafRef) {
467
468 List<YangAtomicPath> absolutePathList = new LinkedList<>();
469 YangPathPredicate yangPathPredicate = new YangPathPredicate();
470 YangNodeIdentifier yangNodeIdentifier;
471
472 while (completePathString != null) {
473 String path = completePathString.replaceFirst(SLASH_FOR_STRING, EMPTY_STRING);
474 if (path == null || path.length() == 0) {
475 ParserException parserException = new ParserException("YANG file error : "
476 + YangConstructType.getYangConstructType(yangConstruct) + " " + yangLeafRef.getPath() +
477 " does not follow valid path syntax");
478 parserException.setLine(ctx.getStart().getLine());
479 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
480 throw parserException;
481 }
482 String matchedPathPredicate;
483 String nodeIdentifier;
484 String[] differentiate = new String[2];
485 int forNodeIdentifier = path.indexOf(CHAR_OF_SLASH);
486 int forPathPredicate = path.indexOf(CHAR_OF_OPEN_SQUARE_BRACKET);
487
488 // Checks if path predicate is present for the node.
489 if ((forPathPredicate < forNodeIdentifier) && (forPathPredicate != -1)) {
490 List<String> pathPredicate = new ArrayList<>();
491 matchedPathPredicate = matchForPathPredicate(path);
492
493 if (matchedPathPredicate == null || matchedPathPredicate.length() == 0) {
494 ParserException parserException = new ParserException("YANG file error : "
495 + YangConstructType.getYangConstructType(yangConstruct) + " " + yangLeafRef.getPath() +
496 " does not follow valid path syntax");
497 parserException.setLine(ctx.getStart().getLine());
498 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
499 throw parserException;
500 }
501 int indexOfMatchedFirstOpenBrace = path.indexOf(CHAR_OF_OPEN_SQUARE_BRACKET);
502 differentiate[0] = path.substring(0, indexOfMatchedFirstOpenBrace);
503 differentiate[1] = path.substring(indexOfMatchedFirstOpenBrace);
504 pathPredicate.add(matchedPathPredicate);
505 nodeIdentifier = differentiate[0];
506 // Starts adding all path predicates of a node into the list.
507 if (!differentiate[1].isEmpty()) {
508 while (differentiate[1].startsWith(OPEN_SQUARE_BRACKET)) {
509 matchedPathPredicate = matchForPathPredicate(differentiate[1]);
510 if (matchedPathPredicate == null || matchedPathPredicate.length() == 0) {
511 ParserException parserException = new ParserException(
512 "YANG file error : " + YangConstructType.getYangConstructType(yangConstruct) + " "
513 + yangLeafRef.getPath() +
514 " does not follow valid path syntax");
515 parserException.setLine(ctx.getStart().getLine());
516 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
517 throw parserException;
518 }
519 pathPredicate.add(matchedPathPredicate);
520 differentiate[1] = differentiate[1].substring(matchedPathPredicate.length());
521 }
522 }
523
524 List<YangPathPredicate> pathPredicateList = validatePathPredicate(pathPredicate, yangConstruct, ctx,
525 yangPathPredicate, yangLeafRef);
526 YangAtomicPath atomicPath = new YangAtomicPath();
527 yangNodeIdentifier = getValidNodeIdentifierForLeafref(nodeIdentifier, yangConstruct, ctx, yangLeafRef);
528 atomicPath.setNodeIdentifier(yangNodeIdentifier);
529 atomicPath.setPathPredicatesList(pathPredicateList);
530 absolutePathList.add(atomicPath);
531 } else {
532 if (path.contains(SLASH_FOR_STRING)) {
533 nodeIdentifier = path.substring(0, path.indexOf(CHAR_OF_SLASH));
534 differentiate[1] = path.substring(path.indexOf(CHAR_OF_SLASH));
535 } else {
536 nodeIdentifier = path;
537 differentiate[1] = null;
538 }
539 yangNodeIdentifier = getValidNodeIdentifierForLeafref(nodeIdentifier, yangConstruct, ctx, yangLeafRef);
540
541 YangAtomicPath atomicPath = new YangAtomicPath();
542 atomicPath.setNodeIdentifier(yangNodeIdentifier);
543 atomicPath.setPathPredicatesList(null);
544 absolutePathList.add(atomicPath);
545 }
546 if (differentiate[1] == null || differentiate[1].length() == 0) {
547 completePathString = null;
548 } else {
549 completePathString = differentiate[1];
550 }
551 }
552 return absolutePathList;
553 }
554
555 /**
556 * Validates path predicate in the absolute path's node.
557 *
558 * @param pathPredicate list of path predicates in the node of absolute path
559 * @param yangConstruct yang construct for creating error message
560 * @param ctx yang construct's context to get the line number and character position
561 * @param yangPathPredicate instance of path predicate where it has to be set
562 * @param yangLeafRef instance of leafref where the path argument has to be set
563 * @return list of object of path predicates in absolute path's node
564 */
565 private static List<YangPathPredicate> validatePathPredicate(List<String> pathPredicate,
566 YangConstructType yangConstruct, ParserRuleContext ctx, YangPathPredicate yangPathPredicate,
567 YangLeafRef yangLeafRef) {
568
569 Iterator<String> pathPredicateString = pathPredicate.iterator();
570 List<String> pathEqualityExpression = new ArrayList<>();
571
572 while (pathPredicateString.hasNext()) {
573 String pathPredicateForNode = pathPredicateString.next();
574 pathPredicateForNode = (pathPredicateForNode.substring(1)).trim();
575 pathPredicateForNode = pathPredicateForNode.substring(0,
576 pathPredicateForNode.indexOf(CHAR_OF_CLOSE_SQUARE_BRACKET));
577 pathEqualityExpression.add(pathPredicateForNode);
578 }
579 List<YangPathPredicate> validatedPathPredicateList = validatePathEqualityExpression(pathEqualityExpression,
580 yangConstruct, ctx, yangPathPredicate, yangLeafRef);
581 return validatedPathPredicateList;
582 }
583
584 /**
585 * Validates the path equality expression.
586 *
587 * @param pathEqualityExpression list of path equality expression in the path predicates of the node
588 * @param yangConstruct yang construct for creating error message
589 * @param ctx yang construct's context to get the line number and character position
590 * @param yangPathPredicate instance of path predicate where it has to be set
591 * @param yangLeafRef instance of leafref where the path argument has to be set
592 * @return list of object of path predicates in absolute path's node
593 */
594 private static List<YangPathPredicate> validatePathEqualityExpression(List<String> pathEqualityExpression,
595 YangConstructType yangConstruct, ParserRuleContext ctx, YangPathPredicate yangPathPredicate,
596 YangLeafRef yangLeafRef) {
597
598 Iterator<String> pathEqualityExpressionString = pathEqualityExpression.iterator();
599 List<YangPathPredicate> yangPathPredicateList = new ArrayList<>();
600
601 while (pathEqualityExpressionString.hasNext()) {
602 String pathEqualityExpressionForNode = pathEqualityExpressionString.next();
603 String[] pathEqualityExpressionArray = pathEqualityExpressionForNode.split("[=]");
604
605 YangNodeIdentifier yangNodeIdentifierForPredicate;
606 YangRelativePath yangRelativePath;
607 yangNodeIdentifierForPredicate = getValidNodeIdentifierForLeafref(pathEqualityExpressionArray[0].trim(),
608 yangConstruct, ctx, yangLeafRef);
609 yangRelativePath = validatePathKeyExpression(pathEqualityExpressionArray[1].trim(), yangConstruct, ctx,
610 yangLeafRef);
611 yangPathPredicate.setNodeIdentifier(yangNodeIdentifierForPredicate);
612 yangPathPredicate.setPathOperator(EQUALTO);
613 yangPathPredicate.setRightRelativePath(yangRelativePath);
614 yangPathPredicateList.add(yangPathPredicate);
615 }
616 return yangPathPredicateList;
617 }
618
619 /**
620 * Validate the path key expression.
621 *
622 * @param rightRelativePath relative path in the path predicate
623 * @param yangConstruct yang construct for creating error message
624 * @param ctx yang construct's context to get the line number and character position
625 * @param yangLeafRef instance of leafref where the path argument has to be set
626 * @return object of right relative path in path predicate
627 */
628 private static YangRelativePath validatePathKeyExpression(String rightRelativePath,
629 YangConstructType yangConstruct, ParserRuleContext ctx, YangLeafRef yangLeafRef) {
630
631 YangRelativePath yangRelativePath = new YangRelativePath();
632 String[] relativePath = rightRelativePath.split(SLASH_FOR_STRING);
633 List<String> rightAbsolutePath = new ArrayList<>();
634 int accessAncestor = 0;
635 for (String path : relativePath) {
636 if (path.trim().equals(ANCESTOR_ACCESSOR)) {
637 accessAncestor = accessAncestor + 1;
638 } else {
639 rightAbsolutePath.add(path);
640 }
641 }
642 List<YangAtomicPath> atomicPathInRelativePath = validateRelativePathKeyExpression(rightAbsolutePath,
643 yangConstruct, ctx, yangLeafRef);
644 yangRelativePath.setAtomicPathList(atomicPathInRelativePath);
645 yangRelativePath.setAncestorNodeCount(accessAncestor);
646 return yangRelativePath;
647 }
648
649 /**
650 * Validates the relative path key expression.
651 *
652 * @param rightAbsolutePath absolute path nodes present in the relative path
653 * @param yangConstruct yang construct for creating error message
654 * @param ctx yang construct's context to get the line number and character position
655 * @param yangLeafRef instance of leafref where the path argument has to be set
656 * @return list of object of absolute path nodes present in the relative path
657 */
658 private static List<YangAtomicPath> validateRelativePathKeyExpression(List<String> rightAbsolutePath,
659 YangConstructType yangConstruct, ParserRuleContext ctx, YangLeafRef yangLeafRef) {
660
661 List<YangAtomicPath> atomicPathList = new ArrayList<>();
662 YangNodeIdentifier yangNodeIdentifier;
663
664 Iterator<String> nodes = rightAbsolutePath.iterator();
665 String currentInvocationFunction = nodes.next();
666 currentInvocationFunction = currentInvocationFunction.trim();
667 String[] currentFunction = currentInvocationFunction.split("[(]");
668
669 if (!(currentFunction[0].trim().equals(CURRENT)) || !(currentFunction[1].trim().equals(CLOSE_PARENTHESIS))) {
670 ParserException parserException = new ParserException("YANG file error : "
671 + YangConstructType.getYangConstructType(yangConstruct) + " " + yangLeafRef.getPath() +
672 " does not follow valid path syntax");
673 parserException.setLine(ctx.getStart().getLine());
674 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
675 throw parserException;
676 }
677
678 while (nodes.hasNext()) {
679 YangAtomicPath atomicPath = new YangAtomicPath();
680 String node = nodes.next();
681 yangNodeIdentifier = getValidNodeIdentifierForLeafref(node.trim(), yangConstruct, ctx, yangLeafRef);
682 atomicPath.setNodeIdentifier(yangNodeIdentifier);
683 atomicPathList.add(atomicPath);
684 }
685 return atomicPathList;
686 }
687
688 /**
689 * Validates the match for first path predicate in a given string.
690 *
691 * @param matchRequiredString string for which match has to be done
692 * @return the matched string
693 */
694 private static String matchForPathPredicate(String matchRequiredString) {
695
696 String matchedString = null;
697 java.util.regex.Matcher matcher = PATH_PREDICATE_PATTERN.matcher(matchRequiredString);
698 if (matcher.find()) {
699 matchedString = matcher.group(0);
700 }
701 return matchedString;
702 }
703
704 /**
Vidyashree Rama25bf4d02016-03-29 14:37:02 +0530705 * Checks and return valid absolute schema node id.
706 *
707 * @param argumentString string from yang file
708 * @param yangConstructType yang construct for creating error message
709 * @param ctx yang construct's context to get the line number and character position
710 * @return target nodes list of absolute schema node id
711 */
Bharat saraswalb1170bd2016-07-14 13:26:18 +0530712 public static List<YangAtomicPath> getValidAbsoluteSchemaNodeId(String argumentString,
Vidyashree Rama25bf4d02016-03-29 14:37:02 +0530713 YangConstructType yangConstructType, ParserRuleContext ctx) {
714
Bharat saraswalb1170bd2016-07-14 13:26:18 +0530715 List<YangAtomicPath> targetNodes = new ArrayList<>();
Vidyashree Rama25bf4d02016-03-29 14:37:02 +0530716 YangNodeIdentifier yangNodeIdentifier;
717 String tmpSchemaNodeId = removeQuotesAndHandleConcat(argumentString);
718
719 // absolute-schema-nodeid = 1*("/" node-identifier)
720 if (!tmpSchemaNodeId.startsWith(SLASH)) {
721 ParserException parserException = new ParserException("YANG file error : " +
722 YangConstructType.getYangConstructType(yangConstructType) + " name " + argumentString +
723 "is not valid");
724 parserException.setLine(ctx.getStart().getLine());
725 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
726 throw parserException;
727 }
728 String[] tmpData = tmpSchemaNodeId.replaceFirst(CARET + SLASH, EMPTY_STRING).split(SLASH);
729 for (String nodeIdentifiers : tmpData) {
730 yangNodeIdentifier = getValidNodeIdentifier(nodeIdentifiers, yangConstructType, ctx);
Bharat saraswalb1170bd2016-07-14 13:26:18 +0530731 YangAtomicPath yangAbsPath = new YangAtomicPath();
732 yangAbsPath.setNodeIdentifier(yangNodeIdentifier);
733 targetNodes.add(yangAbsPath);
Vidyashree Rama25bf4d02016-03-29 14:37:02 +0530734 }
735 return targetNodes;
736 }
Vidyashree Rama1db15562016-05-17 16:16:15 +0530737
738 /**
739 * Throws parser exception for unsupported YANG constructs.
740 *
741 * @param yangConstructType yang construct for creating error message
742 * @param ctx yang construct's context to get the line number and character position
743 * @param errorInfo error information
744 */
745 public static void handleUnsupportedYangConstruct(YangConstructType yangConstructType,
746 ParserRuleContext ctx, String errorInfo) {
747 ParserException parserException = new ParserException(YANG_FILE_ERROR
748 + QUOTES + YangConstructType.getYangConstructType(yangConstructType) + QUOTES
749 + errorInfo);
750 parserException.setLine(ctx.getStart().getLine());
751 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
752 throw parserException;
753 }
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530754
755 /**
756 * Returns date and makes it in usable format for revision.
757 *
758 * @param dateInString date argument string from yang file
759 * @param ctx yang construct's context to get the line number and character position
760 * @return date format for revision
761 */
762 public static Date getValidDateFromString(String dateInString, ParserRuleContext ctx) {
763 String dateArgument = removeQuotesAndHandleConcat(dateInString);
764 if (dateArgument == null || !dateArgument.matches(DATE_PATTERN)) {
765 ParserException parserException = new ParserException("YANG file error: Input date is not correct");
766 parserException.setLine(ctx.getStart().getLine());
767 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
768 throw parserException;
769 }
770
771 SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
772 sdf.setLenient(false);
773
774 try {
775 //if not valid, it will throw ParseException
776 Date date = sdf.parse(dateArgument);
777 return date;
778 } catch (ParseException e) {
779 ParserException parserException = new ParserException("YANG file error: Input date is not correct");
780 parserException.setLine(ctx.getStart().getLine());
781 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
782 throw parserException;
783 }
784 }
Bharat saraswalb1170bd2016-07-14 13:26:18 +0530785}