From c31a90ed7c04bc622c9404a4a6ef4a39b1b8648d Mon Sep 17 00:00:00 2001 From: "miroslav.kovac" Date: Fri, 30 Oct 2020 12:36:14 +0100 Subject: [PATCH] Add StmtContext.findFirstSubstatementArgument() Introduce utility methods to StmtContext, so that individual implementations can provide optimized version, which does not walk all children. InferredStatementContext used this facility to defer to protype, side-stepping the need to materialize substatements. JIRA: YANGTOOLS-1157 Change-Id: I9e618d3a51f68ed03a76c718b657be38e5cedb5d Signed-off-by: miroslav.kovac Signed-off-by: Robert Varga --- .../reactor/InferredStatementContext.java | 25 +++++++++ .../AbstractAugmentStatementSupport.java | 3 +- .../yang/parser/spi/meta/StmtContext.java | 34 ++++++++++++ .../parser/spi/meta/StmtContextDefaults.java | 53 +++++++++++++++++++ .../parser/spi/meta/StmtContextUtils.java | 15 +++--- 5 files changed, 121 insertions(+), 9 deletions(-) create mode 100644 yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextDefaults.java diff --git a/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/InferredStatementContext.java b/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/InferredStatementContext.java index 08b632cb80..88e491e265 100644 --- a/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/InferredStatementContext.java +++ b/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/InferredStatementContext.java @@ -30,6 +30,7 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType; import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.OnDemandSchemaTreeStorageNode; import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.StorageNodeType; import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext; +import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextDefaults; import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -164,6 +165,30 @@ final class InferredStatementContext, E extend return hasEmptyEffectiveSubstatements(); } + @Override + public > @NonNull Optional findSubstatementArgument( + final @NonNull Class type) { + if (substatementsInitialized()) { + return StmtContextDefaults.findSubstatementArgument(this, type); + } + + final Optional templateArg = prototype.findSubstatementArgument(type); + if (templateArg.isEmpty()) { + return templateArg; + } + if (SchemaTreeEffectiveStatement.class.isAssignableFrom(type)) { + // X is known to be QName + return (Optional) templateArg.map(template -> ((QName) template).bindTo(targetModule)); + } + return templateArg; + } + + @Override + public boolean hasSubstatement(final @NonNull Class> type) { + return substatementsInitialized() ? StmtContextDefaults.hasSubstatement(prototype, type) + : prototype.hasSubstatement(type); + } + @Override public , E extends EffectiveStatement> StmtContext requestSchemaTreeChild(final QName qname) { 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 3925f22046..79b6bcde02 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 @@ -32,6 +32,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.StatusEffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.UsesStatement; +import org.opendaylight.yangtools.yang.model.api.stmt.WhenEffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.WhenStatement; import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.ChildSchemaNodeNamespace; import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.ArgumentUtils; @@ -242,7 +243,7 @@ abstract class AbstractAugmentStatementSupport } private static boolean hasWhenSubstatement(final StmtContext ctx) { - return StmtContextUtils.findFirstSubstatement(ctx, WhenStatement.class) != null; + return ctx.hasSubstatement(WhenEffectiveStatement.class); } private static void copyStatement(final Mutable original, final StatementContextBase target, diff --git a/yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContext.java b/yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContext.java index 2ca1a018e9..337a5fba1a 100644 --- a/yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContext.java +++ b/yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContext.java @@ -391,4 +391,38 @@ public interface StmtContext, E extends Effect void setIsSupportedToBuildEffective(boolean isSupportedToBuild); } + + /** + * Search of any child statement context of specified type and return its argument. If such a statement exists, it + * is assumed to have the right argument. Users should be careful to use this method for statements which have + * cardinality {@code 0..1}, otherwise this method can return any one of the statement's argument. + * + *

+ * The default implementation defers to + * {@link StmtContextDefaults#findSubstatementArgument(StmtContext, Class)}, subclasses are expected to provide + * optimized implementation if possible. + * + * @param Substatement argument type + * @param Substatement effective statement representation + * @param type Effective statement representation being look up + * @return {@link Optional#empty()} if no statement exists, otherwise the argument value + */ + default > @NonNull Optional findSubstatementArgument( + final @NonNull Class type) { + return StmtContextDefaults.findSubstatementArgument(this, type); + } + + /** + * Check if there is any child statement context of specified type. + * + *

+ * The default implementation defers to {@link StmtContextDefaults#hasSubstatement(StmtContext, Class)}, + * subclasses are expected to provide optimized implementation if possible. + * + * @param type Effective statement representation being look up + * @return True if such a child statement exists, false otherwise + */ + default boolean hasSubstatement(final @NonNull Class> type) { + return StmtContextDefaults.hasSubstatement(this, type); + } } diff --git a/yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextDefaults.java b/yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextDefaults.java new file mode 100644 index 0000000000..a5692a860d --- /dev/null +++ b/yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextDefaults.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2020 PANTHEON.tech, s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.yangtools.yang.parser.spi.meta; + +import java.util.Optional; +import org.eclipse.jdt.annotation.NonNull; +import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; + +/** + * Default implementations for various {@link StmtContext} methods. Code hosted here is meant for use by actual + * {@link StmtContext} implementations, not for general use by others. + */ +public final class StmtContextDefaults { + private StmtContextDefaults() { + // Hidden on purpose + } + + /** + * Default implementation of {@link StmtContext#findSubstatementArgument(Class)}. See that method for API contract. + * + * @param Substatement argument type + * @param Substatement effective statement representation + * @param stmt Statement context to search + * @param type Effective statement representation being look up + * @return Effective statement argument, if found + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static > @NonNull Optional findSubstatementArgument( + final @NonNull StmtContext stmt, final @NonNull Class type) { + return stmt.allSubstatementsStream() + .filter(ctx -> ((StmtContext) ctx).producesEffective(type)) + .findAny() + .map(ctx -> (A) ctx.coerceStatementArgument()); + } + + /** + * Default implementation of {@link StmtContext#hasSubstatement(Class)}. See that method for API contract. + * + * @param stmt Statement context to search + * @param type Effective statement representation being look up + * @return True if a match is found, false otherwise + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static boolean hasSubstatement(final @NonNull StmtContext stmt, + @SuppressWarnings("rawtypes") final @NonNull Class> type) { + return stmt.allSubstatementsStream().anyMatch(ctx -> ((StmtContext) ctx).producesEffective(type)); + } +} diff --git a/yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextUtils.java b/yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextUtils.java index 49a8ad589e..4b1678e2d3 100644 --- a/yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextUtils.java +++ b/yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextUtils.java @@ -29,7 +29,7 @@ import org.opendaylight.yangtools.yang.model.api.stmt.LeafStatement; import org.opendaylight.yangtools.yang.model.api.stmt.MandatoryStatement; import org.opendaylight.yangtools.yang.model.api.stmt.MinElementsStatement; import org.opendaylight.yangtools.yang.model.api.stmt.ModuleStatement; -import org.opendaylight.yangtools.yang.model.api.stmt.PresenceStatement; +import org.opendaylight.yangtools.yang.model.api.stmt.PresenceEffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.RevisionStatement; import org.opendaylight.yangtools.yang.model.api.stmt.SubmoduleStatement; import org.opendaylight.yangtools.yang.model.api.stmt.UnknownStatement; @@ -148,7 +148,9 @@ public final class StmtContextUtils { * @param statement argument type * @param declared statement type * @return statement context that was searched for or null if was not found + * @deprecated Use {@link StmtContext#findSubstatementArgument(Class)} instead. */ + @Deprecated(forRemoval = true) public static > StmtContext findFirstSubstatement( final StmtContext stmtContext, final Class declaredType) { final StmtContext effectiveSubstatement = findFirstEffectiveSubstatement(stmtContext, declaredType); @@ -286,7 +288,7 @@ public final class StmtContextUtils { } private static boolean containsPresenceSubStmt(final StmtContext stmtCtx) { - return findFirstSubstatement(stmtCtx, PresenceStatement.class) != null; + return stmtCtx.hasSubstatement(PresenceEffectiveStatement.class); } /** @@ -376,12 +378,9 @@ public final class StmtContextUtils { StmtContext current = ctx.coerceParentContext(); StmtContext parent = current.getParentContext(); while (parent != null) { - if (ancestorType.equals(current.getPublicDefinition())) { - @SuppressWarnings("unchecked") - final Class ancestorChildTypeClass = (Class) ancestorChildType.getDeclaredRepresentationClass(); - if (findFirstSubstatement(current, ancestorChildTypeClass) == null) { - return false; - } + if (ancestorType.equals(current.getPublicDefinition()) + && !current.hasSubstatement(ancestorChildType.getEffectiveRepresentationClass())) { + return false; } current = parent; -- 2.36.6