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