From efe5c7dfe820b42414e1dc3d433630d7059c673a Mon Sep 17 00:00:00 2001 From: Jakub Toth Date: Mon, 12 Sep 2016 15:30:06 +0200 Subject: [PATCH] Bug 6099 - ControllerContext#addKeyValue ignores key type when key is derived type from instance-identifier * added instance identifier support as value * JUnit test added Change-Id: I4f6a070b5814ef2a33b68534d887745a099712c8 Signed-off-by: Jakub Toth (cherry picked from commit aa0006992ccc87f68e9810c0dee6c16cf339f544) --- .../StringModuleInstanceIdentifierCodec.java | 13 ++-- .../netconf/sal/restconf/impl/RestCodec.java | 63 ++++++++++--------- ...16StringModuleInstanceIdentifierCodec.java | 10 +-- .../impl/InstanceIdentifierTypeLeafTest.java | 50 +++++++++++++++ .../instanceidentifier/iid-value.yang | 23 +++++++ 5 files changed, 117 insertions(+), 42 deletions(-) create mode 100644 restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/InstanceIdentifierTypeLeafTest.java create mode 100644 restconf/sal-rest-connector/src/test/resources/instanceidentifier/iid-value.yang diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/StringModuleInstanceIdentifierCodec.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/StringModuleInstanceIdentifierCodec.java index a265ea95a2..77489dec72 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/StringModuleInstanceIdentifierCodec.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/StringModuleInstanceIdentifierCodec.java @@ -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(); } diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestCodec.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestCodec.java index 77e83e367d..c6224663ef 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestCodec.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestCodec.java @@ -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> 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> 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 predicates = keyValuesToPredicateList(((NodeIdentifierWithPredicates) pathArgument) .getKeyValues()); identityValue.setPredicates(predicates); - } else if (pathArgument instanceof NodeWithValue && identityValue != null) { + } else if ((pathArgument instanceof NodeWithValue) && (identityValue != null)) { final List 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 result = new ArrayList(); 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 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 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; diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/patch/Draft16StringModuleInstanceIdentifierCodec.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/patch/Draft16StringModuleInstanceIdentifierCodec.java index ffe9565f4c..148834fcff 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/patch/Draft16StringModuleInstanceIdentifierCodec.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/patch/Draft16StringModuleInstanceIdentifierCodec.java @@ -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 index 0000000000..8439d0cbc4 --- /dev/null +++ b/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/InstanceIdentifierTypeLeafTest.java @@ -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 index 0000000000..4e536dfaee --- /dev/null +++ b/restconf/sal-rest-connector/src/test/resources/instanceidentifier/iid-value.yang @@ -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 -- 2.36.6