Bug 6099 - ControllerContext#addKeyValue ignores key type when key is derived 86/45486/13
authorJakub Toth <jatoth@cisco.com>
Mon, 12 Sep 2016 13:30:06 +0000 (15:30 +0200)
committerJakub Toth <jatoth@cisco.com>
Mon, 3 Oct 2016 08:53:39 +0000 (10:53 +0200)
type from instance-identifier

 * added instance identifier support as value
 * JUnit test added

Change-Id: I4f6a070b5814ef2a33b68534d887745a099712c8
Signed-off-by: Jakub Toth <jatoth@cisco.com>
restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/StringModuleInstanceIdentifierCodec.java
restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestCodec.java
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/patch/Draft16StringModuleInstanceIdentifierCodec.java
restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/InstanceIdentifierTypeLeafTest.java [new file with mode: 0644]
restconf/sal-rest-connector/src/test/resources/instanceidentifier/iid-value.yang [new file with mode: 0644]

index a265ea95a212b40c6dc4bcd5698fb2de57e5c372..77489dec72694c138b0ed0b7e3e6531aee3f103e 100644 (file)
@@ -12,6 +12,7 @@ import com.google.common.base.Preconditions;
 import java.net.URI;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
+import org.opendaylight.restconf.utils.patch.Draft16StringModuleInstanceIdentifierCodec;
 import org.opendaylight.yangtools.yang.data.util.AbstractModuleStringInstanceIdentifierCodec;
 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
 import org.opendaylight.yangtools.yang.model.api.Module;
@@ -19,29 +20,29 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
 /**
  * @deprecated This class will be replaced by
- * {@link org.opendaylight.restconf.utils.patch.Draft11StringModuleInstanceIdentifierCodec}
+ *             {@link Draft16StringModuleInstanceIdentifierCodec}
  */
 @Deprecated
