From: Robert Varga Date: Fri, 6 Jan 2023 15:30:27 +0000 (+0100) Subject: Fix identity-ref value parsing/serialization X-Git-Tag: v11.0.0~232 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=7c8fd1ae5a6942fb3600ab9d05185cd4293f5f51;hp=f31f6f001ec2263715ebfd5f28d214b56e9a0344;p=yangtools.git Fix identity-ref value parsing/serialization When encountering a QName value in a leaf, a leaf-list or implied as the value of a key, we need to properly encode it. The same is true when parsing, where we have to consult current namespace mapping. As a side-effect of this, we are also fixing the case of a leaf-list entry referenced in a path argument -- which is important for all non-String types. JIRA: YANGTOOLS-1473 Change-Id: Id50ebd9a3c0c1378f1af8451b86c66e323757eba Signed-off-by: Robert Varga Signed-off-by: Ruslan Kashapov --- diff --git a/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONInstanceIdentifierCodec.java b/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONInstanceIdentifierCodec.java index 17832f940e..ad89e039f6 100644 --- a/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONInstanceIdentifierCodec.java +++ b/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONInstanceIdentifierCodec.java @@ -21,6 +21,7 @@ import org.opendaylight.yangtools.yang.data.util.AbstractModuleStringInstanceIde import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; +import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.util.LeafrefResolver; @@ -82,8 +83,13 @@ abstract sealed class JSONInstanceIdentifierCodec extends AbstractModuleStringIn protected final Object deserializeKeyValue(final DataSchemaNode schemaNode, final LeafrefResolver resolver, final String value) { requireNonNull(schemaNode, "schemaNode cannot be null"); - checkArgument(schemaNode instanceof LeafSchemaNode, "schemaNode must be of type LeafSchemaNode"); - return codecFactory.codecFor((LeafSchemaNode) schemaNode, resolver).parseValue(null, value); + if (schemaNode instanceof LeafSchemaNode leafSchemaNode) { + return codecFactory.codecFor(leafSchemaNode, resolver).parseValue(null, value); + } else if (schemaNode instanceof LeafListSchemaNode leafListSchemaNode) { + return codecFactory.codecFor(leafListSchemaNode, resolver).parseValue(null, value); + } + throw new IllegalArgumentException("schemaNode " + schemaNode + + " must be of type LeafSchemaNode or LeafListSchemaNode"); } @Override diff --git a/codec/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/YT1473Test.java b/codec/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/YT1473Test.java index 48edc81796..52e0fed732 100644 --- a/codec/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/YT1473Test.java +++ b/codec/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/YT1473Test.java @@ -92,13 +92,11 @@ class YT1473Test { } @Test - @Disabled("YT-1473: QName values need to be recognized and properly encoded via identity codec") void testSerializeIdentityRefSame() throws Exception { assertSerdes("/foo:bar[qname='one']", buildYangInstanceIdentifier(FOO_BAR, FOO_QNAME, FOO_ONE)); } @Test - @Disabled("YT-1473: QName values need to be recognized and properly encoded via identity codec") void testSerializeIdentityRefOther() throws Exception { // No escaping is needed, use double quotes and escape assertSerdes("/foo:bar[qname='bar:two']", buildYangInstanceIdentifier(FOO_BAR, FOO_QNAME, BAR_TWO)); @@ -112,7 +110,6 @@ class YT1473Test { } @Test - @Disabled("YT-1473: QName values need to be recognized and properly encoded via identity codec") void testSerializeIdentityValue() throws Exception { assertSerdes("/bar:foo[.='foo:one']", buildYangInstanceIdentifier(BAR_FOO, FOO_ONE)); assertSerdes("/bar:foo[.='two']", buildYangInstanceIdentifier(BAR_FOO, BAR_TWO)); diff --git a/codec/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/XmlStringInstanceIdentifierCodec.java b/codec/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/XmlStringInstanceIdentifierCodec.java index 4f74ecb4f0..1b24568963 100644 --- a/codec/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/XmlStringInstanceIdentifierCodec.java +++ b/codec/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/XmlStringInstanceIdentifierCodec.java @@ -7,7 +7,6 @@ */ package org.opendaylight.yangtools.yang.data.codec.xml; -import static com.google.common.base.Preconditions.checkArgument; import static java.util.Objects.requireNonNull; import java.util.ArrayDeque; @@ -23,6 +22,7 @@ import org.opendaylight.yangtools.yang.data.util.AbstractModuleStringInstanceIde import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; +import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.util.LeafrefResolver; @@ -64,8 +64,15 @@ final class XmlStringInstanceIdentifierCodec extends AbstractModuleStringInstanc protected Object deserializeKeyValue(final DataSchemaNode schemaNode, final LeafrefResolver resolver, final String value) { requireNonNull(schemaNode, "schemaNode cannot be null"); - checkArgument(schemaNode instanceof LeafSchemaNode, "schemaNode must be of type LeafSchemaNode"); - final XmlCodec objectXmlCodec = codecFactory.codecFor((LeafSchemaNode) schemaNode, resolver); + final XmlCodec objectXmlCodec; + if (schemaNode instanceof LeafSchemaNode leafSchemaNode) { + objectXmlCodec = codecFactory.codecFor(leafSchemaNode, resolver); + } else if (schemaNode instanceof LeafListSchemaNode leafListSchemaNode) { + objectXmlCodec = codecFactory.codecFor(leafListSchemaNode, resolver); + } else { + throw new IllegalArgumentException("schemaNode " + schemaNode + + " must be of type LeafSchemaNode or LeafListSchemaNode"); + } return objectXmlCodec.parseValue(getNamespaceContext(), value); } diff --git a/codec/yang-data-codec-xml/src/test/java/org/opendaylight/yangtools/yang/data/codec/xml/YT1473Test.java b/codec/yang-data-codec-xml/src/test/java/org/opendaylight/yangtools/yang/data/codec/xml/YT1473Test.java index 7bef13a35e..51aaf19e59 100644 --- a/codec/yang-data-codec-xml/src/test/java/org/opendaylight/yangtools/yang/data/codec/xml/YT1473Test.java +++ b/codec/yang-data-codec-xml/src/test/java/org/opendaylight/yangtools/yang/data/codec/xml/YT1473Test.java @@ -92,7 +92,6 @@ class YT1473Test { } @Test - @Disabled("YT-1473: QName values need to be recognized and properly encoded via identity codec") void testSerializeIdentity() throws Exception { assertSerdes("/foo:bar[foo:qname='foo:one']", buildYangInstanceIdentifier(FOO_BAR, FOO_QNAME, FOO_ONE)); assertSerdes("/foo:bar[foo:qname='bar:two']", buildYangInstanceIdentifier(FOO_BAR, FOO_QNAME, BAR_TWO)); @@ -106,7 +105,6 @@ class YT1473Test { } @Test - @Disabled("YT-1473: QName values need to be recognized and properly encoded via identity codec") void testSerializeIdentityValue() throws Exception { assertSerdes("/bar:foo[.='foo:one']", buildYangInstanceIdentifier(BAR_FOO, FOO_ONE)); assertSerdes("/bar:foo[.='bar:two']", buildYangInstanceIdentifier(BAR_FOO, BAR_TWO)); diff --git a/data/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/AbstractStringInstanceIdentifierCodec.java b/data/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/AbstractStringInstanceIdentifierCodec.java index 8ba7d0aef8..a89ae431a8 100644 --- a/data/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/AbstractStringInstanceIdentifierCodec.java +++ b/data/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/AbstractStringInstanceIdentifierCodec.java @@ -79,8 +79,13 @@ public abstract class AbstractStringInstanceIdentifierCodec extends AbstractName return sb.toString(); } - private static StringBuilder appendValue(final StringBuilder sb, final QNameModule currentModule, + private StringBuilder appendValue(final StringBuilder sb, final QNameModule currentModule, final Object value) { + if (value instanceof QName qname) { + // QName implies identity-ref, which can never be escaped + return appendQName(sb.append('\''), qname, currentModule).append('\''); + } + final var str = String.valueOf(value); // We have two specifications here: Section 6.1.3 of both RFC6020 and RFC7950: diff --git a/data/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/XpathStringParsingPathArgumentBuilder.java b/data/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/XpathStringParsingPathArgumentBuilder.java index 84000eea48..a4ac597e3c 100644 --- a/data/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/XpathStringParsingPathArgumentBuilder.java +++ b/data/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/XpathStringParsingPathArgumentBuilder.java @@ -160,7 +160,9 @@ final class XpathStringParsingPathArgumentBuilder implements Mutable { // Break-out from method for leaf-list case if (key == null && currentNode.isLeaf()) { checkValid(offset == data.length(), "Leaf argument must be last argument of instance identifier."); - return new NodeWithValue<>(name, keyValue); + final Object value = codec.deserializeKeyValue(currentNode.getDataSchemaNode(), + type -> resolveLeafref(currentNode.getIdentifier().getNodeType(), type), keyValue); + return new NodeWithValue<>(name, value); } final DataSchemaContextNode keyNode = currentNode.getChild(key); checkValid(keyNode != null, "%s is not correct schema node identifier.", key);