blob: e2097fc91001489ebb287c8fc5eee37043c43db5 [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;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053021import java.util.Date;
Vidyashree Rama25bf4d02016-03-29 14:37:02 +053022import java.util.LinkedList;
23import java.util.List;
Vidyashree Rama468f8282016-03-04 19:08:35 +053024import java.util.regex.Pattern;
Vidyashree Rama8a6b1282016-03-15 10:18:25 +053025
Vidyashree Rama25bf4d02016-03-29 14:37:02 +053026import org.antlr.v4.runtime.ParserRuleContext;
Gaurav Agrawalbd804472016-03-25 11:25:36 +053027import org.onosproject.yangutils.datamodel.YangNodeIdentifier;
Bharat saraswal96dfef02016-06-16 00:29:12 +053028import org.onosproject.yangutils.datamodel.utils.YangConstructType;
Vidyashree Rama8a6b1282016-03-15 10:18:25 +053029import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser;
Vidyashree Rama468f8282016-03-04 19:08:35 +053030import org.onosproject.yangutils.parser.exceptions.ParserException;
31
Vidyashree Rama1db15562016-05-17 16:16:15 +053032import static org.onosproject.yangutils.utils.UtilConstants.ADD;
Vidyashree Rama1db15562016-05-17 16:16:15 +053033import static org.onosproject.yangutils.utils.UtilConstants.CARET;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053034import static org.onosproject.yangutils.utils.UtilConstants.COLON;
janani b6240d292016-05-17 18:20:33 +053035import static org.onosproject.yangutils.utils.UtilConstants.CURRENTLY_UNSUPPORTED;
Vidyashree Rama1db15562016-05-17 16:16:15 +053036import static org.onosproject.yangutils.utils.UtilConstants.EMPTY_STRING;
Vidyashree Rama1db15562016-05-17 16:16:15 +053037import static org.onosproject.yangutils.utils.UtilConstants.FALSE;
janani b6240d292016-05-17 18:20:33 +053038import static org.onosproject.yangutils.utils.UtilConstants.IDENTITYREF;
janani b6240d292016-05-17 18:20:33 +053039import static org.onosproject.yangutils.utils.UtilConstants.INSTANCE_IDENTIFIER;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053040import static org.onosproject.yangutils.utils.UtilConstants.LEAFREF;
41import static org.onosproject.yangutils.utils.UtilConstants.QUOTES;
42import static org.onosproject.yangutils.utils.UtilConstants.SLASH;
43import static org.onosproject.yangutils.utils.UtilConstants.TRUE;
44import static org.onosproject.yangutils.utils.UtilConstants.YANG_FILE_ERROR;
Vidyashree Rama1db15562016-05-17 16:16:15 +053045
Vidyashree Rama468f8282016-03-04 19:08:35 +053046/**
Bharat saraswald9822e92016-04-05 15:13:44 +053047 * Represents an utility for listener.
Vidyashree Rama468f8282016-03-04 19:08:35 +053048 */
49public final class ListenerUtil {
Bharat saraswald9822e92016-04-05 15:13:44 +053050
Vidyashree Rama468f8282016-03-04 19:08:35 +053051 private static final Pattern IDENTIFIER_PATTERN = Pattern.compile("[a-zA-Z_][a-zA-Z0-9_.-]*");
Vidyashree Ramabe0f6da2016-05-09 11:45:05 +053052 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 +053053 private static final String NON_NEGATIVE_INTEGER_PATTERN = "[0-9]+";
Vidyashree Rama1db15562016-05-17 16:16:15 +053054 private static final Pattern INTEGER_PATTERN = Pattern.compile("[-][0-9]+|[0-9]+");
Vidyashree Rama210c01d2016-05-20 16:29:25 +053055 private static final String XML = "xml";
Vidyashree Rama8a6b1282016-03-15 10:18:25 +053056 private static final String ONE = "1";
Vidyashree Rama468f8282016-03-04 19:08:35 +053057 private static final int IDENTIFIER_LENGTH = 64;
janani bcc9ac302016-03-24 12:43:48 +053058 private static final String DATE_FORMAT = "yyyy-MM-dd";
Vidyashree Rama468f8282016-03-04 19:08:35 +053059
60 /**
61 * Creates a new listener util.
62 */
63 private ListenerUtil() {
64 }
65
66 /**
67 * Removes doubles quotes and concatenates if string has plus symbol.
68 *
69 * @param yangStringData string from yang file
70 * @return concatenated string after removing double quotes
71 */
72 public static String removeQuotesAndHandleConcat(String yangStringData) {
73
janani bcc9ac302016-03-24 12:43:48 +053074 yangStringData = yangStringData.replace("\"", EMPTY_STRING);
Vidyashree Rama1db15562016-05-17 16:16:15 +053075 String[] tmpData = yangStringData.split(Pattern.quote(ADD));
Vidyashree Rama468f8282016-03-04 19:08:35 +053076 StringBuilder builder = new StringBuilder();
77 for (String yangString : tmpData) {
78 builder.append(yangString);
79 }
80 return builder.toString();
81 }
82
83 /**
84 * Validates identifier and returns concatenated string if string contains plus symbol.
85 *
86 * @param identifier string from yang file
87 * @param yangConstruct yang construct for creating error message
88 * @param ctx yang construct's context to get the line number and character position
89 * @return concatenated string after removing double quotes
90 */
91 public static String getValidIdentifier(String identifier, YangConstructType yangConstruct, ParserRuleContext ctx) {
92
93 String identifierString = removeQuotesAndHandleConcat(identifier);
94 ParserException parserException;
95
96 if (identifierString.length() > IDENTIFIER_LENGTH) {
97 parserException = new ParserException("YANG file error : " +
98 YangConstructType.getYangConstructType(yangConstruct) + " name " + identifierString + " is " +
99 "greater than 64 characters.");
100 } else if (!IDENTIFIER_PATTERN.matcher(identifierString).matches()) {
101 parserException = new ParserException("YANG file error : " +
102 YangConstructType.getYangConstructType(yangConstruct) + " name " + identifierString + " is not " +
103 "valid.");
Vidyashree Rama210c01d2016-05-20 16:29:25 +0530104 } else if (identifierString.toLowerCase().startsWith(XML)) {
105 parserException = new ParserException("YANG file error : " +
106 YangConstructType.getYangConstructType(yangConstruct) + " identifier " + identifierString +
107 " must not start with (('X'|'x') ('M'|'m') ('L'|'l')).");
Vidyashree Rama468f8282016-03-04 19:08:35 +0530108 } else {
109 return identifierString;
110 }
111
112 parserException.setLine(ctx.getStart().getLine());
113 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
114 throw parserException;
115 }
116
117 /**
118 * Validates the revision date.
119 *
120 * @param dateToValidate input revision date
121 * @return validation result, true for success, false for failure
122 */
123 public static boolean isDateValid(String dateToValidate) {
Vidyashree Ramabe0f6da2016-05-09 11:45:05 +0530124 if (dateToValidate == null || !dateToValidate.matches(DATE_PATTERN)) {
Vidyashree Rama468f8282016-03-04 19:08:35 +0530125 return false;
126 }
127
janani bcc9ac302016-03-24 12:43:48 +0530128 SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
Vidyashree Rama468f8282016-03-04 19:08:35 +0530129 sdf.setLenient(false);
130
131 try {
132 //if not valid, it will throw ParseException
133 sdf.parse(dateToValidate);
134 } catch (ParseException e) {
135 return false;
136 }
137
138 return true;
139 }
Vidyashree Rama8a6b1282016-03-15 10:18:25 +0530140
141 /**
142 * Validates YANG version.
143 *
144 * @param ctx version context object of the grammar rule
145 * @return valid version
146 */
147 public static byte getValidVersion(GeneratedYangParser.YangVersionStatementContext ctx) {
148
149 String value = removeQuotesAndHandleConcat(ctx.version().getText());
150 if (!value.equals(ONE)) {
151 ParserException parserException = new ParserException("YANG file error: Input version not supported");
152 parserException.setLine(ctx.getStart().getLine());
153 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
154 throw parserException;
155 }
156
157 return Byte.valueOf(value);
158 }
159
160 /**
161 * Validates non negative integer value.
162 *
163 * @param integerValue integer to be validated
164 * @param yangConstruct yang construct for creating error message
165 * @param ctx context object of the grammar rule
166 * @return valid non negative integer value
167 */
168 public static int getValidNonNegativeIntegerValue(String integerValue, YangConstructType yangConstruct,
Bharat saraswald9822e92016-04-05 15:13:44 +0530169 ParserRuleContext ctx) {
Vidyashree Rama8a6b1282016-03-15 10:18:25 +0530170
171 String value = removeQuotesAndHandleConcat(integerValue);
172 if (!value.matches(NON_NEGATIVE_INTEGER_PATTERN)) {
173 ParserException parserException = new ParserException("YANG file error : " +
174 YangConstructType.getYangConstructType(yangConstruct) + " value " + value + " is not " +
175 "valid.");
176 parserException.setLine(ctx.getStart().getLine());
177 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
178 throw parserException;
179 }
180
Vidyashree Rama210c01d2016-05-20 16:29:25 +0530181 int valueInInteger;
182 try {
183 valueInInteger = Integer.parseInt(value);
184 } catch (NumberFormatException e) {
185 ParserException parserException = new ParserException("YANG file error : " +
186 YangConstructType.getYangConstructType(yangConstruct) + " value " + value + " is not " +
187 "valid.");
188 parserException.setLine(ctx.getStart().getLine());
189 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
190 throw parserException;
191 }
192 return valueInInteger;
Vidyashree Rama8a6b1282016-03-15 10:18:25 +0530193 }
194
195 /**
Vidyashree Rama1db15562016-05-17 16:16:15 +0530196 * Validates integer value.
197 *
198 * @param integerValue integer to be validated
199 * @param yangConstruct yang construct for creating error message
200 * @param ctx context object of the grammar rule
201 * @return valid integer value
202 */
203 public static int getValidIntegerValue(String integerValue, YangConstructType yangConstruct,
204 ParserRuleContext ctx) {
205
206 String value = removeQuotesAndHandleConcat(integerValue);
207 if (!INTEGER_PATTERN.matcher(value).matches()) {
208 ParserException parserException = new ParserException("YANG file error : " +
209 YangConstructType.getYangConstructType(yangConstruct) + " value " + value + " is not " +
210 "valid.");
211 parserException.setLine(ctx.getStart().getLine());
212 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
213 throw parserException;
214 }
215
216 int valueInInteger;
217 try {
218 valueInInteger = Integer.parseInt(value);
219 } catch (NumberFormatException e) {
220 ParserException parserException = new ParserException("YANG file error : " +
221 YangConstructType.getYangConstructType(yangConstruct) + " value " + value + " is not " +
222 "valid.");
223 parserException.setLine(ctx.getStart().getLine());
224 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
225 throw parserException;
226 }
227 return valueInInteger;
228 }
229
230 /**
Vidyashree Rama8a6b1282016-03-15 10:18:25 +0530231 * Validates boolean value.
232 *
233 * @param booleanValue value to be validated
234 * @param yangConstruct yang construct for creating error message
235 * @param ctx context object of the grammar rule
236 * @return boolean value either true or false
237 */
238 public static boolean getValidBooleanValue(String booleanValue, YangConstructType yangConstruct,
Bharat saraswald9822e92016-04-05 15:13:44 +0530239 ParserRuleContext ctx) {
Vidyashree Rama8a6b1282016-03-15 10:18:25 +0530240
241 String value = removeQuotesAndHandleConcat(booleanValue);
Vidyashree Rama1db15562016-05-17 16:16:15 +0530242 if (value.equals(TRUE)) {
Vidyashree Rama8a6b1282016-03-15 10:18:25 +0530243 return true;
Vidyashree Rama1db15562016-05-17 16:16:15 +0530244 } else if (value.equals(FALSE)) {
Vidyashree Rama8a6b1282016-03-15 10:18:25 +0530245 return false;
246 } else {
247 ParserException parserException = new ParserException("YANG file error : " +
248 YangConstructType.getYangConstructType(yangConstruct) + " value " + value + " is not " +
249 "valid.");
250 parserException.setLine(ctx.getStart().getLine());
251 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
252 throw parserException;
253 }
254 }
janani bcc9ac302016-03-24 12:43:48 +0530255
256 /**
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530257 * Returns current date and makes it in usable format for revision.
janani bcc9ac302016-03-24 12:43:48 +0530258 *
259 * @return usable current date format for revision
260 */
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530261 public static Date getCurrentDateForRevision() {
janani bcc9ac302016-03-24 12:43:48 +0530262
janani bcc9ac302016-03-24 12:43:48 +0530263 SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530264
265 Date date = new Date();
266 String dateInString = dateFormat.format(date);
267 try {
268 //if not valid, it will throw ParseException
269 Date now = dateFormat.parse(dateInString);
270 return date;
271 } catch (ParseException e) {
272 ParserException parserException = new ParserException("YANG file error: Input date is not correct");
273 throw parserException;
274 }
janani bcc9ac302016-03-24 12:43:48 +0530275 }
Gaurav Agrawalbd804472016-03-25 11:25:36 +0530276
277 /**
278 * Checks and return valid node identifier.
279 *
280 * @param nodeIdentifierString string from yang file
281 * @param yangConstruct yang construct for creating error message
282 * @param ctx yang construct's context to get the line number and character position
283 * @return valid node identifier
284 */
Vinod Kumar Sd4deb062016-04-15 18:08:57 +0530285 public static YangNodeIdentifier getValidNodeIdentifier(String nodeIdentifierString,
286 YangConstructType yangConstruct, ParserRuleContext ctx) {
Gaurav Agrawalbd804472016-03-25 11:25:36 +0530287 String tmpIdentifierString = removeQuotesAndHandleConcat(nodeIdentifierString);
288 String[] tmpData = tmpIdentifierString.split(Pattern.quote(COLON));
289 if (tmpData.length == 1) {
290 YangNodeIdentifier nodeIdentifier = new YangNodeIdentifier();
janani b6240d292016-05-17 18:20:33 +0530291 checkForUnsupportedTypes(tmpData[0], yangConstruct, ctx);
Gaurav Agrawalbd804472016-03-25 11:25:36 +0530292 nodeIdentifier.setName(getValidIdentifier(tmpData[0], yangConstruct, ctx));
293 return nodeIdentifier;
294 } else if (tmpData.length == 2) {
295 YangNodeIdentifier nodeIdentifier = new YangNodeIdentifier();
296 nodeIdentifier.setPrefix(getValidIdentifier(tmpData[0], yangConstruct, ctx));
297 nodeIdentifier.setName(getValidIdentifier(tmpData[1], yangConstruct, ctx));
298 return nodeIdentifier;
299 } else {
300 ParserException parserException = new ParserException("YANG file error : " +
301 YangConstructType.getYangConstructType(yangConstruct) + " name " + nodeIdentifierString +
302 " is not valid.");
303 parserException.setLine(ctx.getStart().getLine());
304 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
305 throw parserException;
306 }
307 }
Vidyashree Rama25bf4d02016-03-29 14:37:02 +0530308
309 /**
janani b6240d292016-05-17 18:20:33 +0530310 * Checks whether the type is an unsupported type.
311 *
312 * @param typeName name of the type
313 * @param yangConstruct yang construct to check if it is type
314 * @param ctx yang construct's context to get the line number and character position
315 */
316 private static void checkForUnsupportedTypes(String typeName,
317 YangConstructType yangConstruct, ParserRuleContext ctx) {
318
319 if (yangConstruct == YangConstructType.TYPE_DATA) {
320 if (typeName.equalsIgnoreCase(LEAFREF)) {
321 handleUnsupportedYangConstruct(YangConstructType.LEAFREF_DATA,
322 ctx, CURRENTLY_UNSUPPORTED);
323 } else if (typeName.equalsIgnoreCase(IDENTITYREF)) {
324 handleUnsupportedYangConstruct(YangConstructType.IDENTITYREF_DATA,
325 ctx, CURRENTLY_UNSUPPORTED);
326 } else if (typeName.equalsIgnoreCase(INSTANCE_IDENTIFIER)) {
327 handleUnsupportedYangConstruct(YangConstructType.INSTANCE_IDENTIFIER_DATA,
328 ctx, CURRENTLY_UNSUPPORTED);
329 }
330 }
331 }
332
333 /**
Vidyashree Rama25bf4d02016-03-29 14:37:02 +0530334 * Checks and return valid absolute schema node id.
335 *
336 * @param argumentString string from yang file
337 * @param yangConstructType yang construct for creating error message
338 * @param ctx yang construct's context to get the line number and character position
339 * @return target nodes list of absolute schema node id
340 */
341 public static List<YangNodeIdentifier> getValidAbsoluteSchemaNodeId(String argumentString,
342 YangConstructType yangConstructType, ParserRuleContext ctx) {
343
344 List<YangNodeIdentifier> targetNodes = new LinkedList<>();
345 YangNodeIdentifier yangNodeIdentifier;
346 String tmpSchemaNodeId = removeQuotesAndHandleConcat(argumentString);
347
348 // absolute-schema-nodeid = 1*("/" node-identifier)
349 if (!tmpSchemaNodeId.startsWith(SLASH)) {
350 ParserException parserException = new ParserException("YANG file error : " +
351 YangConstructType.getYangConstructType(yangConstructType) + " name " + argumentString +
352 "is not valid");
353 parserException.setLine(ctx.getStart().getLine());
354 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
355 throw parserException;
356 }
357 String[] tmpData = tmpSchemaNodeId.replaceFirst(CARET + SLASH, EMPTY_STRING).split(SLASH);
358 for (String nodeIdentifiers : tmpData) {
359 yangNodeIdentifier = getValidNodeIdentifier(nodeIdentifiers, yangConstructType, ctx);
360 targetNodes.add(yangNodeIdentifier);
361 }
362 return targetNodes;
363 }
Vidyashree Rama1db15562016-05-17 16:16:15 +0530364
365 /**
366 * Throws parser exception for unsupported YANG constructs.
367 *
368 * @param yangConstructType yang construct for creating error message
369 * @param ctx yang construct's context to get the line number and character position
370 * @param errorInfo error information
371 */
372 public static void handleUnsupportedYangConstruct(YangConstructType yangConstructType,
373 ParserRuleContext ctx, String errorInfo) {
374 ParserException parserException = new ParserException(YANG_FILE_ERROR
375 + QUOTES + YangConstructType.getYangConstructType(yangConstructType) + QUOTES
376 + errorInfo);
377 parserException.setLine(ctx.getStart().getLine());
378 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
379 throw parserException;
380 }
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530381
382 /**
383 * Returns date and makes it in usable format for revision.
384 *
385 * @param dateInString date argument string from yang file
386 * @param ctx yang construct's context to get the line number and character position
387 * @return date format for revision
388 */
389 public static Date getValidDateFromString(String dateInString, ParserRuleContext ctx) {
390 String dateArgument = removeQuotesAndHandleConcat(dateInString);
391 if (dateArgument == null || !dateArgument.matches(DATE_PATTERN)) {
392 ParserException parserException = new ParserException("YANG file error: Input date is not correct");
393 parserException.setLine(ctx.getStart().getLine());
394 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
395 throw parserException;
396 }
397
398 SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
399 sdf.setLenient(false);
400
401 try {
402 //if not valid, it will throw ParseException
403 Date date = sdf.parse(dateArgument);
404 return date;
405 } catch (ParseException e) {
406 ParserException parserException = new ParserException("YANG file error: Input date is not correct");
407 parserException.setLine(ctx.getStart().getLine());
408 parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
409 throw parserException;
410 }
411 }
Vidyashree Rama468f8282016-03-04 19:08:35 +0530412}