From 03f1156ed45c26e83ee7e47e794010b2d3f49b4d Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Tue, 15 Nov 2022 19:13:30 +0100 Subject: [PATCH] Lookup schema nodes one item at a time Our current code is using YangInstanceIdentifier to always lookup nodes from root. This ends up being inefficient as we end up looking up things we already crossed over (and have on-stack). Change-Id: I4e8aa2d7a787843fe570ed75a46cc867d5efd28d Signed-off-by: Robert Varga --- .../rests/utils/ReadDataTransactionUtil.java | 79 ++++++++++--------- 1 file changed, 41 insertions(+), 38 deletions(-) diff --git a/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/ReadDataTransactionUtil.java b/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/ReadDataTransactionUtil.java index 520dc1e5ae..75635449c5 100644 --- a/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/ReadDataTransactionUtil.java +++ b/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/ReadDataTransactionUtil.java @@ -11,6 +11,7 @@ import com.google.common.util.concurrent.ListenableFuture; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Optional; import java.util.function.Function; import java.util.stream.Collectors; @@ -52,6 +53,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.builder.NormalizedNodeCon import org.opendaylight.yangtools.yang.data.impl.schema.Builders; import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; import org.opendaylight.yangtools.yang.data.impl.schema.SchemaAwareBuilders; +import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode; import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree; import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; @@ -133,17 +135,15 @@ public final class ReadDataTransactionUtil { case REPORT_ALL, REPORT_ALL_TAGGED -> throw new RestconfDocumentedException( "Unsupported with-defaults value " + withDefa.paramValue()); }; - final DataSchemaContextTree baseSchemaCtxTree = DataSchemaContextTree.from(ctx); - final DataSchemaNode baseSchemaNode = baseSchemaCtxTree.findChild(path).orElseThrow().getDataSchemaNode(); + final DataSchemaContextNode ctxNode = DataSchemaContextTree.from(ctx).findChild(path).orElseThrow(); + final DataSchemaNode baseSchemaNode = ctxNode.getDataSchemaNode(); if (result instanceof ContainerNode) { - final DataContainerNodeBuilder builder = - SchemaAwareBuilders.containerBuilder((ContainerSchemaNode) baseSchemaNode); - buildCont(builder, (ContainerNode) result, baseSchemaCtxTree, path, trim); + final var builder = SchemaAwareBuilders.containerBuilder((ContainerSchemaNode) baseSchemaNode); + buildCont(builder, (ContainerNode) result, ctxNode, trim); return builder.build(); } else { - final DataContainerNodeBuilder builder = - SchemaAwareBuilders.mapEntryBuilder((ListSchemaNode) baseSchemaNode); - buildMapEntryBuilder(builder, (MapEntryNode) result, baseSchemaCtxTree, path, trim, + final var builder = SchemaAwareBuilders.mapEntryBuilder((ListSchemaNode) baseSchemaNode); + buildMapEntryBuilder(builder, (MapEntryNode) result, ctxNode, trim, ((ListSchemaNode) baseSchemaNode).getKeyDefinition()); return builder.build(); } @@ -151,21 +151,23 @@ public final class ReadDataTransactionUtil { private static void buildMapEntryBuilder( final DataContainerNodeBuilder builder, - final MapEntryNode result, final DataSchemaContextTree baseSchemaCtxTree, - final YangInstanceIdentifier actualPath, final boolean trim, final List keys) { + final MapEntryNode result, final DataSchemaContextNode ctxNode, final boolean trim, + final List keys) { for (final DataContainerChild child : result.body()) { - final YangInstanceIdentifier path = actualPath.node(child.getIdentifier()); - final DataSchemaNode childSchema = baseSchemaCtxTree.findChild(path).orElseThrow().getDataSchemaNode(); + final var childCtx = ctxNode.getChild(child.getIdentifier()); + if (childCtx == null) { + throw new NoSuchElementException("Failed to map child " + child.getIdentifier()); + } + + final DataSchemaNode childSchema = childCtx.getDataSchemaNode(); if (child instanceof ContainerNode) { - final DataContainerNodeBuilder childBuilder = - SchemaAwareBuilders.containerBuilder((ContainerSchemaNode) childSchema); - buildCont(childBuilder, (ContainerNode) child, baseSchemaCtxTree, path, trim); + final var childBuilder = SchemaAwareBuilders.containerBuilder((ContainerSchemaNode) childSchema); + buildCont(childBuilder, (ContainerNode) child, childCtx, trim); builder.withChild(childBuilder.build()); } else if (child instanceof MapNode) { - final CollectionNodeBuilder childBuilder = - SchemaAwareBuilders.mapBuilder((ListSchemaNode) childSchema); - buildList(childBuilder, (MapNode) child, baseSchemaCtxTree, path, trim, - ((ListSchemaNode) childSchema).getKeyDefinition()); + final var childBuilder = SchemaAwareBuilders.mapBuilder((ListSchemaNode) childSchema); + buildList(childBuilder, (MapNode) child, childCtx, trim, + ((ListSchemaNode) childSchema).getKeyDefinition()); builder.withChild(childBuilder.build()); } else if (child instanceof LeafNode) { final Object defaultVal = ((LeafSchemaNode) childSchema).getType().getDefaultValue().orElse(null); @@ -184,35 +186,36 @@ public final class ReadDataTransactionUtil { } private static void buildList(final CollectionNodeBuilder builder, - final MapNode result, final DataSchemaContextTree baseSchemaCtxTree, final YangInstanceIdentifier path, - final boolean trim, final List keys) { + final MapNode result, DataSchemaContextNode ctxNode, final boolean trim, final List keys) { for (final MapEntryNode mapEntryNode : result.body()) { - final YangInstanceIdentifier actualNode = path.node(mapEntryNode.getIdentifier()); - final DataSchemaNode childSchema = baseSchemaCtxTree.findChild(actualNode).orElseThrow() - .getDataSchemaNode(); - final DataContainerNodeBuilder mapEntryBuilder = - SchemaAwareBuilders.mapEntryBuilder((ListSchemaNode) childSchema); - buildMapEntryBuilder(mapEntryBuilder, mapEntryNode, baseSchemaCtxTree, actualNode, trim, keys); + final var childCtx = ctxNode.getChild(mapEntryNode.getIdentifier()); + if (childCtx == null) { + throw new NoSuchElementException("Failed to match entry " + mapEntryNode.getIdentifier()); + } + final DataSchemaNode childSchema = childCtx.getDataSchemaNode(); + final var mapEntryBuilder = SchemaAwareBuilders.mapEntryBuilder((ListSchemaNode) childSchema); + buildMapEntryBuilder(mapEntryBuilder, mapEntryNode, childCtx, trim, keys); builder.withChild(mapEntryBuilder.build()); } } private static void buildCont(final DataContainerNodeBuilder builder, - final ContainerNode result, final DataSchemaContextTree baseSchemaCtxTree, - final YangInstanceIdentifier actualPath, final boolean trim) { + final ContainerNode result, final DataSchemaContextNode ctxNode, final boolean trim) { for (final DataContainerChild child : result.body()) { - final YangInstanceIdentifier path = actualPath.node(child.getIdentifier()); - final DataSchemaNode childSchema = baseSchemaCtxTree.findChild(path).orElseThrow().getDataSchemaNode(); + final var childCtx = ctxNode.getChild(child.getIdentifier()); + if (childCtx == null) { + throw new NoSuchElementException("Cannot resolve child " + child.getIdentifier()); + } + + final DataSchemaNode childSchema = childCtx.getDataSchemaNode(); if (child instanceof ContainerNode) { - final DataContainerNodeBuilder builderChild = - SchemaAwareBuilders.containerBuilder((ContainerSchemaNode) childSchema); - buildCont(builderChild, result, baseSchemaCtxTree, actualPath, trim); + final var builderChild = SchemaAwareBuilders.containerBuilder((ContainerSchemaNode) childSchema); + buildCont(builderChild, result, childCtx, trim); builder.withChild(builderChild.build()); } else if (child instanceof MapNode) { - final CollectionNodeBuilder childBuilder = - SchemaAwareBuilders.mapBuilder((ListSchemaNode) childSchema); - buildList(childBuilder, (MapNode) child, baseSchemaCtxTree, path, trim, - ((ListSchemaNode) childSchema).getKeyDefinition()); + final var childBuilder = SchemaAwareBuilders.mapBuilder((ListSchemaNode) childSchema); + buildList(childBuilder, (MapNode) child, childCtx, trim, + ((ListSchemaNode) childSchema).getKeyDefinition()); builder.withChild(childBuilder.build()); } else if (child instanceof LeafNode) { final Object defaultVal = ((LeafSchemaNode) childSchema).getType().getDefaultValue().orElse(null); -- 2.36.6