-final class StringModuleInstanceIdentifierCodec extends AbstractModuleStringInstanceIdentifierCodec {
+public final class StringModuleInstanceIdentifierCodec extends AbstractModuleStringInstanceIdentifierCodec {
 
     private final DataSchemaContextTree dataContextTree;
     private final SchemaContext context;
     private final String defaultPrefix;
 
-    StringModuleInstanceIdentifierCodec(SchemaContext context) {
+    public StringModuleInstanceIdentifierCodec(final SchemaContext context) {
         this.context = Preconditions.checkNotNull(context);
         this.dataContextTree = DataSchemaContextTree.from(context);
         this.defaultPrefix = "";
     }
 
-    StringModuleInstanceIdentifierCodec(SchemaContext context, @Nonnull String defaultPrefix) {
+    StringModuleInstanceIdentifierCodec(final SchemaContext context, @Nonnull final String defaultPrefix) {
         this.context = Preconditions.checkNotNull(context);
         this.dataContextTree = DataSchemaContextTree.from(context);
         this.defaultPrefix = defaultPrefix;
     }
 
     @Override
-    protected Module moduleForPrefix(@Nonnull String prefix) {
+    protected Module moduleForPrefix(@Nonnull final String prefix) {
         if (prefix.isEmpty() && !this.defaultPrefix.isEmpty()) {
             return this.context.findModuleByName(this.defaultPrefix, null);
         } else {
@@ -57,7 +58,7 @@ final class StringModuleInstanceIdentifierCodec extends AbstractModuleStringInst
 
     @Nullable
     @Override
-    protected String prefixForNamespace(@Nonnull URI namespace) {
+    protected String prefixForNamespace(@Nonnull final URI namespace) {
         final Module module = this.context.findModuleByNamespaceAndRevision(namespace, null);
         return module == null ? null : module.getName();
     }
index 77e83e367dc71afbfdb443574fabb89fd85f7bf6..c6224663efacbb3e654223c0f016d3161713cbbc 100644 (file)
@@ -14,6 +14,7 @@ import java.util.List;
 import java.util.Map;
 import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
 import org.opendaylight.netconf.sal.rest.impl.RestUtil;
+import org.opendaylight.netconf.sal.rest.impl.StringModuleInstanceIdentifierCodec;
 import org.opendaylight.netconf.sal.restconf.impl.IdentityValuesDTO.IdentityValue;
 import org.opendaylight.netconf.sal.restconf.impl.IdentityValuesDTO.Predicate;
 import org.opendaylight.yangtools.concepts.Codec;
@@ -63,16 +64,16 @@ public class RestCodec {
         private final TypeDefinition<?> type;
 
         private ObjectCodec(final TypeDefinition<?> typeDefinition, final DOMMountPoint mountPoint) {
-            type = RestUtil.resolveBaseTypeFrom(typeDefinition);
-            if (type instanceof IdentityrefTypeDefinition) {
-                identityrefCodec = new IdentityrefCodecImpl(mountPoint);
+            this.type = RestUtil.resolveBaseTypeFrom(typeDefinition);
+            if (this.type instanceof IdentityrefTypeDefinition) {
+                this.identityrefCodec = new IdentityrefCodecImpl(mountPoint);
             } else {
-                identityrefCodec = null;
+                this.identityrefCodec = null;
             }
-            if (type instanceof InstanceIdentifierTypeDefinition) {
-                instanceIdentifier = new InstanceIdentifierCodecImpl(mountPoint);
+            if (this.type instanceof InstanceIdentifierTypeDefinition) {
+                this.instanceIdentifier = new InstanceIdentifierCodecImpl(mountPoint);
             } else {
-                instanceIdentifier = null;
+                this.instanceIdentifier = null;
             }
         }
 
@@ -80,9 +81,9 @@ public class RestCodec {
         @Override
         public Object deserialize(final Object input) {
             try {
-                if (type instanceof IdentityrefTypeDefinition) {
+                if (this.type instanceof IdentityrefTypeDefinition) {
                     if (input instanceof IdentityValuesDTO) {
-                        return identityrefCodec.deserialize(input);
+                        return this.identityrefCodec.deserialize(input);
                     }
                     if(LOG.isDebugEnabled()) {
                         LOG.debug(
@@ -90,24 +91,24 @@ public class RestCodec {
                             input == null ? "null" : input.getClass(), String.valueOf(input));
                     }
                     return null;
-                } else if (type instanceof InstanceIdentifierTypeDefinition) {
+                } else if (this.type instanceof InstanceIdentifierTypeDefinition) {
                     if (input instanceof IdentityValuesDTO) {
-                        return instanceIdentifier.deserialize(input);
+                        return this.instanceIdentifier.deserialize(input);
+                    } else {
+                        final StringModuleInstanceIdentifierCodec codec = new StringModuleInstanceIdentifierCodec(
+                                ControllerContext.getInstance().getGlobalSchema());
+                        return codec.deserialize((String) input);
                     }
-                    LOG.info(
-                            "Value is not instance of InstanceIdentifierTypeDefinition but is {}. Therefore NULL is used as translation of  - {}",
-                            input == null ? "null" : input.getClass(), String.valueOf(input));
-                    return null;
                 } else {
                     final TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>> typeAwarecodec = TypeDefinitionAwareCodec
-                            .from(type);
+                            .from(this.type);
                     if (typeAwarecodec != null) {
                         if (input instanceof IdentityValuesDTO) {
                             return typeAwarecodec.deserialize(((IdentityValuesDTO) input).getOriginValue());
                         }
                         return typeAwarecodec.deserialize(String.valueOf(input));
                     } else {
-                        LOG.debug("Codec for type \"" + type.getQName().getLocalName()
+                        LOG.debug("Codec for type \"" + this.type.getQName().getLocalName()
                                 + "\" is not implemented yet.");
                         return null;
                     }
@@ -124,20 +125,20 @@ public class RestCodec {
         @Override
         public Object serialize(final Object input) {
             try {
-                if (type instanceof IdentityrefTypeDefinition) {
-                    return identityrefCodec.serialize(input);
-                } else if (type instanceof LeafrefTypeDefinition) {
+                if (this.type instanceof IdentityrefTypeDefinition) {
+                    return this.identityrefCodec.serialize(input);
+                } else if (this.type instanceof LeafrefTypeDefinition) {
                     return LEAFREF_DEFAULT_CODEC.serialize(input);
-                } else if (type instanceof InstanceIdentifierTypeDefinition) {
-                    return instanceIdentifier.serialize(input);
+                } else if (this.type instanceof InstanceIdentifierTypeDefinition) {
+                    return this.instanceIdentifier.serialize(input);
                 } else {
                     final TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>> typeAwarecodec = TypeDefinitionAwareCodec
-                            .from(type);
+                            .from(this.type);
                     if (typeAwarecodec != null) {
                         return typeAwarecodec.serialize(input);
                     } else {
                         if(LOG.isDebugEnabled()) {
-                            LOG.debug("Codec for type \"" + type.getQName().getLocalName()
+                            LOG.debug("Codec for type \"" + this.type.getQName().getLocalName()
                                 + "\" is not implemented yet.");
                         }
                         return null;
@@ -171,7 +172,7 @@ public class RestCodec {
         @Override
         public QName deserialize(final IdentityValuesDTO data) {
             final IdentityValue valueWithNamespace = data.getValuesWithNamespaces().get(0);
-            final Module module = getModuleByNamespace(valueWithNamespace.getNamespace(), mountPoint);
+            final Module module = getModuleByNamespace(valueWithNamespace.getNamespace(), this.mountPoint);
             if (module == null) {
                 LOG.info("Module was not found for namespace {}", valueWithNamespace.getNamespace());
                 LOG.info("Idenetityref will be translated as NULL for data - {}", String.valueOf(valueWithNamespace));
@@ -210,11 +211,11 @@ public class RestCodec {
             final IdentityValuesDTO identityValuesDTO = new IdentityValuesDTO();
             for (final PathArgument pathArgument : data.getPathArguments()) {
                 final IdentityValue identityValue = qNameToIdentityValue(pathArgument.getNodeType());
-                if (pathArgument instanceof NodeIdentifierWithPredicates && identityValue != null) {
+                if ((pathArgument instanceof NodeIdentifierWithPredicates) && (identityValue != null)) {
                     final List<Predicate> predicates = keyValuesToPredicateList(((NodeIdentifierWithPredicates) pathArgument)
                             .getKeyValues());
                     identityValue.setPredicates(predicates);
-                } else if (pathArgument instanceof NodeWithValue && identityValue != null) {
+                } else if ((pathArgument instanceof NodeWithValue) && (identityValue != null)) {
                     final List<Predicate> predicates = new ArrayList<>();
                     final String value = String.valueOf(((NodeWithValue) pathArgument).getValue());
                     predicates.add(new Predicate(null, value));
@@ -229,7 +230,7 @@ public class RestCodec {
         public YangInstanceIdentifier deserialize(final IdentityValuesDTO data) {
             final List<PathArgument> result = new ArrayList<PathArgument>();
             final IdentityValue valueWithNamespace = data.getValuesWithNamespaces().get(0);
-            final Module module = getModuleByNamespace(valueWithNamespace.getNamespace(), mountPoint);
+            final Module module = getModuleByNamespace(valueWithNamespace.getNamespace(), this.mountPoint);
             if (module == null) {
                 LOG.info("Module by namespace '{}' of first node in instance-identifier was not found.",
                         valueWithNamespace.getNamespace());
@@ -242,7 +243,7 @@ public class RestCodec {
             final List<IdentityValue> identities = data.getValuesWithNamespaces();
             for (int i = 0; i < identities.size(); i++) {
                 final IdentityValue identityValue = identities.get(i);
-                URI validNamespace = resolveValidNamespace(identityValue.getNamespace(), mountPoint);
+                URI validNamespace = resolveValidNamespace(identityValue.getNamespace(), this.mountPoint);
                 final DataSchemaNode node = ControllerContext.findInstanceDataChildByNameAndNamespace(
                         parentContainer, identityValue.getValue(), validNamespace);
                 if (node == null) {
@@ -269,7 +270,7 @@ public class RestCodec {
                         final DataNodeContainer listNode = (DataNodeContainer) node;
                         final Map<QName, Object> predicatesMap = new HashMap<>();
                         for (final Predicate predicate : identityValue.getPredicates()) {
-                            validNamespace = resolveValidNamespace(predicate.getName().getNamespace(), mountPoint);
+                            validNamespace = resolveValidNamespace(predicate.getName().getNamespace(), this.mountPoint);
                             final DataSchemaNode listKey = ControllerContext
                                     .findInstanceDataChildByNameAndNamespace(listNode, predicate.getName().getValue(),
                                             validNamespace);
@@ -284,7 +285,7 @@ public class RestCodec {
                     }
                 }
                 result.add(pathArgument);
-                if (i < identities.size() - 1) { // last element in instance-identifier can be other than
+                if (i < (identities.size() - 1)) { // last element in instance-identifier can be other than
                     // DataNodeContainer
                     if (node instanceof DataNodeContainer) {
                         parentContainer = (DataNodeContainer) node;
index ffe9565f4c7fe5c195791c8fe9cbc2bba7f10902..148834fcff50fdd37bef6fa5816d5c23183fc554 100644 (file)
@@ -17,26 +17,26 @@ import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
-final class Draft16StringModuleInstanceIdentifierCodec extends AbstractModuleStringInstanceIdentifierCodec {
+public final class Draft16StringModuleInstanceIdentifierCodec extends AbstractModuleStringInstanceIdentifierCodec {
 
     private final DataSchemaContextTree dataContextTree;
     private final SchemaContext context;
     private final String defaultPrefix;
 
-    Draft16StringModuleInstanceIdentifierCodec(SchemaContext context) {
+    public Draft16StringModuleInstanceIdentifierCodec(final SchemaContext context) {
         this.context = Preconditions.checkNotNull(context);
         this.dataContextTree = DataSchemaContextTree.from(context);
         this.defaultPrefix = "";
     }
 
-    Draft16StringModuleInstanceIdentifierCodec(SchemaContext context, @Nonnull String defaultPrefix) {
+    Draft16StringModuleInstanceIdentifierCodec(final SchemaContext context, @Nonnull final String defaultPrefix) {
         this.context = Preconditions.checkNotNull(context);
         this.dataContextTree = DataSchemaContextTree.from(context);
         this.defaultPrefix = defaultPrefix;
     }
 
     @Override
-    protected Module moduleForPrefix(@Nonnull String prefix) {
+    protected Module moduleForPrefix(@Nonnull final String prefix) {
         if (prefix.isEmpty() && !this.defaultPrefix.isEmpty()) {
             return this.context.findModuleByName(this.defaultPrefix, null);
         } else {
@@ -52,7 +52,7 @@ final class Draft16StringModuleInstanceIdentifierCodec extends AbstractModuleStr
 
     @Nullable
     @Override
-    protected String prefixForNamespace(@Nonnull URI namespace) {
+    protected String prefixForNamespace(@Nonnull final URI namespace) {
         final Module module = this.context.findModuleByNamespaceAndRevision(namespace, null);
         return module == null ? null : module.getName();
     }
diff --git a/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/InstanceIdentifierTypeLeafTest.java b/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/InstanceIdentifierTypeLeafTest.java
new file mode 100644 (file)
index 0000000..8439d0c
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016 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.rest.impl;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.rest.common.TestRestconfUtils;
+import org.opendaylight.netconf.sal.restconf.impl.ControllerContext;
+import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class InstanceIdentifierTypeLeafTest {
+
+    @Test
+    public void stringToInstanceIdentifierTest() throws Exception {
+        final SchemaContext schemaContext = TestRestconfUtils.loadSchemaContext("/instanceidentifier");
+        ControllerContext.getInstance().setGlobalSchema(schemaContext);
+        final InstanceIdentifierContext<?> instanceIdentifier =
+                ControllerContext.getInstance().toInstanceIdentifier(
+                        "/iid-value-module:cont-iid/iid-list/%2Fiid-value-module%3Acont-iid%2Fiid-value-module%3A"
+                                + "values-iid%5Biid-value-module:value-iid='value'%5D");
+        final YangInstanceIdentifier yiD = instanceIdentifier.getInstanceIdentifier();
+        Assert.assertNotNull(yiD);
+        final PathArgument lastPathArgument = yiD.getLastPathArgument();
+        Assert.assertTrue(lastPathArgument.getNodeType().getNamespace().toString().equals("iid:value:module"));
+        Assert.assertTrue(lastPathArgument.getNodeType().getLocalName().equals("iid-list"));
+
+        final NodeIdentifierWithPredicates list = (NodeIdentifierWithPredicates) lastPathArgument;
+        final YangInstanceIdentifier value = (YangInstanceIdentifier) list.getKeyValues()
+                .get(QName.create(lastPathArgument.getNodeType(), "iid-leaf"));
+        final PathArgument lastPathArgumentOfValue = value.getLastPathArgument();
+        Assert.assertTrue(lastPathArgumentOfValue.getNodeType().getNamespace().toString().equals("iid:value:module"));
+        Assert.assertTrue(lastPathArgumentOfValue.getNodeType().getLocalName().equals("values-iid"));
+
+        final NodeIdentifierWithPredicates valueList = (NodeIdentifierWithPredicates) lastPathArgumentOfValue;
+        final String valueIid = (String) valueList.getKeyValues()
+                .get(QName.create(lastPathArgumentOfValue.getNodeType(), "value-iid"));
+        Assert.assertEquals("value", valueIid);
+    }
+
+}
diff --git a/restconf/sal-rest-connector/src/test/resources/instanceidentifier/iid-value.yang b/restconf/sal-rest-connector/src/test/resources/instanceidentifier/iid-value.yang
new file mode 100644 (file)
index 0000000..4e536df
--- /dev/null
@@ -0,0 +1,23 @@
+module iid-value-module {
+    namespace "iid:value:module";
+
+    prefix "iidvm";
+    revision 2016-09-12 {
+    }
+
+    container cont-iid {
+        list iid-list{
+            key "iid-leaf";
+            leaf iid-leaf{
+                type instance-identifier;
+            }
+        }
+
+        list values-iid{
+            key "value-iid";
+            leaf value-iid{
+                type string;
+            }
+        }
+    }
+}
\ No newline at end of file