From b792380644d076274abf500df3a0e1cb1aae1366 Mon Sep 17 00:00:00 2001 From: Tomas Cere Date: Wed, 9 Mar 2022 14:16:08 +0100 Subject: [PATCH] Do not parse YIID to put together a SchemaPath 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 --- .../context/InstanceIdentifierContext.java | 20 ++++++++- .../impl/NormalizedNodeXmlBodyWriter.java | 16 +++---- .../sal/restconf/impl/ControllerContext.java | 42 ++++++++++++------- .../sal/restconf/impl/RestconfImpl.java | 35 +++++++++++----- 4 files changed, 75 insertions(+), 38 deletions(-) diff --git a/restconf/restconf-common/src/main/java/org/opendaylight/restconf/common/context/InstanceIdentifierContext.java b/restconf/restconf-common/src/main/java/org/opendaylight/restconf/common/context/InstanceIdentifierContext.java index 526542ce2c..e386d1c741 100644 --- a/restconf/restconf-common/src/main/java/org/opendaylight/restconf/common/context/InstanceIdentifierContext.java +++ b/restconf/restconf-common/src/main/java/org/opendaylight/restconf/common/context/InstanceIdentifierContext.java @@ -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 { 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 { return instanceIdentifier; } + public SchemaNodeIdentifier getSchemaNodeIdentifier() { + return schemaNodeIdentifier; + } + public T getSchemaNode() { return schemaNode; } diff --git a/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/rest/impl/NormalizedNodeXmlBodyWriter.java b/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/rest/impl/NormalizedNodeXmlBodyWriter.java index 1a8805c55e..ca7f3b3451 100644 --- a/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/rest/impl/NormalizedNodeXmlBodyWriter.java +++ b/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/rest/impl/NormalizedNodeXmlBodyWriter.java @@ -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 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 diff --git a/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/restconf/impl/ControllerContext.java b/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/restconf/impl/ControllerContext.java index 4ce6f060f5..6632db8adc 100644 --- a/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/restconf/impl/ControllerContext.java +++ b/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/restconf/impl/ControllerContext.java @@ -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 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 strings, final DataNodeContainer parentNode, final DOMMountPoint mountPoint, - final boolean returnJustMountPoint) { + final List strings, final List 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 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 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 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, diff --git a/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestconfImpl.java b/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestconfImpl.java index 1a7fd9fc5e..9c7f564455 100644 --- a/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestconfImpl.java +++ b/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestconfImpl.java @@ -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)); } -- 2.36.6