Bug 4933: Yang parser does not accept deviate "not-supported" 14/32414/7
authorPeter Kajsa <pkajsa@cisco.com>
Tue, 12 Jan 2016 12:45:30 +0000 (13:45 +0100)
committerGerrit Code Review <gerrit@opendaylight.org>
Wed, 13 Jan 2016 14:24:49 +0000 (14:24 +0000)
The method parseDeviateFromString does not parse input string
to Deviate enum correctly. This problem occurs when yang keyword
does not match java indentifier of Deviate enum.

Change-Id: I188b9539c804a561b13adac9df247fd57fab8599
Signed-off-by: Peter Kajsa <pkajsa@cisco.com>
yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/Deviation.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/Utils.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/test/Bug4933Test.java [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/bugs/bug4933/correct/foo.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/bugs/bug4933/incorrect/foo.yang [new file with mode: 0644]

index 3a7cce85b546545f1c5f49b915a178e88cbb0991..69a920a6c5d27653babd646a5c5dc0355932a32e 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.yangtools.yang.model.api;
 
+import com.google.common.base.Preconditions;
 import java.util.List;
 
 /**
@@ -25,7 +26,20 @@ public interface Deviation {
      * definition.
      */
     enum Deviate {
-        NOT_SUPPORTED, ADD, REPLACE, DELETE
+        NOT_SUPPORTED("not-supported"), ADD("add"), REPLACE("replace"), DELETE("delete");
+
+        private final String keyword;
+
+        private Deviate(final String keyword) {
+            this.keyword = Preconditions.checkNotNull(keyword);
+        }
+
+        /**
+         * @return String that corresponds to the yang keyword.
+         */
+        public String getKeyword() {
+            return keyword;
+        }
     }
 
     /**
index 91301d02044df1baad6ae255cb0104a3d869aa4d..59a22343e13743e8d9531faf92dea4059bc94adb 100644 (file)
@@ -317,7 +317,8 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
             public StatementContextBase build() throws SourceException {
                 StatementContextBase<?, ?, ?> potential = null;
 
-                if (getDefinition().getPublicView() != Rfc6020Mapping.AUGMENT) {
+                StatementDefinition stmtDef = getDefinition().getPublicView();
+                if (stmtDef != Rfc6020Mapping.AUGMENT && stmtDef != Rfc6020Mapping.DEVIATION) {
                     potential = substatements.get(createIdentifier());
                 }
                 if (potential == null) {
index 3654785eb8e73800305c6d2a017a1dfc0a01063d..03996c932904314dd31dc1631547c4f09d5f1c74 100644 (file)
@@ -12,6 +12,8 @@ import com.google.common.base.CharMatcher;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Splitter;
 import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
 import com.google.common.collect.Iterables;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -19,7 +21,7 @@ import java.util.Collection;
 import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
-import java.util.Objects;
+import java.util.Map;
 import java.util.Set;
 import java.util.regex.Pattern;
 import javax.annotation.Nullable;
@@ -32,6 +34,7 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
 import org.opendaylight.yangtools.yang.model.api.Deviation;
+import org.opendaylight.yangtools.yang.model.api.Deviation.Deviate;
 import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
 import org.opendaylight.yangtools.yang.model.api.Status;
@@ -64,6 +67,15 @@ public final class Utils {
     private static final Splitter SPACE_SPLITTER = Splitter.on(' ').omitEmptyStrings().trimResults();
     private static final Pattern PATH_ABS = Pattern.compile("/[^/].*");
 
+    private static final Map<String, Deviate> KEYWORD_TO_DEVIATE_MAP;
+    static {
+        Builder<String, Deviate> keywordToDeviateMapBuilder = ImmutableMap.builder();
+        for (Deviate deviate : Deviation.Deviate.values()) {
+            keywordToDeviateMapBuilder.put(deviate.getKeyword(), deviate);
+        }
+        KEYWORD_TO_DEVIATE_MAP = keywordToDeviateMapBuilder.build();
+    }
+
     private static final ThreadLocal<XPathFactory> XPATH_FACTORY = new ThreadLocal<XPathFactory>() {
         @Override
         protected XPathFactory initialValue() {
@@ -301,20 +313,9 @@ public final class Utils {
                 .isAssignableFrom(UnknownStatementImpl.class);
     }
 
-    public static Deviation.Deviate parseDeviateFromString(final String deviate) {
-
-        // Yang constants should be lowercase so we have throw if value does not
-        // suit this
-        String deviateUpper = deviate.toUpperCase();
-        Preconditions.checkArgument(!Objects.equals(deviate, deviateUpper),
-            "String %s is not valid deviate argument", deviate);
-
-        // but Java enum is uppercase so we cannot use lowercase here
-        try {
-            return Deviation.Deviate.valueOf(deviateUpper);
-        } catch (IllegalArgumentException e) {
-            throw new IllegalArgumentException(String.format("String %s is not valid deviate argument", deviate), e);
-        }
+    public static Deviation.Deviate parseDeviateFromString(final String deviateKeyword) {
+        return Preconditions.checkNotNull(KEYWORD_TO_DEVIATE_MAP.get(deviateKeyword),
+                "String '%s' is not valid deviate argument", deviateKeyword);
     }
 
     public static Status parseStatus(final String value) {
diff --git a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/test/Bug4933Test.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/test/Bug4933Test.java
new file mode 100644 (file)
index 0000000..c9b71a0
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * 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/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.stmt.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.io.FileNotFoundException;
+import java.net.URISyntaxException;
+import java.util.Set;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.model.api.Deviation;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+
+public class Bug4933Test {
+
+    @Test
+    public void test() throws SourceException, ReactorException, FileNotFoundException, URISyntaxException {
+        SchemaContext context = StmtTestUtils.parseYangSources("/bugs/bug4933/correct");
+        assertNotNull(context);
+
+        Set<Deviation> deviations = context.getModules().iterator().next().getDeviations();
+        assertEquals(4, deviations.size());
+    }
+
+    @Test
+    public void incorrectKeywordTest() throws SourceException, ReactorException, FileNotFoundException,
+            URISyntaxException {
+        try {
+            StmtTestUtils.parseYangSources("/bugs/bug4933/incorrect");
+            fail("NullPointerException should be thrown.");
+        } catch (NullPointerException e) {
+            assertEquals("String 'not_supported' is not valid deviate argument", e.getMessage());
+        }
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/bugs/bug4933/correct/foo.yang b/yang/yang-parser-impl/src/test/resources/bugs/bug4933/correct/foo.yang
new file mode 100644 (file)
index 0000000..282e242
--- /dev/null
@@ -0,0 +1,38 @@
+module foo {
+    yang-version 1;
+    namespace "foo";
+    prefix foo;
+
+    container my-container {
+        leaf-list my-leaf-list {
+            type string;
+            max-elements 5;
+            must "0 != 1";
+        }
+    }
+
+    deviation /my-container/my-leaf-list {
+        deviate add {
+            min-elements 1;
+        }
+    }
+
+    deviation /my-container/my-leaf-list {
+        deviate replace {
+            max-elements 10;
+        }
+    }
+
+    deviation /my-container/my-leaf-list {
+        deviate delete {
+            must "0 != 1";
+        }
+    }
+
+    container my-container2 {
+    }
+
+    deviation /my-container2 {
+        deviate not-supported;
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/bugs/bug4933/incorrect/foo.yang b/yang/yang-parser-impl/src/test/resources/bugs/bug4933/incorrect/foo.yang
new file mode 100644 (file)
index 0000000..2993abd
--- /dev/null
@@ -0,0 +1,38 @@
+module foo {
+    yang-version 1;
+    namespace "foo";
+    prefix foo;
+
+    container my-container {
+        leaf-list my-leaf-list {
+            type string;
+            max-elements 5;
+            must "0 != 1";
+        }
+    }
+
+    deviation /my-container/my-leaf-list {
+        deviate add {
+            min-elements 1;
+        }
+    }
+
+    deviation /my-container/my-leaf-list {
+        deviate replace {
+            max-elements 10;
+        }
+    }
+
+    deviation /my-container/my-leaf-list {
+        deviate delete {
+            must "0 != 1";
+        }
+    }
+
+    container my-container2 {
+    }
+
+    deviation /my-container2 {
+        deviate not_supported;
+    }
+}