BUG 652 leafref CCE & BUG 720 colons problem 35/6335/4
authorJozef Gloncak <jgloncak@cisco.com>
Wed, 23 Apr 2014 12:56:10 +0000 (14:56 +0200)
committerJozef Gloncak <jgloncak@cisco.com>
Thu, 24 Apr 2014 09:15:24 +0000 (11:15 +0200)
BUG 652 leafref Class cast exception
By default if input data were in format which was possible to parse as
XPath if was done like this. It caused that for leafref which indexed to
instance-identifier the value was parsed as XPath and not as string.

BUG 720 colons problem in JSON
If input string contained colon (:) then it was dealed as namespace:value
and object of type IdentityValuesDTO was created (it is probable that
data could be of type identityref). If data wasn't of type leafref then it
was incorrectly processed as leafref.
The RestCodec was updated to correctly translate data (cases when data
contains ':' but aren't of type leafref)

Change-Id: I0cba06bce1b1c69f6901cc90d2b30a3735e5f57e
Signed-off-by: Jozef Gloncak <jgloncak@cisco.com>
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonReader.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestUtil.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlReader.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/IdentityValuesDTO.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestCodec.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlAndJsonToCnSnLeafRefTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/leafref/json/jsondata.json [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/leafref/xml/xmldata.xml [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/leafref/yang/leafref-module.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/leafref/yang/referenced-module.yang [new file with mode: 0644]

index e19f9f5805d9074cd946aee53d48e15510d9e0ef..4d9958ee6b4720b66fe5fc2a286e754630274e20 100644 (file)
@@ -122,7 +122,7 @@ class JsonReader {
         // it could be identityref Built-In Type
         URI namespace = getNamespaceFor(value);
         if (namespace != null) {
-            return new IdentityValuesDTO(namespace.toString(), getLocalNameFor(value), null);
+            return new IdentityValuesDTO(namespace.toString(), getLocalNameFor(value), null,value);
         }
         // it is not "prefix:value" but just "value"
         return value;
index 225eb7de6a7c16c1fea465659de373e0c65ef8ab..ba3e315e72728d9e0b9f7aa2c4ee78ff892ea428 100644 (file)
@@ -42,7 +42,7 @@ public final class RestUtil {
         if (xPathParts.length < 2) { // must be at least "/pr:node"
             return null;
         }
-        IdentityValuesDTO identityValuesDTO = new IdentityValuesDTO();
+        IdentityValuesDTO identityValuesDTO = new IdentityValuesDTO(value);
         for (int i = 1; i < xPathParts.length; i++) {
             String xPathPartTrimmed = xPathParts[i].trim();
             
index d807070dbdc21ad00429410ad360d5ce87607e6f..a75f6b4a85f8277bffa57ad6034abe6bc323f2a0 100644 (file)
@@ -205,7 +205,7 @@ public class XmlReader {
         if (namespaceAndValue.length == 2) {
             String namespace = startElement.getNamespaceContext().getNamespaceURI(namespaceAndValue[0]);
             if (namespace != null && !namespace.isEmpty()) {
-                return new IdentityValuesDTO(namespace, namespaceAndValue[1], namespaceAndValue[0]);
+                return new IdentityValuesDTO(namespace, namespaceAndValue[1], namespaceAndValue[0],value);
             }
         }
         // it is not "prefix:value" but just "value"
index 4fb75141d5d8e909143c93017727d740921b8a44..14a558967d2081a18e045192712ab0988cde6efa 100644 (file)
@@ -14,13 +14,19 @@ import java.util.List;
 public final class IdentityValuesDTO {
 
     private final List<IdentityValue> elementData = new ArrayList<>();
+    private final String originValue;
 
-    public IdentityValuesDTO(String namespace, String value, String prefix) {
+    public IdentityValuesDTO(String namespace, String value, String prefix,String originValue) {
         elementData.add(new IdentityValue(namespace, value, prefix));
+        this.originValue = originValue;
+    }
+    
+    public IdentityValuesDTO(String originValue) {
+        this.originValue = originValue;
     }
     
     public IdentityValuesDTO() {
-        
+        originValue = null;
     }
 
     public void add(String namespace, String value, String prefix) {
@@ -40,6 +46,10 @@ public final class IdentityValuesDTO {
     public String toString() {
         return elementData.toString();
     }
+    
+    public String getOriginValue() {
+        return originValue;
+    }
 
     public static final class IdentityValue {
 
index d6b530039eb681cf831956b9e61a83aad106ac64..42658d79f1468b97eaead0e852b57a125ee528b9 100644 (file)
@@ -89,6 +89,9 @@ public class RestCodec {
                             input == null ? "null" : input.getClass(), String.valueOf(input));
                     return null;
                 } else if (type instanceof LeafrefTypeDefinition) {
+                    if (input instanceof IdentityValuesDTO) {
+                        return LEAFREF_DEFAULT_CODEC.deserialize(((IdentityValuesDTO)input).getOriginValue());
+                    }
                     return LEAFREF_DEFAULT_CODEC.deserialize(input);
                 } else if (type instanceof InstanceIdentifierTypeDefinition) {
                     if (input instanceof IdentityValuesDTO) {
@@ -102,6 +105,9 @@ public class RestCodec {
                     TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>> typeAwarecodec = TypeDefinitionAwareCodec
                             .from(type);
                     if (typeAwarecodec != null) {
+                        if (input instanceof IdentityValuesDTO) {
+                            return typeAwarecodec.deserialize(((IdentityValuesDTO)input).getOriginValue());
+                        }
                         return typeAwarecodec.deserialize(String.valueOf(input));
                     } else {
                         logger.debug("Codec for type \"" + type.getQName().getLocalName()
@@ -162,7 +168,7 @@ public class RestCodec {
 
         @Override
         public IdentityValuesDTO serialize(QName data) {
-            return new IdentityValuesDTO(data.getNamespace().toString(), data.getLocalName(), data.getPrefix());
+            return new IdentityValuesDTO(data.getNamespace().toString(), data.getLocalName(), data.getPrefix(),null);
         }
 
         @Override
index fa478ac72e398ae928c619004023b8aae6cc68fe..a0bd99c5d2cc3dfc4b822125f43bdf104c8663ba 100644 (file)
@@ -669,7 +669,7 @@ class RestconfImpl implements RestconfService {
 
             if (schema.typeDefinition instanceof IdentityrefTypeDefinition) {
                 if (value instanceof String) {
-                    inputValue = new IdentityValuesDTO(nodeBuilder.namespace.toString, value as String, null)
+                    inputValue = new IdentityValuesDTO(nodeBuilder.namespace.toString, value as String, null,value as String);
                 } // else value is already instance of IdentityValuesDTO
             }
             
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlAndJsonToCnSnLeafRefTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlAndJsonToCnSnLeafRefTest.java
new file mode 100644 (file)
index 0000000..e5a737e
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2014 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.controller.sal.restconf.impl.test;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+import javax.ws.rs.WebApplicationException;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
+import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+
+public class XmlAndJsonToCnSnLeafRefTest extends YangAndXmlAndDataSchemaLoader {
+
+    @BeforeClass
+    public static void initialize() {
+        dataLoad("/leafref/yang", 2, "leafref-module", "cont");
+    }
+
+    @Test
+    public void loadXmlToCnSn() throws WebApplicationException, IOException, URISyntaxException {
+        CompositeNode cnSn = TestUtils.readInputToCnSn("/leafref/xml/xmldata.xml", XmlToCompositeNodeProvider.INSTANCE);
+        TestUtils.normalizeCompositeNode(cnSn, modules, schemaNodePath);
+        verifyContPredicate(cnSn, "/ns:cont/ns:lf1", "/cont/lf1", "/ns:cont/ns:lf1", "../lf1");
+    }
+
+    @Test
+    public void loadJsonToCnSn() throws WebApplicationException, IOException, URISyntaxException {
+        CompositeNode cnSn = TestUtils.readInputToCnSn("/leafref/json/jsondata.json",
+                JsonToCompositeNodeProvider.INSTANCE);
+        TestUtils.normalizeCompositeNode(cnSn, modules, schemaNodePath);
+        verifyContPredicate(cnSn, "/leafref-module:cont/leafref-module:lf1", "/leafref-module:cont/leafref-module:lf1",
+                "/referenced-module:cont/referenced-module:lf1", "/leafref-module:cont/leafref-module:lf1");
+    }
+
+    private void verifyContPredicate(CompositeNode cnSn, String... values) throws URISyntaxException {
+        Object lf2Value = null;
+        Object lf3Value = null;
+        Object lf4Value = null;
+        Object lf5Value = null;
+
+        for (Node<?> node : cnSn.getValue()) {
+            if (node.getNodeType().getLocalName().equals("lf2")) {
+                lf2Value = ((SimpleNode<?>) node).getValue();
+            } else if (node.getNodeType().getLocalName().equals("lf3")) {
+                lf3Value = ((SimpleNode<?>) node).getValue();
+            } else if (node.getNodeType().getLocalName().equals("lf4")) {
+                lf4Value = ((SimpleNode<?>) node).getValue();
+            } else if (node.getNodeType().getLocalName().equals("lf5")) {
+                lf5Value = ((SimpleNode<?>) node).getValue();
+            }
+        }
+        assertEquals(values[0], lf2Value);
+        assertEquals(values[1], lf3Value);
+        assertEquals(values[2], lf4Value);
+        assertEquals(values[3], lf5Value);
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/leafref/json/jsondata.json b/opendaylight/md-sal/sal-rest-connector/src/test/resources/leafref/json/jsondata.json
new file mode 100644 (file)
index 0000000..cbe455b
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "leafref-module:cont" : {
+        "lf4" : "/referenced-module:cont/referenced-module:lf1",
+        "lf2" : "/leafref-module:cont/leafref-module:lf1",
+        "lf3" : "/leafref-module:cont/leafref-module:lf1",
+        "lf5" : "/leafref-module:cont/leafref-module:lf1"
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/leafref/xml/xmldata.xml b/opendaylight/md-sal/sal-rest-connector/src/test/resources/leafref/xml/xmldata.xml
new file mode 100644 (file)
index 0000000..01bf092
--- /dev/null
@@ -0,0 +1,6 @@
+<cont xmlns="leafref:module">
+    <lf4 xmlns:ns="referenced:module">/ns:cont/ns:lf1</lf4>
+    <lf2 xmlns:ns="leafref:module">/ns:cont/ns:lf1</lf2>
+    <lf3 xmlns:ns="leafref:module">/cont/lf1</lf3>
+    <lf5 xmlns:ns="leafref:module">../lf1</lf5>
+</cont>
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/leafref/yang/leafref-module.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/leafref/yang/leafref-module.yang
new file mode 100644 (file)
index 0000000..00df290
--- /dev/null
@@ -0,0 +1,44 @@
+module leafref-module {
+  namespace "leafref:module";  
+
+
+  prefix "lfrfmodule";
+
+  import referenced-module { prefix refmod; revision-date 2014-04-17;} 
+
+  
+  revision 2014-04-17 {    
+  }
+  
+
+    container cont {
+        leaf lf1 {
+            type instance-identifier;
+        }
+
+        leaf lf2 {
+            type leafref {
+                path "../lf1";
+            }
+        }
+
+        leaf lf3 {
+            type leafref {
+                path "/refmod:cont/refmod:lf1";
+            }
+        }
+
+        leaf lf4 {
+            type leafref {
+                path "/cont/lf1";
+            }
+        }
+
+        leaf lf5 {
+            type leafref {
+                path "../lf1";
+            }
+        }
+        
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/leafref/yang/referenced-module.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/leafref/yang/referenced-module.yang
new file mode 100644 (file)
index 0000000..b6de719
--- /dev/null
@@ -0,0 +1,13 @@
+module referenced-module {
+  namespace "referenced:module";  
+
+  prefix "refmodule";
+  revision 2014-04-17 {    
+  }
+
+    container cont {
+        leaf lf1 {
+            type instance-identifier;
+        }
+    }
+}
\ No newline at end of file