Do not parse YIID to put together a SchemaPath 24/100024/4
authorTomas Cere <tomas.cere@pantheon.tech>
Wed, 9 Mar 2022 13:16:08 +0000 (14:16 +0100)
committerTomas Cere <tomas.cere@pantheon.tech>
Fri, 11 Mar 2022 14:18:48 +0000 (15:18 +0100)
Once we have InstanceIdentifierContext available,
we have already decoded YangInstanceIdentifier.
Due to this we can store the SchemaNodeIdentifier during
the decoding and not iterate through it again with streams.

Change-Id: I27739c755acec519e8422c4fa49a47266487d3cd
Signed-off-by: Tomas Cere <tomas.cere@pantheon.tech>
restconf/restconf-common/src/main/java/org/opendaylight/restconf/common/context/InstanceIdentifierContext.java
restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/rest/impl/NormalizedNodeXmlBodyWriter.java
restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/restconf/impl/ControllerContext.java
restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestconfImpl.java

index 526542ce2c5a61307880b51d9e762e4b4be92573..e386d1c741b992a9c668637ac986dd23906be95f 100644 (file)
@@ -7,21 +7,33 @@
  */
 package org.opendaylight.restconf.common.context;
 
+import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.mdsal.dom.api.DOMMountPoint;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
 
 public class InstanceIdentifierContext<T extends SchemaNode> {
 
     private final YangInstanceIdentifier instanceIdentifier;
+    private final @Nullable SchemaNodeIdentifier schemaNodeIdentifier;
     private final T schemaNode;
     private final DOMMountPoint mountPoint;
     private final EffectiveModelContext schemaContext;
 
-    public InstanceIdentifierContext(final YangInstanceIdentifier instanceIdentifier, final T schemaNode,
-            final DOMMountPoint mountPoint, final EffectiveModelContext context) {
+    public InstanceIdentifierContext(final YangInstanceIdentifier instanceIdentifier,
+                                     final T schemaNode, final DOMMountPoint mountPoint,
+                                     final EffectiveModelContext context) {
+        this(instanceIdentifier, null, schemaNode, mountPoint, context);
+    }
+
+    public InstanceIdentifierContext(final YangInstanceIdentifier instanceIdentifier,
+                                     final SchemaNodeIdentifier schemaNodeIdentifier,
+                                     final T schemaNode, final DOMMountPoint mountPoint,
+                                     final EffectiveModelContext context) {
         this.instanceIdentifier = instanceIdentifier;
+        this.schemaNodeIdentifier = schemaNodeIdentifier;
         this.schemaNode = schemaNode;
         this.mountPoint = mountPoint;
         this.schemaContext = context;
@@ -31,6 +43,10 @@ public class InstanceIdentifierContext<T extends SchemaNode> {
         return instanceIdentifier;
     }
 
+    public SchemaNodeIdentifier getSchemaNodeIdentifier() {
+        return schemaNodeIdentifier;
+    }
+
     public T getSchemaNode() {
         return schemaNode;
     }
index 1a8805c55e334ebe54b1cd68cfc331e47c0f9f03..ca7f3b3451d55430a938b6c555d7ce56b80aeef3 100644 (file)
@@ -13,9 +13,7 @@ import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
 import java.net.URISyntaxException;
 import java.nio.charset.StandardCharsets;
-import java.util.List;
 import java.util.Map.Entry;
-import java.util.stream.Collectors;
 import javanet.staxutils.IndentingXMLStreamWriter;
 import javax.ws.rs.Produces;
 import javax.ws.rs.WebApplicationException;
@@ -35,8 +33,6 @@ import org.opendaylight.netconf.sal.rest.api.RestconfService;
 import org.opendaylight.netconf.util.NetconfUtil;
 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.DOMSourceAnyxmlNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
@@ -137,12 +133,12 @@ public class NormalizedNodeXmlBodyWriter implements MessageBodyWriter<Normalized
             nnWriter = createNormalizedNodeWriter(xmlWriter, schemaCtx, path, depth);
             writeElements(xmlWriter, nnWriter, (ContainerNode) data);
         } else {
-            final List<QName> qNames = pathContext.getInstanceIdentifier().getPathArguments().stream()
-                .filter(arg -> !(arg instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates))
-                .filter(arg -> !(arg instanceof YangInstanceIdentifier.AugmentationIdentifier))
-                .map(PathArgument::getNodeType)
-                .collect(Collectors.toList());
-            final SchemaPath path = SchemaPath.of(Absolute.of(qNames)).getParent();
+            final SchemaPath path;
+            if (pathContext.getSchemaNodeIdentifier() == null) {
+                path = SchemaPath.ROOT;
+            } else {
+                path = SchemaPath.of(pathContext.getSchemaNodeIdentifier()).getParent();
+            }
             nnWriter = createNormalizedNodeWriter(xmlWriter, schemaCtx, path, depth);
             if (data instanceof MapEntryNode) {
                 // Restconf allows returning one list item. We need to wrap it
index 4ce6f060f5673ffb994ca9d7fbb58818f7b45279..6632db8adc7b5d62775e2180ce3fb9a14553f05a 100644 (file)
@@ -72,6 +72,8 @@ import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
@@ -166,7 +168,7 @@ public final class ControllerContext implements EffectiveModelContextListener, C
         checkPreconditions();
 
         if (restconfInstance == null) {
-            return new InstanceIdentifierContext<>(YangInstanceIdentifier.empty(), globalSchema, null,
+            return new InstanceIdentifierContext<>(YangInstanceIdentifier.empty(), null, globalSchema, null,
                     globalSchema);
         }
 
@@ -192,7 +194,8 @@ public final class ControllerContext implements EffectiveModelContextListener, C
         }
 
         final InstanceIdentifierContext<?> iiWithSchemaNode =
-                collectPathArguments(builder, pathArgs, latestModule.iterator().next(), null, toMountPointIdentifier);
+                collectPathArguments(builder, pathArgs, new ArrayList<>(), latestModule.iterator().next(), null,
+                        toMountPointIdentifier);
 
         if (iiWithSchemaNode == null) {
             throw new RestconfDocumentedException("URI has bad format", ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
@@ -523,10 +526,14 @@ public final class ControllerContext implements EffectiveModelContextListener, C
         return object == null ? "" : URLEncoder.encode(codec.serialize(object).toString(), StandardCharsets.UTF_8);
     }
 
+    private SchemaNodeIdentifier schemaNodeIdentifierFromPath(final List<QName> qnames) {
+        return qnames.isEmpty() ? null : Absolute.of(qnames);
+    }
+
     @SuppressFBWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE", justification = "Unrecognised NullableDecl")
     private InstanceIdentifierContext<?> collectPathArguments(final InstanceIdentifierBuilder builder,
-            final List<String> strings, final DataNodeContainer parentNode, final DOMMountPoint mountPoint,
-            final boolean returnJustMountPoint) {
+            final List<String> strings, final List<QName> qnames, final DataNodeContainer parentNode,
+            final DOMMountPoint mountPoint, final boolean returnJustMountPoint) {
         requireNonNull(strings);
 
         if (parentNode == null) {
@@ -536,14 +543,15 @@ public final class ControllerContext implements EffectiveModelContextListener, C
         final EffectiveModelContext modelContext = mountPoint != null ? getModelContext(mountPoint) : globalSchema;
 
         if (strings.isEmpty()) {
-            return createContext(builder.build(), (DataSchemaNode) parentNode, mountPoint, modelContext);
+            return createContext(builder.build(), schemaNodeIdentifierFromPath(qnames), (DataSchemaNode) parentNode,
+                    mountPoint, modelContext);
         }
 
         final String head = strings.iterator().next();
 
         if (head.isEmpty()) {
             final List<String> remaining = strings.subList(1, strings.size());
-            return collectPathArguments(builder, remaining, parentNode, mountPoint, returnJustMountPoint);
+            return collectPathArguments(builder, remaining, qnames, parentNode, mountPoint, returnJustMountPoint);
         }
 
         final String nodeName = toNodeName(head);
@@ -579,7 +587,8 @@ public final class ControllerContext implements EffectiveModelContextListener, C
                 }
 
                 if (returnJustMountPoint || strings.size() == 1) {
-                    return new InstanceIdentifierContext<>(YangInstanceIdentifier.empty(), mountPointSchema, mount,
+                    return new InstanceIdentifierContext<>(YangInstanceIdentifier.empty(), null,
+                            mountPointSchema, mount,
                         mountPointSchema);
                 }
 
@@ -598,8 +607,8 @@ public final class ControllerContext implements EffectiveModelContextListener, C
                 }
 
                 final List<String> subList = strings.subList(1, strings.size());
-                return collectPathArguments(YangInstanceIdentifier.builder(), subList, it.next(), mount,
-                        returnJustMountPoint);
+                return collectPathArguments(YangInstanceIdentifier.builder(), subList, new ArrayList<>(), it.next(),
+                        mount, returnJustMountPoint);
             }
 
             Module module = null;
@@ -634,7 +643,7 @@ public final class ControllerContext implements EffectiveModelContextListener, C
                     rpc = getRpcDefinition(module, rpcName);
                 }
                 if (rpc != null) {
-                    return new InstanceIdentifierContext<>(builder.build(), rpc, mountPoint, modelContext);
+                    return new InstanceIdentifierContext<>(builder.build(), null, rpc, mountPoint, modelContext);
                 }
             }
 
@@ -711,20 +720,23 @@ public final class ControllerContext implements EffectiveModelContextListener, C
             builder.node(targetNode.getQName());
         }
 
+        qnames.add(targetNode.getQName());
+
         if (targetNode instanceof DataNodeContainer) {
             final List<String> remaining = strings.subList(consumed, strings.size());
-            return collectPathArguments(builder, remaining, (DataNodeContainer) targetNode, mountPoint,
+            return collectPathArguments(builder, remaining, qnames, (DataNodeContainer) targetNode, mountPoint,
                     returnJustMountPoint);
         }
 
-        return createContext(builder.build(), targetNode, mountPoint, modelContext);
+        return createContext(builder.build(), Absolute.of(qnames), targetNode, mountPoint, modelContext);
     }
 
     private static InstanceIdentifierContext<?> createContext(final YangInstanceIdentifier instance,
-            final DataSchemaNode dataSchemaNode, final DOMMountPoint mountPoint,
-            final EffectiveModelContext schemaContext) {
+            final SchemaNodeIdentifier schemaNodeIdentifier, final DataSchemaNode dataSchemaNode,
+            final DOMMountPoint mountPoint, final EffectiveModelContext schemaContext) {
         final YangInstanceIdentifier instanceIdentifier = new DataNormalizer(schemaContext).toNormalized(instance);
-        return new InstanceIdentifierContext<>(instanceIdentifier, dataSchemaNode, mountPoint, schemaContext);
+        return new InstanceIdentifierContext<>(instanceIdentifier, schemaNodeIdentifier, dataSchemaNode, mountPoint,
+                schemaContext);
     }
 
     public static DataSchemaNode findInstanceDataChildByNameAndNamespace(final DataNodeContainer container,
index 1a7fd9fc5e91f33d0fef5a5a564dad736c015bc9..9c7f564455bd063ec1ea2fc2b9ba2c167bf8e415 100644 (file)
@@ -131,6 +131,7 @@ import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -190,23 +191,32 @@ public final class RestconfImpl implements RestconfService {
             .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true)
             .appendOffset("+HH:MM", "Z").toFormatter();
 
+    private static final @NonNull QName RESTCONF = QName.create(RestConfModule.IETF_RESTCONF_QNAME, "restconf");
+
     private static final YangInstanceIdentifier MODULES = YangInstanceIdentifier.builder()
-            .node(QName.create(RestConfModule.IETF_RESTCONF_QNAME, "restconf"))
-            .node(QName.create(RestConfModule.IETF_RESTCONF_QNAME, "restconf"))
+            .node(RESTCONF)
+            .node(RESTCONF)
             .node(MODULES_CONTAINER_QNAME)
             .build();
     private static final YangInstanceIdentifier MODULE = YangInstanceIdentifier.builder()
-            .node(QName.create(RestConfModule.IETF_RESTCONF_QNAME, "restconf"))
-            .node(QName.create(RestConfModule.IETF_RESTCONF_QNAME, "restconf"))
+            .node(RESTCONF)
+            .node(RESTCONF)
             .node(MODULES_CONTAINER_QNAME)
             .node(MODULE_LIST_QNAME)
             .build();
     private static final YangInstanceIdentifier STREAMS = YangInstanceIdentifier.builder()
-            .node(QName.create(RestConfModule.IETF_RESTCONF_QNAME, "restconf"))
-            .node(QName.create(RestConfModule.IETF_RESTCONF_QNAME, "restconf"))
+            .node(RESTCONF)
+            .node(RESTCONF)
             .node(STREAMS_CONTAINER_QNAME)
             .build();
 
+    private static final SchemaNodeIdentifier MODULES_SCHEMA_IDENTIFIER =
+            Absolute.of(RESTCONF, RESTCONF, MODULES_CONTAINER_QNAME);
+    private static final SchemaNodeIdentifier MODULE_SCHEMA_IDENTIFIER =
+            Absolute.of(RESTCONF, RESTCONF, MODULES_CONTAINER_QNAME, MODULE_LIST_QNAME);
+    private static final SchemaNodeIdentifier STREAMS_SCHEMA_IDENTIFIER =
+            Absolute.of(RESTCONF, RESTCONF, STREAMS_CONTAINER_QNAME);
+
     private final BrokerFacade broker;
 
     private final ControllerContext controllerContext;
@@ -243,8 +253,9 @@ public final class RestconfImpl implements RestconfService {
                 SchemaAwareBuilders.containerBuilder((ContainerSchemaNode) modulesSchemaNode);
         moduleContainerBuilder.withChild(allModuleMap);
 
-        return new NormalizedNodeContext(new InstanceIdentifierContext<>(MODULES, modulesSchemaNode, null,
-                schemaContext), moduleContainerBuilder.build(), QueryParametersParser.parseWriterParameters(uriInfo));
+        return new NormalizedNodeContext(new InstanceIdentifierContext<>(MODULES, MODULES_SCHEMA_IDENTIFIER,
+                modulesSchemaNode, null, schemaContext), moduleContainerBuilder.build(),
+                QueryParametersParser.parseWriterParameters(uriInfo));
     }
 
     /**
@@ -275,7 +286,7 @@ public final class RestconfImpl implements RestconfService {
         moduleContainerBuilder.withChild(mountPointModulesMap);
 
         return new NormalizedNodeContext(
-                new InstanceIdentifierContext<>(MODULES, modulesSchemaNode, mountPoint,
+                new InstanceIdentifierContext<>(MODULES, MODULES_SCHEMA_IDENTIFIER, modulesSchemaNode, mountPoint,
                         controllerContext.getGlobalSchema()),
                 moduleContainerBuilder.build(), QueryParametersParser.parseWriterParameters(uriInfo));
     }
@@ -314,7 +325,8 @@ public final class RestconfImpl implements RestconfService {
         checkState(moduleSchemaNode instanceof ListSchemaNode);
 
         return new NormalizedNodeContext(
-                new InstanceIdentifierContext<>(MODULE, moduleSchemaNode, mountPoint, schemaContext), moduleMap,
+                new InstanceIdentifierContext<>(MODULE, MODULE_SCHEMA_IDENTIFIER, moduleSchemaNode, mountPoint,
+                        schemaContext), moduleMap,
                 QueryParametersParser.parseWriterParameters(uriInfo));
     }
 
@@ -344,7 +356,8 @@ public final class RestconfImpl implements RestconfService {
         streamsContainerBuilder.withChild(listStreamsBuilder.build());
 
         return new NormalizedNodeContext(
-                new InstanceIdentifierContext<>(STREAMS, streamsContainerSchemaNode, null, schemaContext),
+                new InstanceIdentifierContext<>(STREAMS, STREAMS_SCHEMA_IDENTIFIER, streamsContainerSchemaNode,
+                        null, schemaContext),
                 streamsContainerBuilder.build(), QueryParametersParser.parseWriterParameters(uriInfo));
     }