From f51b868fbb0870fcfc84ecfd1e90a59c5a05b302 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Thu, 12 Jul 2018 11:26:35 +0200 Subject: [PATCH] Do not use SchemaNodeIdentifierBuildNamespace prerequisites Incremental lookups on ChildSchemaNodeNamespace allow us to react to childen being created, hence we do not have an assumption that the target node must be instantiated by someone else (like eager instantiation). This will also allow us better recovery if the target node is not going to appear due to being disabled by if-feature. JIRA: YANGTOOLS-694 Change-Id: Ibc05e18037bb85d42ed7123293e7f83f896aad5d Signed-off-by: Robert Varga (cherry picked from commit 509988128ed9d5fe314a14906114f53778200e47) --- .../namespace/ChildSchemaNodeNamespace.java | 55 +++++++++++++++++++ .../SchemaNodeIdentifierBuildNamespace.java | 33 ++++------- .../AbstractAugmentStatementSupport.java | 8 +-- .../AbstractDeviateStatementSupport.java | 6 +- .../rfc7950/stmt/uses/UsesStatementImpl.java | 4 +- 5 files changed, 75 insertions(+), 31 deletions(-) diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/namespace/ChildSchemaNodeNamespace.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/namespace/ChildSchemaNodeNamespace.java index 7685e93cf2..7968cd4a6d 100644 --- a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/namespace/ChildSchemaNodeNamespace.java +++ b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/namespace/ChildSchemaNodeNamespace.java @@ -8,14 +8,21 @@ package org.opendaylight.yangtools.yang.parser.rfc7950.namespace; import com.google.common.annotations.Beta; +import java.util.Collection; +import java.util.Iterator; import java.util.Map; +import java.util.Optional; import javax.annotation.Nonnull; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement; import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; +import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier; +import org.opendaylight.yangtools.yang.model.api.stmt.UnknownStatement; import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour; import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace; import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext; +import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable; +import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils; import org.opendaylight.yangtools.yang.parser.spi.source.SourceException; /** @@ -61,6 +68,54 @@ public final class ChildSchemaNodeNamespace, } } + /** + * Find statement context identified by interpreting specified {@link SchemaNodeIdentifier} starting at specified + * {@link StmtContext}. + * + * @param root Search root context + * @param identifier {@link SchemaNodeIdentifier} relative to search root + * @return Matching statement context, if present. + * @throws NullPointerException if any of the arguments is null + */ + public static Optional> findNode(final StmtContext root, + final SchemaNodeIdentifier identifier) { + final Iterator iterator = identifier.getPathFromRoot().iterator(); + if (!iterator.hasNext()) { + return Optional.of((Mutable>) root); + } + + QName nextPath = iterator.next(); + Mutable> current = root.getFromNamespace(ChildSchemaNodeNamespace.class, + nextPath); + if (current == null) { + return Optional.ofNullable(tryToFindUnknownStatement(nextPath.getLocalName(), + (Mutable>) root)); + } + while (current != null && iterator.hasNext()) { + nextPath = iterator.next(); + final Mutable> nextNodeCtx = current.getFromNamespace( + ChildSchemaNodeNamespace.class,nextPath); + if (nextNodeCtx == null) { + return Optional.ofNullable(tryToFindUnknownStatement(nextPath.getLocalName(), current)); + } + current = nextNodeCtx; + } + return Optional.ofNullable(current); + } + + @SuppressWarnings("unchecked") + static Mutable> tryToFindUnknownStatement(final String localName, + final Mutable> current) { + final Collection> unknownSubstatements = StmtContextUtils.findAllSubstatements( + current, UnknownStatement.class); + for (final StmtContext unknownSubstatement : unknownSubstatements) { + if (localName.equals(unknownSubstatement.rawStatementArgument())) { + return (Mutable>) unknownSubstatement; + } + } + return null; + } + private static NamespaceStorageNode globalOrStatementSpecific(final NamespaceStorageNode storage) { NamespaceStorageNode current = storage; while (!isLocalOrGlobal(current.getStorageNodeType())) { diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/namespace/SchemaNodeIdentifierBuildNamespace.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/namespace/SchemaNodeIdentifierBuildNamespace.java index c26b9f7403..708fb01698 100644 --- a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/namespace/SchemaNodeIdentifierBuildNamespace.java +++ b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/namespace/SchemaNodeIdentifierBuildNamespace.java @@ -7,10 +7,7 @@ */ package org.opendaylight.yangtools.yang.parser.rfc7950.namespace; -import static java.util.Objects.requireNonNull; - import com.google.common.annotations.Beta; -import java.util.Collection; import java.util.Iterator; import java.util.Optional; import javax.annotation.Nonnull; @@ -18,14 +15,18 @@ import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace; import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier; -import org.opendaylight.yangtools.yang.model.api.stmt.UnknownStatement; import org.opendaylight.yangtools.yang.parser.spi.meta.DerivedNamespaceBehaviour; import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour; import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext; import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable; -import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils; +/** + * Legacy namespace for looking up nodes by their Schema Tree identifier. + * + * @deprecated Use path-based utilities provided around {@link ChildSchemaNodeNamespace} instead. + */ @Beta +@Deprecated public final class SchemaNodeIdentifierBuildNamespace extends DerivedNamespaceBehaviour>, QName, SchemaNodeIdentifierBuildNamespace, ChildSchemaNodeNamespace> @@ -44,11 +45,12 @@ public final class SchemaNodeIdentifierBuildNamespace * @param identifier {@link SchemaNodeIdentifier} relative to search root * @return Matching statement context, if present. * @throws NullPointerException if any of the arguments is null + * @deprecated Use {@link ChildSchemaNodeNamespace#findNode(StmtContext, SchemaNodeIdentifier)} instead. */ + @Deprecated public static Optional> findNode(final StmtContext root, final SchemaNodeIdentifier identifier) { - return Optional.ofNullable(root.getFromNamespace(SchemaNodeIdentifierBuildNamespace.class, - requireNonNull(identifier))); + return ChildSchemaNodeNamespace.findNode(root, identifier); } @Override @@ -77,7 +79,7 @@ public final class SchemaNodeIdentifierBuildNamespace Mutable> current = lookupStartStorage.getFromLocalStorage( ChildSchemaNodeNamespace.class,nextPath); if (current == null && lookupStartStorage instanceof StmtContext) { - return tryToFindUnknownStatement(nextPath.getLocalName(), + return ChildSchemaNodeNamespace.tryToFindUnknownStatement(nextPath.getLocalName(), (Mutable>) lookupStartStorage); } while (current != null && iterator.hasNext()) { @@ -85,26 +87,13 @@ public final class SchemaNodeIdentifierBuildNamespace final Mutable> nextNodeCtx = current.getFromNamespace( ChildSchemaNodeNamespace.class,nextPath); if (nextNodeCtx == null) { - return tryToFindUnknownStatement(nextPath.getLocalName(), current); + return ChildSchemaNodeNamespace.tryToFindUnknownStatement(nextPath.getLocalName(), current); } current = nextNodeCtx; } return current; } - @SuppressWarnings("unchecked") - private static Mutable> tryToFindUnknownStatement(final String localName, - final Mutable> current) { - final Collection> unknownSubstatements = StmtContextUtils.findAllSubstatements( - current, UnknownStatement.class); - for (final StmtContext unknownSubstatement : unknownSubstatements) { - if (localName.equals(unknownSubstatement.rawStatementArgument())) { - return (Mutable>) unknownSubstatement; - } - } - return null; - } - @Override public QName getSignificantKey(final SchemaNodeIdentifier key) { return key.getLastComponent(); diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/augment/AbstractAugmentStatementSupport.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/augment/AbstractAugmentStatementSupport.java index d4e5881171..18093dc432 100644 --- a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/augment/AbstractAugmentStatementSupport.java +++ b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/augment/AbstractAugmentStatementSupport.java @@ -24,7 +24,7 @@ import org.opendaylight.yangtools.yang.model.api.stmt.DataDefinitionStatement; import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier; import org.opendaylight.yangtools.yang.model.api.stmt.UsesStatement; import org.opendaylight.yangtools.yang.model.api.stmt.WhenStatement; -import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.SchemaNodeIdentifierBuildNamespace; +import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.ChildSchemaNodeNamespace; import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.ArgumentUtils; import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport; import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType; @@ -95,8 +95,8 @@ abstract class AbstractAugmentStatementSupport extends AbstractStatementSupport< EffectiveStatement>> sourceCtxPrereq = augmentAction.requiresCtx(augmentNode, ModelProcessingPhase.EFFECTIVE_MODEL); final Prerequisite>> target = - augmentAction.mutatesEffectiveCtx(getSearchRoot(augmentNode), - SchemaNodeIdentifierBuildNamespace.class, augmentNode.getStatementArgument()); + augmentAction.mutatesEffectiveCtxPath(getSearchRoot(augmentNode), + ChildSchemaNodeNamespace.class, augmentNode.getStatementArgument().getPathFromRoot()); augmentAction.apply(new ModelActionBuilder.InferenceAction() { @Override @@ -147,7 +147,7 @@ abstract class AbstractAugmentStatementSupport extends AbstractStatementSupport< * Do not fail, if it is an uses-augment to an unknown node. */ if (YangStmtMapping.USES == augmentNode.getParentContext().getPublicDefinition()) { - final Optional> targetNode = SchemaNodeIdentifierBuildNamespace.findNode( + final Optional> targetNode = ChildSchemaNodeNamespace.findNode( getSearchRoot(augmentNode), augmentNode.getStatementArgument()); if (targetNode.isPresent() && StmtContextUtils.isUnknownStatement(targetNode.get())) { augmentNode.setIsSupportedToBuildEffective(false); diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/deviate/AbstractDeviateStatementSupport.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/deviate/AbstractDeviateStatementSupport.java index 0ba89b6174..02bf569413 100644 --- a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/deviate/AbstractDeviateStatementSupport.java +++ b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/deviate/AbstractDeviateStatementSupport.java @@ -23,7 +23,7 @@ import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition; import org.opendaylight.yangtools.yang.model.api.stmt.DeviateStatement; import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier; -import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.SchemaNodeIdentifierBuildNamespace; +import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.ChildSchemaNodeNamespace; import org.opendaylight.yangtools.yang.parser.rfc7950.reactor.YangValidationBundles; import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport; import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType; @@ -143,8 +143,8 @@ abstract class AbstractDeviateStatementSupport extends AbstractStatementSupport< deviateAction.requiresCtx(deviateStmtCtx, ModelProcessingPhase.EFFECTIVE_MODEL); final Prerequisite>> targetCtxPrerequisite = - deviateAction.mutatesEffectiveCtx(deviateStmtCtx.getRoot(), - SchemaNodeIdentifierBuildNamespace.class, deviationTarget); + deviateAction.mutatesEffectiveCtxPath(deviateStmtCtx.getRoot(), + ChildSchemaNodeNamespace.class, deviationTarget.getPathFromRoot()); deviateAction.apply(new InferenceAction() { @Override diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/uses/UsesStatementImpl.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/uses/UsesStatementImpl.java index 1357a5754e..3a6cab552b 100644 --- a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/uses/UsesStatementImpl.java +++ b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/uses/UsesStatementImpl.java @@ -22,7 +22,7 @@ import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition; import org.opendaylight.yangtools.yang.model.api.stmt.RefineStatement; import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier; import org.opendaylight.yangtools.yang.model.api.stmt.UsesStatement; -import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.SchemaNodeIdentifierBuildNamespace; +import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.ChildSchemaNodeNamespace; import org.opendaylight.yangtools.yang.parser.rfc7950.reactor.YangValidationBundles; import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractDeclaredStatement; import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType; @@ -145,7 +145,7 @@ final class UsesStatementImpl extends AbstractDeclaredStatement implement subStmtCtx.getStatementSourceReference(), "Invalid refine argument %s. It must be instance of SchemaNodeIdentifier.", refineArgument); - final Optional> optRefineTargetCtx = SchemaNodeIdentifierBuildNamespace.findNode( + final Optional> optRefineTargetCtx = ChildSchemaNodeNamespace.findNode( usesParentCtx, (SchemaNodeIdentifier) refineArgument); InferenceException.throwIf(!optRefineTargetCtx.isPresent(), subStmtCtx.getStatementSourceReference(), "Refine target node %s not found.", refineArgument); -- 2.36.6