Fix license header violations in yang-parser-impl
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / impl / ParserListenerUtils.java
index 933ac6b6d4f17f489efb3fa878ea868bbf7bfb94..49d6d986a3dc27837e50df14b16e70dc0fd4e426 100644 (file)
@@ -3,25 +3,26 @@
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/eplv10.html
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
+
 package org.opendaylight.yangtools.yang.parser.impl;
 
 import static com.google.common.base.Preconditions.checkState;
 
 import com.google.common.base.CharMatcher;
 import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
 import com.google.common.base.Splitter;
-import com.google.common.collect.Lists;
-
+import com.google.common.collect.Sets;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
-
+import java.util.Set;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
 import org.antlr.v4.runtime.ParserRuleContext;
 import org.antlr.v4.runtime.tree.ParseTree;
 import org.antlr.v4.runtime.tree.TerminalNode;
@@ -183,13 +184,13 @@ public final class ParserListenerUtils {
                 continue;
             }
             /*
-             * 
+             *
              * It is safe not to check last argument to be same
              * grammars enforces that.
-             * 
+             *
              * FIXME: Introduce proper escaping and translation of escaped
              * characters here.
-             * 
+             *
              */
             sb.append(quoteMatcher.removeFrom(str.substring(1, str.length()-1)));
         }
@@ -306,15 +307,15 @@ public final class ParserListenerUtils {
     }
 
     /**
-     * Create java.util.List of key node names.
+     * Create java.util.LinkedHashSet of key node names.
      *
      * @param ctx
      *            Key_stmtContext context
-     * @return YANG list key as java.util.List of key node names
+     * @return YANG list key as java.util.LinkedHashSet of key node names
      */
