Merge "Finding data nodes in choices and cases."
authorEd Warnicke <eaw@cisco.com>
Fri, 29 Nov 2013 14:20:34 +0000 (14:20 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 29 Nov 2013 14:20:34 +0000 (14:20 +0000)
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/SchemaLocation.java [deleted file]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/ToJsonChoiceCaseTest.java
opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/choice/choice.yang
opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/choice/xml/data_case_defined_without_case.xml [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/choice/xml/data_more_choices_same_level.xml
opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/choice/xml/data_more_choices_same_level_various_paths_err.xml [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/choice/xml/data_three_choices_same_level.xml [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/choice/xml/data_various_path_err.xml [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/choice/xml/data_various_path.xml with 100% similarity]

index 36b46a171cde4706a1b7e22d17ed4c7e00ccdc90..9608d65e41ca82a13e2dada78b5ce5dfeb0728e7 100644 (file)
@@ -47,26 +47,13 @@ class JsonMapper {
         checkNotNull(parent);
         checkNotNull(parentSchema);
 
-        List<String> longestPathToElementViaChoiceCase = new ArrayList<>();
         for (Node<?> child : parent.getChildren()) {
-            Deque<String> choiceCasePathStack = new ArrayDeque<>(longestPathToElementViaChoiceCase);
-            SchemaLocation schemaLocation = findFirstSchemaForNode(child, parentSchema.getChildNodes(),
-                    choiceCasePathStack);
-
-            if (schemaLocation == null) {
-                if (!choiceCasePathStack.isEmpty()) {
-                    throw new UnsupportedDataTypeException("On choice-case path " + choiceCasePathStack
-                            + " wasn't found data schema for " + child.getNodeType().getLocalName());
-                } else {
-                    throw new UnsupportedDataTypeException("Probably the data node \""
-                            + child.getNodeType().getLocalName() + "\" is not conform to schema");
-                }
-            }
-
-            longestPathToElementViaChoiceCase = resolveLongerPath(longestPathToElementViaChoiceCase,
-                    schemaLocation.getLocation());
+            DataSchemaNode childSchema = findFirstSchemaForNode(child, parentSchema.getChildNodes());
 
-            DataSchemaNode childSchema = schemaLocation.getSchema();
+            if (childSchema == null) {
+                throw new UnsupportedDataTypeException("Probably the data node \"" + child.getNodeType().getLocalName()
+                        + "\" is not conform to schema");
+            }
 
             if (childSchema instanceof ContainerSchemaNode) {
                 Preconditions.checkState(child instanceof CompositeNode,
@@ -97,10 +84,7 @@ class JsonMapper {
         }
 
         for (Node<?> child : parent.getChildren()) {
-            SchemaLocation schemaLocation = findFirstSchemaForNode(child, parentSchema.getChildNodes(),
-                    new ArrayDeque<>(longestPathToElementViaChoiceCase));
-
-            DataSchemaNode childSchema = schemaLocation.getSchema();
+            DataSchemaNode childSchema = findFirstSchemaForNode(child, parentSchema.getChildNodes());
             if (childSchema instanceof LeafListSchemaNode) {
                 foundLeafLists.remove((LeafListSchemaNode) childSchema);
             } else if (childSchema instanceof ListSchemaNode) {
@@ -109,45 +93,17 @@ class JsonMapper {
         }
     }
 
-    private List<String> resolveLongerPath(List<String> l1, List<String> l2) {
-        return l1.size() > l2.size() ? l1 : l2;
-    }
-
-    private SchemaLocation findFirstSchemaForNode(Node<?> node, Set<DataSchemaNode> dataSchemaNode,
-            Deque<String> pathIterator) {
-        Map<String, ChoiceNode> choiceSubnodes = new HashMap<>();
+    private DataSchemaNode findFirstSchemaForNode(Node<?> node, Set<DataSchemaNode> dataSchemaNode) {
         for (DataSchemaNode dsn : dataSchemaNode) {
-            if (dsn instanceof ChoiceNode) {
-                choiceSubnodes.put(dsn.getQName().getLocalName(), (ChoiceNode) dsn);
-            } else if (node.getNodeType().getLocalName().equals(dsn.getQName().getLocalName())) {
-                return new SchemaLocation(dsn);
-            }
-        }
-
-        for (ChoiceNode choiceSubnode : choiceSubnodes.values()) {
-            if ((!pathIterator.isEmpty() && pathIterator.peekLast().equals(choiceSubnode.getQName().getLocalName()))
-                    || pathIterator.isEmpty()) {
-                String pathPartChoice = pathIterator.pollLast();
-                for (ChoiceCaseNode concreteCase : choiceSubnode.getCases()) {
-                    if ((!pathIterator.isEmpty() && pathIterator.peekLast().equals(
-                            concreteCase.getQName().getLocalName()))
-                            || pathIterator.isEmpty()) {
-                        String pathPartCase = pathIterator.pollLast();
-                        SchemaLocation schemaLocation = findFirstSchemaForNode(node, concreteCase.getChildNodes(),
-                                pathIterator);
-                        if (schemaLocation != null) {
-                            schemaLocation.addPathPart(concreteCase.getQName().getLocalName());
-                            schemaLocation.addPathPart(choiceSubnode.getQName().getLocalName());
-                            return schemaLocation;
-                        }
-                        if (pathPartCase != null) {
-                            pathIterator.addLast(pathPartCase);
-                        }
+            if (node.getNodeType().getLocalName().equals(dsn.getQName().getLocalName())) {
+                return dsn;
+            } else if (dsn instanceof ChoiceNode) {
+                for (ChoiceCaseNode choiceCase : ((ChoiceNode) dsn).getCases()) {
+                    DataSchemaNode foundDsn = findFirstSchemaForNode(node, choiceCase.getChildNodes());
+                    if (foundDsn != null) {
+                        return foundDsn;
                     }
                 }
-                if (pathPartChoice != null) {
-                    pathIterator.addLast(pathPartChoice);
-                }
             }
         }
         return null;
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/SchemaLocation.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/SchemaLocation.java
deleted file mode 100644 (file)
index 24055ce..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-package org.opendaylight.controller.sal.rest.impl;
-
-import java.util.*;
-
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-
-class SchemaLocation {
-    final private List<String> location = new ArrayList<>();
-    final private DataSchemaNode schema;
-
-    public SchemaLocation(DataSchemaNode schema) {
-        this.schema = schema;
-    }
-
-    DataSchemaNode getSchema() {
-        return schema;
-    }
-
-    List<String> getLocation() {
-        return location;
-    }
-
-    SchemaLocation addPathPart(String partOfPath) {
-        location.add(partOfPath);
-        return this;
-    }
-
-}
index 141ffdb75467f8db326c03763e83ce4cb2d27b74..8e3ff1d2ed4a998997181a897a1c8ff648099aaa 100644 (file)
@@ -25,39 +25,56 @@ public class ToJsonChoiceCaseTest {
     }
 
     /**
-     * Test when some data are in one case node and other in another. Exception
-     * expected!!
+     * Test when some data are in one case node and other in another. This isn't
+     * correct. Next Json validator should return error because nodes has to be
+     * from one case below concrete choice.
+     * 
      */
     @Test
-    public void compNodeDataOnVariousChoiceCasePathTest() {
-        boolean exceptionCatched = false;
+    public void nodeSchemasOnVariousChoiceCasePathTest() {
         try {
             TestUtils.writeCompNodeWithSchemaContextToJson(
-                    TestUtils.loadCompositeNode("/yang-to-json-conversion/choice/xml/data_various_path.xml"),
+                    TestUtils.loadCompositeNode("/yang-to-json-conversion/choice/xml/data_various_path_err.xml"),
                     "/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
-        } catch (UnsupportedDataTypeException e) {
-            exceptionCatched = true;
-
         } catch (WebApplicationException | IOException e) {
             // shouldn't end here
             assertTrue(false);
         }
+    }
 
-        assertTrue(exceptionCatched);
-
+    /**
+     * Test when some data are in one case node and other in another.
+     * Additionally data are loadef from various choices. This isn't
+     * correct. Next Json validator should return error because nodes has to be
+     * from one case below concrete choice.
+     * 
+     */
+    @Test
+    public void nodeSchemasOnVariousChoiceCasePathAndMultipleChoicesTest() {
+        try {
+            TestUtils
+                    .writeCompNodeWithSchemaContextToJson(
+                            TestUtils
+                                    .loadCompositeNode("/yang-to-json-conversion/choice/xml/data_more_choices_same_level_various_paths_err.xml"),
+                            "/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
+        } catch (WebApplicationException | IOException e) {
+            // shouldn't end here
+            assertTrue(false);
+        }
     }
 
     /**
      * Test when second level data are red first, then first and at the end
      * third level. Level represents pass through couple choice-case
      */
-    @Ignore
+
     @Test
-    public void compNodeDataWithRandomOrderAccordingLevel() {
+    public void nodeSchemasWithRandomOrderAccordingLevel() {
         try {
-            String jsonOutput = TestUtils.writeCompNodeWithSchemaContextToJson(
+            TestUtils.writeCompNodeWithSchemaContextToJson(
                     TestUtils.loadCompositeNode("/yang-to-json-conversion/choice/xml/data_random_level.xml"),
                     "/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
+
         } catch (WebApplicationException | IOException e) {
             // shouldn't end here
             assertTrue(false);
@@ -67,11 +84,10 @@ public class ToJsonChoiceCaseTest {
     /**
      * Test when element from no first case is used
      */
-    @Ignore
     @Test
-    public void compNodeDataNoFirstCase() {
+    public void nodeSchemasNotInFirstCase() {
         try {
-            String jsonOutput = TestUtils.writeCompNodeWithSchemaContextToJson(
+            TestUtils.writeCompNodeWithSchemaContextToJson(
                     TestUtils.loadCompositeNode("/yang-to-json-conversion/choice/xml/data_no_first_case.xml"),
                     "/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
         } catch (WebApplicationException | IOException e) {
@@ -83,11 +99,10 @@ public class ToJsonChoiceCaseTest {
     /**
      * Test when element in case is list
      */
-    @Ignore
     @Test
-    public void compNodeDataAsList() {
+    public void nodeSchemaAsList() {
         try {
-            String jsonOutput = TestUtils.writeCompNodeWithSchemaContextToJson(
+            TestUtils.writeCompNodeWithSchemaContextToJson(
                     TestUtils.loadCompositeNode("/yang-to-json-conversion/choice/xml/data_list.xml"),
                     "/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
         } catch (WebApplicationException | IOException e) {
@@ -99,11 +114,10 @@ public class ToJsonChoiceCaseTest {
     /**
      * Test when element in case is container
      */
-    @Ignore
     @Test
-    public void compNodeDataAsContainer() {
+    public void nodeSchemaAsContainer() {
         try {
-            String jsonOutput = TestUtils.writeCompNodeWithSchemaContextToJson(
+            TestUtils.writeCompNodeWithSchemaContextToJson(
                     TestUtils.loadCompositeNode("/yang-to-json-conversion/choice/xml/data_container.xml"),
                     "/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
         } catch (WebApplicationException | IOException e) {
@@ -113,13 +127,12 @@ public class ToJsonChoiceCaseTest {
     }
 
     /**
-     * Test when element in case is container
+     * Test when element in case is leaflist
      */
-    @Ignore
     @Test
-    public void compNodeDataAsLeafList() {
+    public void nodeSchemaAsLeafList() {
         try {
-            String jsonOutput = TestUtils.writeCompNodeWithSchemaContextToJson(
+            TestUtils.writeCompNodeWithSchemaContextToJson(
                     TestUtils.loadCompositeNode("/yang-to-json-conversion/choice/xml/data_leaflist.xml"),
                     "/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
         } catch (WebApplicationException | IOException e) {
@@ -128,4 +141,50 @@ public class ToJsonChoiceCaseTest {
         }
     }
 
+    /**
+     * 
+     */
+    @Test
+    public void nodeSchemasInMultipleChoicesTest() {
+        try {
+            TestUtils
+                    .writeCompNodeWithSchemaContextToJson(TestUtils
+                            .loadCompositeNode("/yang-to-json-conversion/choice/xml/data_more_choices_same_level.xml"),
+                            "/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
+        } catch (WebApplicationException | IOException e) {
+            // shouldn't end here
+            assertTrue(false);
+        }
+    }
+
+    /**
+     * Test whether is possible to find data schema for node which is specified
+     * as dirrect subnode of choice (case without CASE key word)
+     */
+    @Test
+    public void nodeSchemasInCaseNotDefinedWithCaseKeyword() {
+        try {
+            TestUtils.writeCompNodeWithSchemaContextToJson(TestUtils
+                    .loadCompositeNode("/yang-to-json-conversion/choice/xml/data_case_defined_without_case.xml"),
+                    "/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
+        } catch (WebApplicationException | IOException e) {
+            // shouldn't end here
+            assertTrue(false);
+        }
+    }
+
+    /**
+     * Test of multiple use of choices
+     */
+    @Test
+    public void nodeSchemasInThreeChoicesAtSameLevel() {
+        try {
+            TestUtils.writeCompNodeWithSchemaContextToJson(TestUtils
+                    .loadCompositeNode("/yang-to-json-conversion/choice/xml/data_three_choices_same_level.xml"),
+                    "/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
+        } catch (WebApplicationException | IOException e) {
+            // shouldn't end here
+            assertTrue(false);
+        }
+    }
 }
index 8b02a9297991a00ed66417fbc3b57f52dd417da4..a6a32df52ee762c1a395908a86af81e6378c56a5 100644 (file)
@@ -10,7 +10,7 @@ module choice-case-test {
                        type string;
                }               
                
-               choice choi1 {
+               choice choi1 {            
                        case a1 {
                                leaf lf1a {
                                        type uint16;    
@@ -59,6 +59,9 @@ module choice-case-test {
                                        type string;
                                }
                        }
+            leaf e1 {
+                type uint32;
+            }
                }
                
                choice choi2 {
@@ -73,6 +76,31 @@ module choice-case-test {
                                }
                        }
                }
+        
+        choice choi4 {
+            case a4 {
+                list lst4a {
+                    choice choi4aa {
+                        case aa1 {
+                            leaf lf4aa {
+                                type string;
+                            }
+                        }
+                        case ab2 {
+                            leaf lf4ab {
+                                type int16;
+                            }
+                        }
+                    }
+                }
+            }
+            case b4 {
+                leaf-list lflst4b {
+                    type uint32;
+                }
+            }
+            
+        }
                
 /*              equal identifiers in various cases are illegal 7.9.2 rfc6020 */
 /*             
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/choice/xml/data_case_defined_without_case.xml b/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/choice/xml/data_case_defined_without_case.xml
new file mode 100644 (file)
index 0000000..b669842
--- /dev/null
@@ -0,0 +1,4 @@
+<cont>
+       <e1>45</e1>
+       <lf2b>lf2b val</lf2b>
+</cont>
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/choice/xml/data_more_choices_same_level_various_paths_err.xml b/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/choice/xml/data_more_choices_same_level_various_paths_err.xml
new file mode 100644 (file)
index 0000000..331c8ae
--- /dev/null
@@ -0,0 +1,7 @@
+<cont>
+       <cont1c>
+               <lf11c>lf11c val</lf11c>
+       </cont1c>
+       <lf2b>lf2b value</lf2b>
+       <lf2a>lf2b value</lf2a>
+</cont>
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/choice/xml/data_three_choices_same_level.xml b/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/choice/xml/data_three_choices_same_level.xml
new file mode 100644 (file)
index 0000000..ecc0caa
--- /dev/null
@@ -0,0 +1,13 @@
+<cont>
+       <lf1aaa>lf1aaa value</lf1aaa>
+       <lf2b>lf2b value</lf2b>
+       <lst4a>
+               <lf4ab>33</lf4ab>
+       </lst4a>
+       <lst4a>
+               <lf4ab>33</lf4ab>
+       </lst4a>
+       <lst4a>
+               <lf4ab>37</lf4ab>
+       </lst4a>
+</cont>
\ No newline at end of file