import com.google.common.base.VerifyException;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Streams;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
import java.util.Optional;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
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.StatementFactory;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
return new InferredStatementContext<>(this, newParent);
}
+ @Override
+ E createEffective(final StatementFactory<A, D, E> factory) {
+ // If we have not materialized we do not have a difference in effective substatements, hence we can forward
+ // towards the source of the statement.
+ return substatements == null ? tryToReusePrototype(factory) : super.createEffective(factory);
+ }
+
+ private @NonNull E tryToReusePrototype(final StatementFactory<A, D, E> factory) {
+ final E origEffective = prototype.buildEffective();
+ final Collection<? extends @NonNull EffectiveStatement<?, ?>> origSubstatements =
+ origEffective.effectiveSubstatements();
+
+ // First check if we can reuse the entire prototype
+ if (!factory.canReuseCurrent(this, prototype, origSubstatements)) {
+ // FIXME: YANGTOOLS-1067: an incremental improvement here is that we reuse statements that are not affected
+ // by us changing parent. For example: if our SchemaPath changed, but the namespace
+ // remained the same, 'key' statement should get reused.
+ // Fall back to full instantiation
+ return super.createEffective(factory);
+ }
+
+ // No substatements to deal with, we can freely reuse the original
+ if (origSubstatements.isEmpty()) {
+ LOG.debug("Reusing empty: {}", origEffective);
+ substatements = ImmutableList.of();
+ prototype.decRef();
+ return origEffective;
+ }
+
+ // We can reuse this statement let's see if all the statements agree
+ final List<Entry<Mutable<?, ?, ?>, Mutable<?, ?, ?>>> declared = prototype.streamDeclared()
+ .filter(StmtContext::isSupportedByFeatures)
+ .map(sub -> effectiveCopy((ReactorStmtCtx<?, ?, ?>) sub))
+ .filter(Objects::nonNull)
+ .collect(Collectors.toUnmodifiableList());
+ final List<Entry<Mutable<?, ?, ?>, Mutable<?, ?, ?>>> effective = prototype.streamEffective()
+ .map(sub -> effectiveCopy((ReactorStmtCtx<?, ?, ?>) sub))
+ .filter(Objects::nonNull)
+ .collect(Collectors.toUnmodifiableList());
+
+ // We no longer need the prototype's substatements, but we may need to retain ours
+ prototype.decRef();
+ if (haveRef()) {
+ substatements = Streams.concat(declared.stream(), effective.stream())
+ .map(Entry::getValue)
+ .collect(ImmutableList.toImmutableList());
+ } else {
+ // This should immediately get swept anyway. Should we use a poison object?
+ substatements = List.of();
+ }
+
+ if (allReused(declared) && allReused(effective)) {
+ LOG.debug("Reusing after substatement check: {}", origEffective);
+ return origEffective;
+ }
+
+ // Values are the effective copies, hence this efficienly deals with recursion.
+ return factory.createEffective(this, declared.stream().map(Entry::getValue),
+ effective.stream().map(Entry::getValue));
+ }
+
+ private static boolean allReused(final List<Entry<Mutable<?, ?, ?>, Mutable<?, ?, ?>>> entries) {
+ for (Entry<Mutable<?, ?, ?>, Mutable<?, ?, ?>> entry : entries) {
+ if (entry.getKey() != entry.getValue()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
@Override
boolean hasEmptySubstatements() {
if (substatements == null) {
YangStmtMapping.TYPEDEF,
YangStmtMapping.USES);
+ private Map.Entry<Mutable<?, ?, ?>, Mutable<?, ?, ?>> effectiveCopy(final ReactorStmtCtx<?, ?, ?> stmt) {
+ // FIXME: YANGTOOLS-652: formerly known as "isReusedByUses"
+ if (REUSED_DEF_SET.contains(stmt.definition().getPublicView())) {
+ return Map.entry(stmt, stmt.replicaAsChildOf(this));
+ }
+
+ final ReactorStmtCtx<?, ?, ?> effective = stmt.asEffectiveChildOf(this, childCopyType, targetModule);
+ return effective == null ? null : Map.entry(stmt, effective);
+ }
+
private void copySubstatement(final Mutable<?, ?, ?> substatement, final Collection<Mutable<?, ?, ?>> buffer,
final Map<StmtContext<?, ?, ?>, ReactorStmtCtx<?, ?, ?>> materializedSchemaTree) {
final StatementDefinition def = substatement.publicDefinition();
}
private Optional<? extends Mutable<?, ?, ?>> copySubstatement(final Mutable<?, ?, ?> substatement) {
- // FIXME: YANGTOOLS-1195: this is not exactly what we want to do here, because we are deling with two different
+ // FIXME: YANGTOOLS-1195: this is not exactly what we want to do here, because we are dealing with two different
// requests: copy for inference purposes (this method), while we also copy for purposes
// of buildEffective() -- in which case we want to probably invoke asEffectiveChildOf()
// or similar
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.common.YangVersion;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
import org.opendaylight.yangtools.yang.model.api.stmt.UsesStatement;
import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
// definition().onNamespaceElementAdded(this, type, key, value);
}
+ abstract @Nullable ReactorStmtCtx<?, ?, ?> asEffectiveChildOf(StatementContextBase<?, ?, ?> parent, CopyType type,
+ QNameModule targetModule);
+
//
//
// Statement build entry points -- both public and package-private.
}
}
+ /**
+ * Return {@code true} if this context has an outstanding reference.
+ *
+ * @return True if this context has an outstanding reference.
+ */
+ final boolean haveRef() {
+ return refcount > REFCOUNT_NONE;
+ }
+
private void lastDecRef() {
if (noImplictRef()) {
// We are no longer guarded by effective instance
return source.copyAsChildOf(newParent, type, targetModule);
}
+ @Override
+ ReactorStmtCtx<?, ?, ?> asEffectiveChildOf(final StatementContextBase<?, ?, ?> newParent, final CopyType type,
+ final QNameModule targetModule) {
+ return source.asEffectiveChildOf(newParent, type, targetModule);
+ }
+
@Override
StatementDefinitionContext<A, D, E> definition() {
return source.definition();
import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceKeyCriterion;
import org.opendaylight.yangtools.yang.parser.spi.meta.ParserNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementFactory;
import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport.CopyPolicy;
return effective.isEmpty() ? new ArrayList<>(toAdd) : effective;
}
-
@Override
final E createEffective() {
- final E result = definition.getFactory().createEffective(this, streamDeclared(), streamEffective());
+ final E result = createEffective(definition.getFactory());
if (result instanceof MutableStatement) {
getRoot().addMutableStmtToSeal((MutableStatement) result);
}
return result;
}
+ @NonNull E createEffective(final StatementFactory<A, D, E> factory) {
+ return createEffective(factory, this);
+ }
+
+ // Creates EffectiveStatement through full materialization
+ static <A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>> @NonNull E createEffective(
+ final StatementFactory<A, D, E> factory, final StatementContextBase<A, D, E> ctx) {
+ return factory.createEffective(ctx, ctx.streamDeclared(), ctx.streamEffective());
+ }
+
abstract Stream<? extends StmtContext<?, ?, ?>> streamDeclared();
abstract Stream<? extends StmtContext<?, ?, ?>> streamEffective();
public Optional<? extends Mutable<?, ?, ?>> copyAsChildOf(final Mutable<?, ?, ?> parent, final CopyType type,
final QNameModule targetModule) {
checkEffectiveModelCompleted(this);
+ return Optional.ofNullable(copyAsChildOfImpl(parent, type, targetModule));
+ }
+ private ReactorStmtCtx<A, D, E> copyAsChildOfImpl(final Mutable<?, ?, ?> parent, final CopyType type,
+ final QNameModule targetModule) {
final StatementSupport<A, D, E> support = definition.support();
final CopyPolicy policy = support.copyPolicy();
switch (policy) {
case CONTEXT_INDEPENDENT:
- if (substatementsContextIndependent()) {
- return Optional.of(replicaAsChildOf(parent));
+ if (allSubstatementsContextIndependent()) {
+ return replicaAsChildOf(parent);
}
// fall through
case DECLARED_COPY:
- return Optional.of(parent.childCopyOf(this, type, targetModule));
+ // FIXME: ugly cast
+ return (ReactorStmtCtx<A, D, E>) parent.childCopyOf(this, type, targetModule);
case IGNORE:
- return Optional.empty();
+ return null;
case REJECT:
throw new IllegalStateException("Statement " + support.getPublicView() + " should never be copied");
default:
}
}
- private boolean substatementsContextIndependent() {
- // FIXME: YANGTOOLS-1195: we really want to compute (and cache) the summary for substatements.
- //
- // For now we just check if there are any substatements, but we really want to ask:
- //
- // Are all substatements (recursively) CONTEXT_INDEPENDENT as well?
- //
- // Which is something we want to compute once and store. This needs to be implemented.
- return hasEmptySubstatements();
- }
+ @Override
+ final ReactorStmtCtx<?, ?, ?> asEffectiveChildOf(final StatementContextBase<?, ?, ?> parent, final CopyType type,
+ final QNameModule targetModule) {
+ final ReactorStmtCtx<A, D, E> copy = copyAsChildOfImpl(parent, type, targetModule);
+ if (copy == null) {
+ // The statement fizzled, this should never happen, perhaps a verify()?
+ return null;
+ }
- // FIXME: YANGTOOLS-1195: this method is unused, but should be called from InferredStatementContext at the very
- // least. It should return @NonNull -- either 'E' or EffectiveStmtCtx.Current'. Perhaps its arguments need
- // to be adjusted, too.
- final void asEffectiveChildOf(final Mutable<?, ?, ?> parent, final CopyType type, final QNameModule targetModule) {
- checkEffectiveModelCompleted(this);
+ parent.ensureCompletedPhase(copy);
+ return canReuseCurrent(copy) ? replicaAsChildOf(parent) : copy;
+ }
- final StatementSupport<A, D, E> support = definition.support();
- final StmtContext<?, ?, ?> effective = support.effectiveCopyOf(this, parent, type, targetModule);
- if (effective == this) {
- LOG.debug("Should reuse {}", this);
- return;
- }
+ private boolean canReuseCurrent(final ReactorStmtCtx<A, D, E> copy) {
+ // Defer to statement factory to see if we can reuse this object. If we can and have only context-independent
+ // substatements we can reuse the object. More complex cases are handled indirectly via the copy.
+ return definition.getFactory().canReuseCurrent(copy, this, buildEffective().effectiveSubstatements())
+ && allSubstatementsContextIndependent();
+ }
- // FIXME: YANGTOOLS-1195: here is probably where we want to do some statement reuse: even if the parent is
- // affected, some substatements may not -- in which case we want to reuse them. This
- // probably needs to be a callout of some kind.
- // FIXME: YANGTOOLS-1067: an incremental improvement to that is that if no substatements changed, we want to
- // be reusing the entire List<EffectiveStatement> and pass that as substatements.
+ // FIXME: YANGTOOLS-1195: we really want to compute (and cache) the summary for substatements.
+ //
+ // For now we just check if there are any substatements, but we really want to ask:
+ //
+ // Are all substatements (recursively) CONTEXT_INDEPENDENT as well?
+ //
+ // Which is something we want to compute once and store. This needs to be implemented.
+ private boolean allSubstatementsContextIndependent() {
+ return hasEmptySubstatements();
}
@Override
@Beta
public abstract class BaseStatementSupport<A, D extends DeclaredStatement<A>,
E extends EffectiveStatement<A, D>> extends AbstractStatementSupport<A, D, E> {
-
+ @Deprecated
protected BaseStatementSupport(final StatementDefinition publicDefinition, final CopyPolicy copyPolicy) {
super(publicDefinition, copyPolicy);
}
+ protected BaseStatementSupport(final StatementDefinition publicDefinition, final StatementPolicy<A, D> policy) {
+ super(publicDefinition, policy);
+ }
+
@Override
public final D createDeclared(final StmtContext<A, D, ?> ctx) {
final ImmutableList<? extends DeclaredStatement<?>> substatements = ctx.declaredSubstatements().stream()
*/
private static final Splitter KEY_ARG_SPLITTER = Splitter.on(SEP).omitEmptyStrings();
- private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator.builder(
- YangStmtMapping.KEY)
- .build();
+ private static final SubstatementValidator SUBSTATEMENT_VALIDATOR =
+ SubstatementValidator.builder(YangStmtMapping.KEY).build();
private static final KeyStatementSupport INSTANCE = new KeyStatementSupport();
private KeyStatementSupport() {
- super(YangStmtMapping.KEY, CopyPolicy.DECLARED_COPY);
+ super(YangStmtMapping.KEY, StatementPolicy.copyDeclared(
+ // Identity comparison is sufficient because adaptArgumentValue() is careful about reuse.
+ (copy, current, substatements) -> copy.getArgument() == current.getArgument()));
}
public static KeyStatementSupport getInstance() {
}
}
- // This makes sure we reuse the collection when a grouping is
- // instantiated in the same module
+ // This makes sure we reuse the collection when a grouping is instantiated in the same module.
return replaced ? builder.build() : ctx.argument();
}
import com.google.common.annotations.Beta;
import com.google.common.base.VerifyException;
+import java.util.Collection;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
-import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.concepts.Immutable;
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.StatementDefinition;
-import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
+import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
/**
* Class providing necessary support for processing a YANG statement. This class is intended to be subclassed
*/
public abstract class AbstractStatementSupport<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
implements StatementDefinition, StatementFactory<A, D, E>, StatementSupport<A, D, E> {
+ /**
+ * A baseline class for implementing the {@link StatementFactory#canReuseCurrent(Current, Current, Collection)}
+ * contract in a manner which is consistent with a statement's {@link CopyPolicy}.
+ *
+ * @param <A> Argument type
+ * @param <D> Declared Statement representation
+ */
+ public abstract static class StatementPolicy<A, D extends DeclaredStatement<A>> implements Immutable {
+ final @NonNull CopyPolicy copyPolicy;
+
+ StatementPolicy(final CopyPolicy copyPolicy) {
+ this.copyPolicy = requireNonNull(copyPolicy);
+ }
+
+ /**
+ * Return an {@link StatementPolicy} for {@link CopyPolicy#CONTEXT_INDEPENDENT}.
+ *
+ * @param <A> Argument type
+ * @param <D> Declared Statement representation
+ * @return Context-independent policy
+ */
+ @SuppressWarnings("unchecked")
+ public static final <A, D extends DeclaredStatement<A>> @NonNull StatementPolicy<A, D> contextIndependent() {
+ return (StatementPolicy<A, D>) AlwaysReuse.CONTEXT_INDEPENDENT;
+ }
+
+ /**
+ * Return an {@link StatementPolicy} for {@link CopyPolicy#IGNORE}.
+ *
+ * @param <A> Argument type
+ * @param <D> Declared Statement representation
+ * @return Ignoring policy
+ */
+ @SuppressWarnings("unchecked")
+ public static final <A, D extends DeclaredStatement<A>> @NonNull StatementPolicy<A, D> ignore() {
+ return (StatementPolicy<A, D>) AlwaysFail.IGNORE;
+ }
+
+ /**
+ * Return an {@link StatementPolicy} for {@link CopyPolicy#REJECT}.
+ *
+ * @param <A> Argument type
+ * @param <D> Declared Statement representation
+ * @return Rejecting statement policy
+ */
+ @SuppressWarnings("unchecked")
+ public static final <A, D extends DeclaredStatement<A>> @NonNull StatementPolicy<A, D> reject() {
+ return (StatementPolicy<A, D>) AlwaysFail.REJECT;
+ }
+
+ /**
+ * Return an {@link StatementPolicy} for {@link CopyPolicy#DECLARED_COPY}, deferring to a
+ * {@link StatementEquality} for individual decisions.
+ *
+ * @param <A> Argument type
+ * @param <D> Declared Statement representation
+ * @param equality {@link StatementEquality} to apply to effective statements
+ * @return Rejecting statement policy
+ */
+ public static final <A, D extends DeclaredStatement<A>> @NonNull StatementPolicy<A, D> copyDeclared(
+ final @NonNull StatementEquality<A, D> equality) {
+ return new EqualSemantics<>(equality);
+ }
+
+ abstract boolean canReuseCurrent(@NonNull Current<A, D> copy, @NonNull Current<A, D> current,
+ @NonNull Collection<? extends EffectiveStatement<?, ?>> substatements);
+
+ @Deprecated
+ @SuppressWarnings("unchecked")
+ static <A, D extends DeclaredStatement<A>> StatementPolicy<A, D> compat(final CopyPolicy copyPolicy) {
+ switch (copyPolicy) {
+ case CONTEXT_INDEPENDENT:
+ return contextIndependent();
+ case DECLARED_COPY:
+ return (StatementPolicy<A, D>) AlwaysCopy.DECLARED_COPY;
+ case IGNORE:
+ return ignore();
+ case REJECT:
+ return reject();
+ default:
+ throw new IllegalStateException("Unsupported policy " + copyPolicy);
+ }
+ }
+
+ private static final class AlwaysCopy<A, D extends DeclaredStatement<A>> extends StatementPolicy<A, D> {
+ @Deprecated
+ static final @NonNull AlwaysCopy<?, ?> DECLARED_COPY = new AlwaysCopy<>(CopyPolicy.DECLARED_COPY);
+
+ AlwaysCopy(final CopyPolicy copyPolicy) {
+ super(copyPolicy);
+ }
+
+ @Override
+ boolean canReuseCurrent(final Current<A, D> copy, final Current<A, D> current,
+ final Collection<? extends EffectiveStatement<?, ?>> substatements) {
+ return false;
+ }
+ }
+
+ private static final class AlwaysReuse<A, D extends DeclaredStatement<A>> extends StatementPolicy<A, D> {
+ static final @NonNull AlwaysReuse<?, ?> CONTEXT_INDEPENDENT =
+ new AlwaysReuse<>(CopyPolicy.CONTEXT_INDEPENDENT);
+
+ private AlwaysReuse(final CopyPolicy copyPolicy) {
+ super(copyPolicy);
+ }
+ @Override
+ boolean canReuseCurrent(final Current<A, D> copy, final Current<A, D> current,
+ final Collection<? extends EffectiveStatement<?, ?>> substatements) {
+ return true;
+ }
+ }
+
+ private static final class AlwaysFail<A, D extends DeclaredStatement<A>> extends StatementPolicy<A, D> {
+ static final @NonNull AlwaysFail<?, ?> IGNORE = new AlwaysFail<>(CopyPolicy.IGNORE);
+ static final @NonNull AlwaysFail<?, ?> REJECT = new AlwaysFail<>(CopyPolicy.REJECT);
+
+ private AlwaysFail(final CopyPolicy copyPolicy) {
+ super(copyPolicy);
+ }
+
+ @Override
+ boolean canReuseCurrent(final Current<A, D> copy, final Current<A, D> current,
+ final Collection<? extends EffectiveStatement<?, ?>> substatements) {
+ throw new VerifyException("This implementation should never be invoked");
+ }
+ }
+
+ private static final class EqualSemantics<A, D extends DeclaredStatement<A>> extends StatementPolicy<A, D> {
+ private final @NonNull StatementEquality<A, D> equality;
+
+ EqualSemantics(final @NonNull StatementEquality<A, D> equality) {
+ super(CopyPolicy.DECLARED_COPY);
+ this.equality = requireNonNull(equality);
+ }
+
+ @Override
+ boolean canReuseCurrent(final Current<A, D> copy, final Current<A, D> current,
+ final Collection<? extends EffectiveStatement<?, ?>> substatements) {
+ return equality.canReuseCurrent(copy, current, substatements);
+ }
+ }
+ }
+
+ /**
+ * Abstract base class for comparators associated with statements with a {@link CopyPolicy#DECLARED_COPY} copy
+ * policy.
+ *
+ * @param <A> Argument type
+ * @param <D> Declared Statement representation
+ */
+ @FunctionalInterface
+ public interface StatementEquality<A, D extends DeclaredStatement<A>> {
+ /**
+ * Determine whether {@code current} statement has the same semantics as the provided copy. See the contract
+ * specification of {@link StatementFactory#canReuseCurrent(Current, Current, Collection)}.
+ *
+ * @param copy Copy of current effective context
+ * @param current Current effective context
+ * @param substatements Current effective substatements
+ * @return True if {@code current} can be reused in place of {@code copy}, false if the copy needs to be used.
+ */
+ boolean canReuseCurrent(@NonNull Current<A, D> copy, @NonNull Current<A, D> current,
+ @NonNull Collection<? extends EffectiveStatement<?, ?>> substatements);
+ }
+
+ private final @NonNull StatementPolicy<A, D> policy;
private final @NonNull StatementDefinition type;
private final @NonNull CopyPolicy copyPolicy;
@Beta
- protected AbstractStatementSupport(final StatementDefinition publicDefinition, final CopyPolicy copyPolicy) {
+ protected AbstractStatementSupport(final StatementDefinition publicDefinition, final StatementPolicy<A, D> policy) {
this.type = requireNonNull(publicDefinition);
- this.copyPolicy = requireNonNull(copyPolicy);
+ this.policy = requireNonNull(policy);
+ this.copyPolicy = policy.copyPolicy;
checkArgument(publicDefinition != this);
}
+ @Beta
+ @Deprecated
+ // FIXME: remove this constructor
+ protected AbstractStatementSupport(final StatementDefinition publicDefinition, final CopyPolicy copyPolicy) {
+ this(publicDefinition, StatementPolicy.compat(copyPolicy));
+ }
+
@Override
public final StatementDefinition getPublicView() {
return type;
}
@Override
- public final StmtContext<?, ?, ?> effectiveCopyOf(final StmtContext<?, ?, ?> stmt, final Mutable<?, ?, ?> parent,
- final CopyType copyType, final QNameModule targetModule) {
- switch (copyPolicy) {
- case CONTEXT_INDEPENDENT:
- return stmt;
- case DECLARED_COPY:
- // FIXME: YANGTOOLS-1195: this is too harsh, we need to make a callout to subclass methods so they
- // actually examine the differences.
- return parent.childCopyOf(stmt, copyType, targetModule);
- default:
- throw new VerifyException("Attempted to apply " + copyPolicy);
- }
+ public final boolean canReuseCurrent(final Current<A, D> copy, final Current<A, D> current,
+ final Collection<? extends EffectiveStatement<?, ?>> substatements) {
+ return policy.canReuseCurrent(copy, current, substatements);
}
@Override
import com.google.common.annotations.Beta;
import com.google.common.collect.ForwardingObject;
+import java.util.Collection;
import java.util.stream.Stream;
-import org.opendaylight.yangtools.yang.common.QNameModule;
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.StatementDefinition;
}
@Override
- public StmtContext<?, ?, ?> effectiveCopyOf(final StmtContext<?, ?, ?> stmt, final Mutable<?, ?, ?> parent,
- final CopyType copyType, final QNameModule targetModule) {
- return delegate().effectiveCopyOf(stmt, parent, copyType, targetModule);
+ public boolean canReuseCurrent(final Current<A, D> copy, final Current<A, D> current,
+ final Collection<? extends EffectiveStatement<?, ?>> substatements) {
+ return delegate().canReuseCurrent(copy, current, substatements);
}
}
*/
package org.opendaylight.yangtools.yang.parser.spi.meta;
+import java.util.Collection;
import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
/**
* An entity capable of creating {@link DeclaredStatement} and {@link EffectiveStatement} instances for a particular
@NonNull E createEffective(EffectiveStmtCtx.@NonNull Current<A, D> stmt,
Stream<? extends StmtContext<?, ?, ?>> declaredSubstatements,
Stream<? extends StmtContext<?, ?, ?>> effectiveSubstatements);
+
+ /**
+ * Determine reactor copy behaviour of a statement instance. Implementations classes are required to determine
+ * their operations with regard to their statements being replicated into different contexts -- potentially sharing
+ * instantiations.
+ *
+ * <p>
+ * Implementations are examine {@code copy} as to whether it would result in the same semantics as {@code current}
+ * does, provided that {@code current}'s {@code substatements} are properly propagated.
+ *
+ * @param copy Copy of current effective context
+ * @param current Current effective context
+ * @param substatements Current effective substatements
+ * @return True if the differences between {@code copy} and {@code current} do not affect this statement's effective
+ * semantics.
+ */
+ boolean canReuseCurrent(@NonNull Current<A, D> copy, @NonNull Current<A, D> current,
+ @NonNull Collection<? extends EffectiveStatement<?, ?>> substatements);
}
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.StatementDefinition;
-import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
/**
*/
@NonNull CopyPolicy copyPolicy();
- /**
- * Determine reactor copy behaviour of a statement instance. Statement support classes are required to determine
- * their operations with regard to their statements being replicated into different contexts, so that
- * {@link Mutable} instances are not created when it is evident they are superfluous.
- *
- * <p>
- * The copy operation has three intrinsic parts:
- * <ul>
- * <li>target {@code parent}, i.e. new parent statement for the copy. This determines things like default value
- * of the {@code config} statement and similar</li>
- * <li>copy operation type</li>
- * <li>{@code target module}, which defines the default namespace for the statement copy. This might not be always
- * present, in which case the namespace is retained from the source. As an example, {@code uses} changes
- * the default namespace to parent's namespace, whereas {@code augment} does not.</li>
- * </ul>
- *
- * <p>
- * Implementations should return the context to use -- returning {@code stmt} if there is no change or a copy of it.
- *
- * @param stmt Context of statement to be copied statement
- * @param parent Parent statement context
- * @param copyType Type of copy being performed
- * @param targetModule Target module, if present
- * @return StmtContext holding the effective state
- */
- @NonNull StmtContext<?, ?, ?> effectiveCopyOf(StmtContext<?, ?, ?> stmt, Mutable<?, ?, ?> parent, CopyType copyType,
- @Nullable QNameModule targetModule);
-
/**
* Given a raw string representation of an argument, try to use a shared representation.
*
/**
* Statement context copy policy, indicating how should reactor handle statement copy operations. Every statement
- * copied by the reactor is subject to policy check done by
- * {@link StatementSupport#effectiveCopyOf(StmtContext, Mutable, CopyType, QNameModule)}.
+ * copied by the reactor is subject to this policy.
*/
enum CopyPolicy {
/**