X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=yang%2Fyang-parser-reactor%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fparser%2Fstmt%2Freactor%2FStatementContextBase.java;h=5a65edbd5e7e840511e337ec97befa9f58e87577;hb=5db72610e7358baa1f5c9dd85abc9e93f3c8b020;hp=5c1095e061188870e6f9be77b35616be59462f9e;hpb=1a43b3d0a8572dfa034fb54fc10fc1a988c8f2dd;p=yangtools.git diff --git a/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java b/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java index 5c1095e061..5a65edbd5e 100644 --- a/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java +++ b/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java @@ -32,6 +32,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Optional; import java.util.Set; +import java.util.stream.Stream; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.opendaylight.yangtools.yang.common.QName; @@ -42,9 +43,8 @@ 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.meta.IdentifierNamespace; import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition; -import org.opendaylight.yangtools.yang.model.api.meta.StatementSource; import org.opendaylight.yangtools.yang.model.api.stmt.AugmentStatement; -import org.opendaylight.yangtools.yang.model.api.stmt.ConfigStatement; +import org.opendaylight.yangtools.yang.model.api.stmt.ConfigEffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.DeviationStatement; import org.opendaylight.yangtools.yang.model.api.stmt.RefineStatement; import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier; @@ -69,7 +69,6 @@ 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.ImplicitSubstatement; import org.opendaylight.yangtools.yang.parser.spi.source.SourceException; -import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference; import org.opendaylight.yangtools.yang.parser.spi.source.SupportedFeaturesNamespace; import org.opendaylight.yangtools.yang.parser.spi.source.SupportedFeaturesNamespace.SupportedFeatures; import org.opendaylight.yangtools.yang.parser.stmt.reactor.NamespaceBehaviourWithListeners.KeyedValueAddedListener; @@ -141,7 +140,7 @@ public abstract class StatementContextBase, E private Multimap phaseListeners = ImmutableMultimap.of(); private Multimap phaseMutation = ImmutableMultimap.of(); - private List> effective = ImmutableList.of(); + private List> effectOfStatement = ImmutableList.of(); private @Nullable ModelProcessingPhase completedPhase; @@ -312,11 +311,6 @@ public abstract class StatementContextBase, E return getRoot().isEnabledSemanticVersioningImpl(); } - @Override - public StatementSource getStatementSource() { - return getStatementSourceReference().getStatementSource(); - } - @Override public final > Map getAllFromCurrentStmtCtxNamespace( final Class type) { @@ -343,7 +337,7 @@ public abstract class StatementContextBase, E */ @Override public final > void addToNs( - final Class type, final T key, final U value) { + final Class<@NonNull N> type, final T key, final U value) { addToNamespace(type, key, value); } @@ -363,40 +357,38 @@ public abstract class StatementContextBase, E * @throws NamespaceNotAvailableException when the namespace is not available. */ @Override - public final > V getFromNamespace(final Class type, - final T key) { + public final > V getFromNamespace( + final Class<@NonNull N> type, final T key) { return getBehaviourRegistry().getNamespaceBehaviour(type).getFrom(this, key); } - @Override - public Collection> mutableEffectiveSubstatements() { - if (effective instanceof ImmutableCollection) { - return effective; - } - - return Collections.unmodifiableCollection(effective); + static final Collection> mutableEffectiveSubstatements( + final List> effective) { + return effective instanceof ImmutableCollection ? effective : Collections.unmodifiableCollection(effective); } - private void shrinkEffective() { - if (effective.isEmpty()) { - effective = ImmutableList.of(); - } + private static List> shrinkEffective( + final List> effective) { + return effective.isEmpty() ? ImmutableList.of() : effective; } - public void removeStatementFromEffectiveSubstatements(final StatementDefinition statementDef) { + public abstract void removeStatementFromEffectiveSubstatements(StatementDefinition statementDef); + + static final List> removeStatementFromEffectiveSubstatements( + final List> effective, final StatementDefinition statementDef) { if (effective.isEmpty()) { - return; + return effective; } final Iterator> iterator = effective.iterator(); while (iterator.hasNext()) { final StmtContext next = iterator.next(); - if (statementDef.equals(next.getPublicDefinition())) { + if (statementDef.equals(next.publicDefinition())) { iterator.remove(); } } - shrinkEffective(); + return shrinkEffective(effective); } /** @@ -411,25 +403,29 @@ public abstract class StatementContextBase, E * @param statementDef statement definition of the statement context to remove * @param statementArg statement argument of the statement context to remove */ - public void removeStatementFromEffectiveSubstatements(final StatementDefinition statementDef, + public abstract void removeStatementFromEffectiveSubstatements(StatementDefinition statementDef, + String statementArg); + + static final List> removeStatementFromEffectiveSubstatements( + final List> effective, final StatementDefinition statementDef, final String statementArg) { if (statementArg == null) { - removeStatementFromEffectiveSubstatements(statementDef); + return removeStatementFromEffectiveSubstatements(effective, statementDef); } if (effective.isEmpty()) { - return; + return effective; } final Iterator> iterator = effective.iterator(); while (iterator.hasNext()) { final Mutable next = iterator.next(); - if (statementDef.equals(next.getPublicDefinition()) && statementArg.equals(next.rawStatementArgument())) { + if (statementDef.equals(next.publicDefinition()) && statementArg.equals(next.rawArgument())) { iterator.remove(); } } - shrinkEffective(); + return shrinkEffective(effective); } // YANG example: RPC/action statements always have 'input' and 'output' defined @@ -439,7 +435,7 @@ public abstract class StatementContextBase, E // FIXME: YANGTOOLS-652: This does not need to be a SubstatementContext, in can be a specialized // StatementContextBase subclass. final Mutable ret = new SubstatementContext<>(this, new StatementDefinitionContext<>(support), - ImplicitSubstatement.of(getStatementSourceReference()), rawArg); + ImplicitSubstatement.of(sourceReference()), rawArg); support.onStatementAdded(ret); addEffectiveSubstatement(ret); return ret; @@ -449,21 +445,23 @@ public abstract class StatementContextBase, E * Adds an effective statement to collection of substatements. * * @param substatement substatement - * @throws IllegalStateException - * if added in declared phase - * @throws NullPointerException - * if statement parameter is null + * @throws IllegalStateException if added in declared phase + * @throws NullPointerException if statement parameter is null */ - public void addEffectiveSubstatement(final Mutable substatement) { + public abstract void addEffectiveSubstatement(Mutable substatement); + + final List> addEffectiveSubstatement( + final List> effective, final Mutable substatement) { verifyStatement(substatement); - beforeAddEffectiveStatement(1); + final List> resized = beforeAddEffectiveStatement(effective, 1); final StatementContextBase stmt = (StatementContextBase) substatement; final ModelProcessingPhase phase = completedPhase; if (phase != null) { ensureCompletedPhase(stmt, phase); } - effective.add(stmt); + resized.add(stmt); + return resized; } /** @@ -475,21 +473,40 @@ public abstract class StatementContextBase, E * @throws NullPointerException * if statement parameter is null */ - public void addEffectiveSubstatements(final Collection> statements) { + public final void addEffectiveSubstatements(final Collection> statements) { if (!statements.isEmpty()) { statements.forEach(StatementContextBase::verifyStatement); - beforeAddEffectiveStatement(statements.size()); - - final Collection> casted = - (Collection>) statements; - final ModelProcessingPhase phase = completedPhase; - if (phase != null) { - for (StatementContextBase stmt : casted) { - ensureCompletedPhase(stmt, phase); - } + addEffectiveSubstatementsImpl(statements); + } + } + + abstract void addEffectiveSubstatementsImpl(Collection> statements); + + final List> addEffectiveSubstatementsImpl( + final List> effective, + final Collection> statements) { + final List> resized = beforeAddEffectiveStatement(effective, statements.size()); + final Collection> casted = + (Collection>) statements; + final ModelProcessingPhase phase = completedPhase; + if (phase != null) { + for (StatementContextBase stmt : casted) { + ensureCompletedPhase(stmt, phase); } + } + + resized.addAll(casted); + return resized; + } + + abstract Iterable> effectiveChildrenToComplete(); - effective.addAll(casted); + // exposed for InferredStatementContext only + final void ensureCompletedPhase(final Mutable stmt) { + verifyStatement(stmt); + final ModelProcessingPhase phase = completedPhase; + if (phase != null) { + ensureCompletedPhase((StatementContextBase) stmt, phase); } } @@ -505,37 +522,48 @@ public abstract class StatementContextBase, E verify(stmt instanceof StatementContextBase, "Unexpected statement %s", stmt); } - private void beforeAddEffectiveStatement(final int toAdd) { + private List> beforeAddEffectiveStatement( + final List> effective, final int toAdd) { // We cannot allow statement to be further mutated - final StatementSourceReference ref = getStatementSourceReference(); - verify(completedPhase != ModelProcessingPhase.EFFECTIVE_MODEL, "Cannot modify finished statement at %s", ref); + verify(completedPhase != ModelProcessingPhase.EFFECTIVE_MODEL, "Cannot modify finished statement at %s", + sourceReference()); + return beforeAddEffectiveStatementUnsafe(effective, toAdd); + } + final List> beforeAddEffectiveStatementUnsafe( + final List> effective, final int toAdd) { final ModelProcessingPhase inProgressPhase = getRoot().getSourceContext().getInProgressPhase(); checkState(inProgressPhase == ModelProcessingPhase.FULL_DECLARATION || inProgressPhase == ModelProcessingPhase.EFFECTIVE_MODEL, - "Effective statement cannot be added in declared phase at: %s", ref); + "Effective statement cannot be added in declared phase at: %s", sourceReference()); - if (effective.isEmpty()) { - effective = new ArrayList<>(toAdd); - } + return effective.isEmpty() ? new ArrayList<>(toAdd) : effective; } - // Exists only due to memory optimization + // These two exists only due to memory optimization, should live in AbstractResumedStatement final boolean fullyDefined() { return fullyDefined; } - // Exists only due to memory optimization, should live in AbstractResumedStatement final void setFullyDefined() { fullyDefined = true; } @Override public E buildEffective() { - final E existing = effectiveInstance; - return existing != null ? existing : (effectiveInstance = definition.getFactory().createEffective(this)); + final E existing; + return (existing = effectiveInstance) != null ? existing : loadEffective(); + } + + private E loadEffective() { + return effectiveInstance = definition.getFactory().createEffective(new BaseCurrentEffectiveStmtCtx<>(this), + streamDeclared(), streamEffective()); } + abstract Stream> streamDeclared(); + + abstract Stream> streamEffective(); + /** * Try to execute current {@link ModelProcessingPhase} of source parsing. If the phase has already been executed, * this method does nothing. @@ -562,7 +590,7 @@ public abstract class StatementContextBase, E for (final StatementContextBase child : mutableDeclaredSubstatements()) { finished &= child.tryToCompletePhase(phase); } - for (final StatementContextBase child : effective) { + for (final StatementContextBase child : effectiveChildrenToComplete()) { finished &= child.tryToCompletePhase(phase); } return finished; @@ -587,13 +615,17 @@ public abstract class StatementContextBase, E if (openMutations.isEmpty()) { phaseMutation.removeAll(phase); - if (phaseMutation.isEmpty()) { - phaseMutation = ImmutableMultimap.of(); - } + cleanupPhaseMutation(); } return finished; } + private void cleanupPhaseMutation() { + if (phaseMutation.isEmpty()) { + phaseMutation = ImmutableMultimap.of(); + } + } + /** * Occurs on end of {@link ModelProcessingPhase} of source parsing. * @@ -727,12 +759,12 @@ public abstract class StatementContextBase, E } @Override - public StatementDefinition getPublicDefinition() { + public final StatementDefinition publicDefinition() { return definition.getPublicView(); } @Override - public ModelActionBuilder newInferenceAction(final ModelProcessingPhase phase) { + public final ModelActionBuilder newInferenceAction(final ModelProcessingPhase phase) { return getRoot().getSourceContext().newInferenceAction(phase); } @@ -749,8 +781,8 @@ public abstract class StatementContextBase, E * @throws NullPointerException if any of the arguments is null */ void addPhaseCompletedListener(final ModelProcessingPhase phase, final OnPhaseFinished listener) { - checkNotNull(phase, "Statement context processing phase cannot be null at: %s", getStatementSourceReference()); - checkNotNull(listener, "Statement context phase listener cannot be null at: %s", getStatementSourceReference()); + checkNotNull(phase, "Statement context processing phase cannot be null at: %s", sourceReference()); + checkNotNull(listener, "Statement context phase listener cannot be null at: %s", sourceReference()); ModelProcessingPhase finishedPhase = completedPhase; while (finishedPhase != null) { @@ -770,14 +802,13 @@ public abstract class StatementContextBase, E /** * Adds a {@link ContextMutation} to a {@link ModelProcessingPhase}. * - * @throws IllegalStateException - * when the mutation was registered after phase was completed + * @throws IllegalStateException when the mutation was registered after phase was completed */ - void addMutation(final ModelProcessingPhase phase, final ContextMutation mutation) { + final void addMutation(final ModelProcessingPhase phase, final ContextMutation mutation) { ModelProcessingPhase finishedPhase = completedPhase; while (finishedPhase != null) { checkState(!phase.equals(finishedPhase), "Mutation registered after phase was completed at: %s", - getStatementSourceReference()); + sourceReference()); finishedPhase = finishedPhase.getPreviousPhase(); } @@ -787,8 +818,15 @@ public abstract class StatementContextBase, E phaseMutation.put(phase, mutation); } + final void removeMutation(final ModelProcessingPhase phase, final ContextMutation mutation) { + if (!phaseMutation.isEmpty()) { + phaseMutation.remove(phase, mutation); + cleanupPhaseMutation(); + } + } + @Override - public > void addContext(final Class namespace, + public > void addContext(final Class<@NonNull N> namespace, final KT key,final StmtContext stmt) { addContextToNamespace(namespace, key, stmt); } @@ -836,15 +874,15 @@ public abstract class StatementContextBase, E private , Z extends EffectiveStatement> Mutable childCopyOf( final StatementContextBase original, final CopyType type, final QNameModule targetModule) { final Optional> implicitParent = definition.getImplicitParentFor( - original.getPublicDefinition()); + original.publicDefinition()); final StatementContextBase result; final InferredStatementContext copy; if (implicitParent.isPresent()) { final StatementDefinitionContext def = new StatementDefinitionContext<>(implicitParent.get()); - result = new SubstatementContext(this, def, original.getStatementSourceReference(), - original.rawStatementArgument(), original.getStatementArgument(), type); + result = new SubstatementContext(this, def, original.sourceReference(), original.rawArgument(), + original.argument(), type); final CopyType childCopyType; switch (type) { @@ -884,7 +922,7 @@ public abstract class StatementContextBase, E @Beta public final StatementContextBase wrapWithImplicit(final StatementContextBase original) { final Optional> optImplicit = definition.getImplicitParentFor( - original.getPublicDefinition()); + original.publicDefinition()); if (optImplicit.isEmpty()) { return original; } @@ -892,8 +930,7 @@ public abstract class StatementContextBase, E final StatementDefinitionContext def = new StatementDefinitionContext<>(optImplicit.get()); final CopyType type = original.getCopyHistory().getLastOperation(); final SubstatementContext result = new SubstatementContext(original.getParentContext(), def, - original.getStatementSourceReference(), original.rawStatementArgument(), original.getStatementArgument(), - type); + original.sourceReference(), original.rawArgument(), original.argument(), type); result.addEffectiveSubstatement(original.reparent(result)); result.setCompletedPhase(original.getCompletedPhase()); @@ -909,10 +946,6 @@ public abstract class StatementContextBase, E */ abstract boolean hasEmptySubstatements(); - final boolean hasEmptyEffectiveSubstatements() { - return effective.isEmpty(); - } - /** * Config statements are not all that common which means we are performing a recursive search towards the root * every time {@link #isConfiguration()} is invoked. This is quite expensive because it causes a linear search @@ -936,14 +969,13 @@ public abstract class StatementContextBase, E return true; } - final StmtContext configStatement = StmtContextUtils.findFirstSubstatement(this, - ConfigStatement.class); final boolean isConfig; - if (configStatement != null) { - isConfig = configStatement.coerceStatementArgument(); + final Optional optConfig = findSubstatementArgument(ConfigEffectiveStatement.class); + if (optConfig.isPresent()) { + isConfig = optConfig.orElseThrow(); if (isConfig) { // Validity check: if parent is config=false this cannot be a config=true - InferenceException.throwIf(!parent.isConfiguration(), getStatementSourceReference(), + InferenceException.throwIf(!parent.isConfiguration(), sourceReference(), "Parent node has config=false, this node must not be specifed as config=true"); } } else { @@ -1002,15 +1034,17 @@ public abstract class StatementContextBase, E return false; } - // Exists only to support SubstatementContext/InferredStatementContext + abstract @NonNull Optional schemaPath(); + + // Exists only to support {SubstatementContext,InferredStatementContext}.schemaPath() + @Deprecated final @NonNull Optional substatementGetSchemaPath() { SchemaPath local = schemaPath; if (local == null) { synchronized (this) { local = schemaPath; if (local == null) { - local = createSchemaPath(coerceParentContext()); - schemaPath = local; + schemaPath = local = createSchemaPath((StatementContextBase) coerceParentContext()); } } } @@ -1018,18 +1052,19 @@ public abstract class StatementContextBase, E return Optional.ofNullable(local); } - private SchemaPath createSchemaPath(final Mutable parent) { - final Optional maybeParentPath = parent.getSchemaPath(); + @Deprecated + private SchemaPath createSchemaPath(final StatementContextBase parent) { + final Optional maybeParentPath = parent.schemaPath(); verify(maybeParentPath.isPresent(), "Parent %s does not have a SchemaPath", parent); final SchemaPath parentPath = maybeParentPath.get(); if (StmtContextUtils.isUnknownStatement(this)) { - return parentPath.createChild(getPublicDefinition().getStatementName()); + return parentPath.createChild(publicDefinition().getStatementName()); } final Object argument = getStatementArgument(); if (argument instanceof QName) { final QName qname = (QName) argument; - if (StmtContextUtils.producesDeclared(this, UsesStatement.class)) { + if (producesDeclared(UsesStatement.class)) { return maybeParentPath.orElse(null); } @@ -1042,11 +1077,10 @@ public abstract class StatementContextBase, E return parentPath.createChild(qname); } if (argument instanceof SchemaNodeIdentifier - && (StmtContextUtils.producesDeclared(this, AugmentStatement.class) - || StmtContextUtils.producesDeclared(this, RefineStatement.class) - || StmtContextUtils.producesDeclared(this, DeviationStatement.class))) { + && (producesDeclared(AugmentStatement.class) || producesDeclared(RefineStatement.class) + || producesDeclared(DeviationStatement.class))) { - return parentPath.createChild(((SchemaNodeIdentifier) argument).getPathFromRoot()); + return parentPath.createChild(((SchemaNodeIdentifier) argument).getNodeIdentifiers()); } // FIXME: this does not look right @@ -1059,6 +1093,6 @@ public abstract class StatementContextBase, E } protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) { - return toStringHelper.add("definition", definition).add("rawArgument", rawStatementArgument()); + return toStringHelper.add("definition", definition).add("rawArgument", rawArgument()); } }