, E
}
}
+ private void summarizeSubstatementPolicy() {
+ if (definition().support().copyPolicy() == CopyPolicy.EXACT_REPLICA || noSensitiveSubstatements()) {
+ setAllSubstatementsContextIndependent();
+ }
+ }
+
+ /**
+ * Determine whether any substatements are copy-sensitive as determined by {@link StatementSupport#copyPolicy()}.
+ * Only {@link CopyPolicy#CONTEXT_INDEPENDENT}, {@link CopyPolicy#EXACT_REPLICA} and {@link CopyPolicy#IGNORE} are
+ * copy-insensitive. Note that statements which are not {@link StmtContext#isSupportedToBuildEffective()} are all
+ * considered copy-insensitive.
+ *
+ *
+ * Implementations are expected to call {@link #noSensitiveSubstatements()} to actually traverse substatement sets.
+ *
+ * @return True if no substatements require copy-sensitive handling
+ */
+ abstract boolean noSensitiveSubstatements();
+
+ /**
+ * Determine whether any of the provided substatements are context-sensitive for purposes of implementing
+ * {@link #noSensitiveSubstatements()}.
+ *
+ * @param substatements Substatements to check
+ * @return True if no substatements require context-sensitive handling
+ */
+ static boolean noSensitiveSubstatements(final Collection extends ReactorStmtCtx, ?, ?>> substatements) {
+ for (ReactorStmtCtx, ?, ?> stmt : substatements) {
+ if (stmt.isSupportedToBuildEffective()) {
+ if (!stmt.allSubstatementsContextIndependent()) {
+ // This is a recursive property
+ return false;
+ }
+
+ switch (stmt.definition().support().copyPolicy()) {
+ case CONTEXT_INDEPENDENT:
+ case EXACT_REPLICA:
+ case IGNORE:
+ break;
+ default:
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
private void runPhaseListeners(final ModelProcessingPhase phase, final Collection listeners) {
final Iterator listener = listeners.iterator();
while (listener.hasNext()) {
@@ -541,8 +606,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", sourceReference());
- checkNotNull(listener, "Statement context phase listener cannot be null at: %s", sourceReference());
+ requireNonNull(phase, "Statement context processing phase cannot be null");
+ requireNonNull(listener, "Statement context phase listener cannot be null");
ModelProcessingPhase finishedPhase = completedPhase;
while (finishedPhase != null) {
@@ -595,20 +660,27 @@ public abstract class StatementContextBase, E
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 copyAsChildOfImpl(final Mutable, ?, ?> parent, final CopyType type,
+ final QNameModule targetModule) {
final StatementSupport support = definition.support();
final CopyPolicy policy = support.copyPolicy();
switch (policy) {
+ case EXACT_REPLICA:
+ return replicaAsChildOf(parent);
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) 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:
@@ -616,35 +688,24 @@ public abstract class StatementContextBase, E
}
}
- 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();
- }
-
- // 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);
-
- final StatementSupport support = definition.support();
- final StmtContext, ?, ?> effective = support.effectiveCopyOf(this, parent, type, targetModule);
- if (effective == this) {
- LOG.debug("Should reuse {}", this);
- return;
+ @Override
+ final ReactorStmtCtx, ?, ?> asEffectiveChildOf(final StatementContextBase, ?, ?> parent, final CopyType type,
+ final QNameModule targetModule) {
+ final ReactorStmtCtx copy = copyAsChildOfImpl(parent, type, targetModule);
+ if (copy == null) {
+ // The statement fizzled, this should never happen, perhaps a verify()?
+ return null;
}
- // 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 and pass that as substatements.
+ parent.ensureCompletedPhase(copy);
+ return canReuseCurrent(copy) ? this : copy;
+ }
+
+ private boolean canReuseCurrent(final ReactorStmtCtx 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();
}
@Override
@@ -693,13 +754,8 @@ public abstract class StatementContextBase, E
}
@Override
- public final ReactorStmtCtx replicaAsChildOf(final Mutable, ?, ?> parent) {
- checkArgument(parent instanceof StatementContextBase, "Unsupported parent %s", parent);
- return replicaAsChildOf((StatementContextBase, ?, ?>) parent);
- }
-
- final @NonNull ReplicaStatementContext replicaAsChildOf(final StatementContextBase, ?, ?> stmt) {
- return new ReplicaStatementContext<>(stmt, this);
+ final ReplicaStatementContext replicaAsChildOf(final StatementContextBase, ?, ?> parent) {
+ return new ReplicaStatementContext<>(parent, this);
}
private static void checkEffectiveModelCompleted(final StmtContext, ?, ?> stmt) {