Do not use RestUtil.resolveBaseTypeFrom()
[netconf.git] / restconf / restconf-nb-rfc8040 / src / main / java / org / opendaylight / restconf / nb / rfc8040 / utils / parser / YangInstanceIdentifierDeserializer.java
index dd206f84430f80bc072ca6c5b4cca2763e1ee565..9f73482f41aa55cc19fa14d575e6b422a1e61283 100644 (file)
@@ -17,10 +17,8 @@ import java.util.ArrayList;
 import java.util.List;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
-import org.opendaylight.restconf.common.util.RestUtil;
 import org.opendaylight.restconf.nb.rfc8040.ApiPath;
 import org.opendaylight.restconf.nb.rfc8040.ApiPath.ListInstance;
-import org.opendaylight.restconf.nb.rfc8040.codecs.RestCodec;
 import org.opendaylight.yangtools.yang.common.ErrorTag;
 import org.opendaylight.yangtools.yang.common.ErrorType;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -30,6 +28,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdent
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
 import org.opendaylight.yangtools.yang.model.api.ActionNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
@@ -44,6 +43,7 @@ import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.stmt.IdentityEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.RpcEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
 
@@ -198,8 +198,8 @@ public final class YangInstanceIdentifierDeserializer {
                 final var values = ((ListInstance) step).keyValues();
                 final var schema = childNode.getDataSchemaNode();
                 pathArg = schema instanceof ListSchemaNode
-                    ? prepareNodeWithPredicates(qname, (ListSchemaNode) schema, values)
-                        : prepareNodeWithValue(qname, schema, values);
+                    ? prepareNodeWithPredicates(stack, qname, (ListSchemaNode) schema, values)
+                        : prepareNodeWithValue(stack, qname, schema, values);
             } else {
                 RestconfDocumentedException.throwIf(childNode.isKeyedEntry(),
                     ErrorType.PROTOCOL, ErrorTag.MISSING_ATTRIBUTE,
@@ -227,7 +227,7 @@ public final class YangInstanceIdentifierDeserializer {
         return new Result(path, stack, node);
     }
 
-    private NodeIdentifierWithPredicates prepareNodeWithPredicates(final QName qname,
+    private NodeIdentifierWithPredicates prepareNodeWithPredicates(final SchemaInferenceStack stack, final QName qname,
             final @NonNull ListSchemaNode schema, final List<@NonNull String> keyValues) {
         final var keyDef = schema.getKeyDefinition();
         final var keySize = keyDef.size();
@@ -239,15 +239,20 @@ public final class YangInstanceIdentifierDeserializer {
         }
 
         final var values = ImmutableMap.<QName, Object>builderWithExpectedSize(keySize);
+        final var tmp = stack.copy();
         for (int i = 0; i < keySize; ++i) {
             final QName keyName = keyDef.get(i);
-            values.put(keyName, prepareValueByType(schema.getDataChildByName(keyName), keyValues.get(i)));
+            final var child = schema.getDataChildByName(keyName);
+            tmp.enterSchemaTree(keyName);
+            values.put(keyName, prepareValueByType(tmp, child, keyValues.get(i)));
+            tmp.exit();
         }
 
         return NodeIdentifierWithPredicates.of(qname, values.build());
     }
 
-    private Object prepareValueByType(final DataSchemaNode schemaNode, final @NonNull String value) {
+    private Object prepareValueByType(final SchemaInferenceStack stack, final DataSchemaNode schemaNode,
+            final @NonNull String value) {
 
         TypeDefinition<? extends TypeDefinition<?>> typedef;
         if (schemaNode instanceof LeafListSchemaNode) {
@@ -255,27 +260,31 @@ public final class YangInstanceIdentifierDeserializer {
         } else {
             typedef = ((LeafSchemaNode) schemaNode).getType();
         }
-        final TypeDefinition<?> baseType = RestUtil.resolveBaseTypeFrom(typedef);
-        if (baseType instanceof LeafrefTypeDefinition) {
-            typedef = SchemaInferenceStack.ofInstantiatedPath(schemaContext, schemaNode.getPath())
-                .resolveLeafref((LeafrefTypeDefinition) baseType);
+        if (typedef instanceof LeafrefTypeDefinition) {
+            typedef = stack.resolveLeafref((LeafrefTypeDefinition) typedef);
         }
 
         if (typedef instanceof IdentityrefTypeDefinition) {
             return toIdentityrefQName(value, schemaNode);
         }
+
         try {
-            return RestCodec.from(typedef, null, schemaContext).deserialize(value);
+            if (typedef instanceof InstanceIdentifierTypeDefinition) {
+                return new StringModuleInstanceIdentifierCodec(schemaContext).deserialize(value);
+            }
+
+            return verifyNotNull(TypeDefinitionAwareCodec.from(typedef),
+                "Unhandled type %s decoding %s", typedef, value).deserialize(value);
         } catch (IllegalArgumentException e) {
             throw new RestconfDocumentedException("Invalid value '" + value + "' for " + schemaNode.getQName(),
                 ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE, e);
         }
     }
 
-    private NodeWithValue<?> prepareNodeWithValue(final QName qname, final DataSchemaNode schema,
-            final List<String> keyValues) {
+    private NodeWithValue<?> prepareNodeWithValue(final SchemaInferenceStack stack, final QName qname,
+            final DataSchemaNode schema, final List<String> keyValues) {
         // TODO: qname should be always equal to schema.getQName(), right?
-        return new NodeWithValue<>(qname, prepareValueByType(schema,
+        return new NodeWithValue<>(qname, prepareValueByType(stack, schema,
             // FIXME: ahem: we probably want to do something differently here
             keyValues.get(0)));
     }