-    public static List<String> createListKey(final Key_stmtContext ctx) {
-        String keyDefinition = stringFromNode(ctx);
-        return Lists.newArrayList(KEYDEF_SPLITTER.split(keyDefinition));
+    public static Set<String> createListKey(final Key_stmtContext ctx) {
+        final String keyDefinition = stringFromNode(ctx);
+        return Sets.<String>newLinkedHashSet(KEYDEF_SPLITTER.split(keyDefinition));
     }
 
     /**
@@ -378,7 +379,15 @@ public final class ParserListenerUtils {
             ParseTree child = ctx.getChild(i);
             if (child instanceof Value_stmtContext) {
                 String valueStr = stringFromNode(child);
-                value = Integer.valueOf(valueStr);
+                try {
+                    // yang enum value has same restrictions as JAVA Integer
+                    value = Integer.valueOf(valueStr);
+                } catch (NumberFormatException e) {
+                    String err = String
+                            .format("Error on enum '%s': the enum value MUST be in the range from -2147483648 to 2147483647, but was: %s",
+                                    name, valueStr);
+                    throw new YangParseException(moduleName, ctx.getStart().getLine(), err, e);
+                }
             } else if (child instanceof Description_stmtContext) {
                 description = stringFromNode(child);
             } else if (child instanceof Reference_stmtContext) {
@@ -391,10 +400,6 @@ public final class ParserListenerUtils {
         if (value == null) {
             value = highestValue + 1;
         }
-        if (value < -2147483648 || value > 2147483647) {
-            throw new YangParseException(moduleName, ctx.getStart().getLine(), "Error on enum '" + name
-                    + "': the enum value MUST be in the range from -2147483648 to 2147483647, but was: " + value);
-        }
 
         EnumPairImpl result = new EnumPairImpl();
         result.qname = path.getPathTowardsRoot().iterator().next();
@@ -716,7 +721,7 @@ public final class ParserListenerUtils {
      *            type body
      * @return list of pattern constraints
      */
-    private static List<PatternConstraint> getPatternConstraint(final Type_body_stmtsContext ctx) {
+    private static List<PatternConstraint> getPatternConstraint(final Type_body_stmtsContext ctx, final String moduleName) {
         List<PatternConstraint> patterns = new ArrayList<>();
 
         for (int i = 0; i < ctx.getChildCount(); i++) {
@@ -725,7 +730,11 @@ public final class ParserListenerUtils {
                 for (int j = 0; j < stringRestrChild.getChildCount(); j++) {
                     ParseTree lengthChild = stringRestrChild.getChild(j);
                     if (lengthChild instanceof Pattern_stmtContext) {
-                        patterns.add(parsePatternConstraint((Pattern_stmtContext) lengthChild));
+                        final PatternConstraint constraint = parsePatternConstraint((Pattern_stmtContext) lengthChild,
+                            moduleName);
+                        if (constraint != null) {
+                            patterns.add(constraint);
+                        }
                     }
                 }
             }
@@ -740,7 +749,7 @@ public final class ParserListenerUtils {
      *            pattern context
      * @return PatternConstraint object
      */
-    private static PatternConstraint parsePatternConstraint(final Pattern_stmtContext ctx) {
+    private static PatternConstraint parsePatternConstraint(final Pattern_stmtContext ctx, final String moduleName) {
         Optional<String> description = Optional.absent();
         Optional<String> reference = Optional.absent();
         for (int i = 0; i < ctx.getChildCount(); i++) {
@@ -751,8 +760,31 @@ public final class ParserListenerUtils {
                 reference = Optional.of(stringFromNode(child));
             }
         }
-        String pattern = parsePatternString(ctx);
-        return BaseConstraints.newPatternConstraint(pattern, description, reference);
+        final String rawPattern = parsePatternString(ctx);
+        final String pattern = wrapPattern(rawPattern);
+        if (isValidPattern(pattern, ctx, moduleName)) {
+            return BaseConstraints.newPatternConstraint(pattern, description, reference);
+        }
+        return null;
+    }
+
+    private static String wrapPattern(String rawPattern) {
+        final StringBuilder wrapPatternBuilder = new StringBuilder(rawPattern.length() + 2);
+        wrapPatternBuilder.append('^');
+        wrapPatternBuilder.append(rawPattern);
+        wrapPatternBuilder.append('$');
+        return wrapPatternBuilder.toString();
+    }
+
+    private static boolean isValidPattern(final String pattern, final Pattern_stmtContext ctx, final String moduleName) {
+        try {
+            Pattern.compile(pattern);
+            return true;
+        } catch (PatternSyntaxException ex) {
+            LOG.warn("Unable to compile pattern defined in module {} at line {}. Error message: {}",
+                moduleName, ctx.getStart().getLine(), ex.getMessage());
+        }
+        return false;
     }
 
     /**
@@ -1056,7 +1088,7 @@ public final class ParserListenerUtils {
 
         List<RangeConstraint> rangeStatements = getRangeConstraints(typeBody, moduleBuilder.getName());
         List<LengthConstraint> lengthStatements = getLengthConstraints(typeBody, moduleBuilder.getName());
-        List<PatternConstraint> patternStatements = getPatternConstraint(typeBody);
+        List<PatternConstraint> patternStatements = getPatternConstraint(typeBody, moduleBuilder.getName());
         Integer fractionDigits = getFractionDigits(typeBody, moduleBuilder.getName());
 
         if (parent instanceof TypeDefinitionBuilder && !(parent instanceof UnionTypeBuilder)) {
@@ -1106,7 +1138,7 @@ public final class ParserListenerUtils {
 
         Integer fractionDigits = getFractionDigits(typeBody, moduleName);
         List<LengthConstraint> lengthStatements = getLengthConstraints(typeBody, moduleName);
-        List<PatternConstraint> patternStatements = getPatternConstraint(typeBody);
+        List<PatternConstraint> patternStatements = getPatternConstraint(typeBody, moduleName);
         List<RangeConstraint> rangeStatements = getRangeConstraints(typeBody, moduleName);
 
         TypeConstraints constraints = new TypeConstraints(moduleName, line);