From: miroslav.kovac Date: Fri, 30 Oct 2020 11:36:14 +0000 (+0100) Subject: Add StmtContext.findFirstSubstatementArgument() X-Git-Tag: v6.0.1~16 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=yangtools.git;a=commitdiff_plain;h=c31a90ed7c04bc622c9404a4a6ef4a39b1b8648d 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 --- 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;