Remove ReactorStmtCtx.parentStmtCtx()
[yangtools.git] / yang / yang-parser-reactor / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / reactor / StatementContextBase.java
index 070d89095762da166f8d9905ffa77e872cf11cb6..50198334ce4187d87d7a2c393b90283f5ea86b2d 100644 (file)
@@ -65,7 +65,6 @@ 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;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
-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;
@@ -84,7 +83,7 @@ import org.slf4j.LoggerFactory;
  * @param <E> Effective Statement representation
  */
 public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
-        extends NamespaceStorageSupport implements Mutable<A, D, E> {
+        extends ReactorStmtCtx<A, D, E> {
     /**
      * Event listener when an item is added to model namespace.
      */
@@ -265,9 +264,6 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
         this.completedPhase = completedPhase;
     }
 
-    @Override
-    public abstract StatementContextBase<?, ?, ?> getParentContext();
-
     /**
      * Returns the model root for this statement.
      *
@@ -383,7 +379,7 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
         final Iterator<? extends StmtContext<?, ?, ?>> iterator = effective.iterator();
         while (iterator.hasNext()) {
             final StmtContext<?, ?, ?> next = iterator.next();
-            if (statementDef.equals(next.getPublicDefinition())) {
+            if (statementDef.equals(next.publicDefinition())) {
                 iterator.remove();
             }
         }
@@ -420,7 +416,7 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
         final Iterator<StatementContextBase<?, ?, ?>> 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();
             }
         }
@@ -435,7 +431,7 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
         // FIXME: YANGTOOLS-652: This does not need to be a SubstatementContext, in can be a specialized
         //                       StatementContextBase subclass.
         final Mutable<X, Y, Z> ret = new SubstatementContext<>(this, new StatementDefinitionContext<>(support),
-                ImplicitSubstatement.of(getStatementSourceReference()), rawArg);
+                ImplicitSubstatement.of(sourceReference()), rawArg);
         support.onStatementAdded(ret);
         addEffectiveSubstatement(ret);
         return ret;
@@ -526,7 +522,7 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
             final List<StatementContextBase<?, ?, ?>> effective, final int toAdd) {
         // We cannot allow statement to be further mutated
         verify(completedPhase != ModelProcessingPhase.EFFECTIVE_MODEL, "Cannot modify finished statement at %s",
-            getStatementSourceReference());
+            sourceReference());
         return beforeAddEffectiveStatementUnsafe(effective, toAdd);
     }
 
@@ -535,7 +531,7 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
         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", getStatementSourceReference());
+                "Effective statement cannot be added in declared phase at: %s", sourceReference());
 
         return effective.isEmpty() ? new ArrayList<>(toAdd) : effective;
     }
@@ -556,8 +552,23 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
     }
 
     private E loadEffective() {
-        return effectiveInstance = definition.getFactory().createEffective(new BaseCurrentEffectiveStmtCtx<>(this),
-            streamDeclared(), streamEffective());
+        // Creating an effective statement does not strictly require a declared instance -- there are statements like
+        // 'input', which are implicitly defined.
+        // Our implementation design makes an invariant assumption that buildDeclared() has been called by the time
+        // we attempt to create effective statement:
+        buildDeclared();
+
+        final E ret = effectiveInstance = createEffective();
+        // we have called createEffective(), substatements are no longer guarded by us. Let's see if we can clear up
+        // some residue.
+        releaseImplicitRef();
+        return ret;
+    }
+
+    // Exposed for ReplicaStatementContext
+    E createEffective() {
+        return definition.getFactory().createEffective(new BaseCurrentEffectiveStmtCtx<>(this), streamDeclared(),
+            streamEffective());
     }
 
     abstract Stream<? extends StmtContext<?, ?, ?>> streamDeclared();
@@ -781,8 +792,8 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, 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) {
@@ -808,7 +819,7 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
         ModelProcessingPhase finishedPhase = completedPhase;
         while (finishedPhase != null) {
             checkState(!phase.equals(finishedPhase), "Mutation registered after phase was completed at: %s",
-                getStatementSourceReference());
+                sourceReference());
             finishedPhase = finishedPhase.getPreviousPhase();
         }
 
@@ -842,7 +853,7 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
             case CONTEXT_INDEPENDENT:
                 if (hasEmptySubstatements()) {
                     // This statement is context-independent and has no substatements -- hence it can be freely shared.
-                    return Optional.of(this);
+                    return Optional.of(replicaAsChildOf(parent));
                 }
                 // FIXME: YANGTOOLS-694: filter out all context-independent substatements, eliminate fall-through
                 // fall through
@@ -874,15 +885,15 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
     private <X, Y extends DeclaredStatement<X>, Z extends EffectiveStatement<X, Y>> Mutable<X, Y, Z> childCopyOf(
             final StatementContextBase<X, Y, Z> original, final CopyType type, final QNameModule targetModule) {
         final Optional<StatementSupport<?, ?, ?>> implicitParent = definition.getImplicitParentFor(
-            original.getPublicDefinition());
+            original.publicDefinition());
 
         final StatementContextBase<X, Y, Z> result;
         final InferredStatementContext<X, Y, Z> 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) {
@@ -908,6 +919,16 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
         return result;
     }
 
+    @Override
+    public final StatementContextBase<A, D, E> replicaAsChildOf(final Mutable<?, ?, ?> parent) {
+        checkArgument(parent instanceof StatementContextBase, "Unsupported parent %s", parent);
+        return replicaAsChildOf((StatementContextBase<?, ?, ?>) parent);
+    }
+
+    final @NonNull StatementContextBase<A, D, E> replicaAsChildOf(final StatementContextBase<?, ?, ?> stmt) {
+        return new ReplicaStatementContext<>(stmt, this);
+    }
+
     private static void checkEffectiveModelCompleted(final StmtContext<?, ?, ?> stmt) {
         final ModelProcessingPhase phase = stmt.getCompletedPhase();
         checkState(phase == ModelProcessingPhase.EFFECTIVE_MODEL,
@@ -922,7 +943,7 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
     @Beta
     public final StatementContextBase<?, ?, ?> wrapWithImplicit(final StatementContextBase<?, ?, ?> original) {
         final Optional<StatementSupport<?, ?, ?>> optImplicit = definition.getImplicitParentFor(
-            original.getPublicDefinition());
+            original.publicDefinition());
         if (optImplicit.isEmpty()) {
             return original;
         }
@@ -930,8 +951,7 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, 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());
@@ -947,6 +967,11 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
      */
     abstract boolean hasEmptySubstatements();
 
+    @Override
+    final boolean noImplictRef() {
+        return effectiveInstance != null || !isSupportedToBuildEffective();
+    }
+
     /**
      * 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
@@ -976,7 +1001,7 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
             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 {
@@ -1060,9 +1085,9 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
         final SchemaPath parentPath = maybeParentPath.get();
 
         if (StmtContextUtils.isUnknownStatement(this)) {
-            return parentPath.createChild(getPublicDefinition().getStatementName());
+            return parentPath.createChild(publicDefinition().getStatementName());
         }
-        final Object argument = getStatementArgument();
+        final Object argument = argument();
         if (argument instanceof QName) {
             final QName qname = (QName) argument;
             if (producesDeclared(UsesStatement.class)) {
@@ -1094,6 +1119,6 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
     }
 
     protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
-        return toStringHelper.add("definition", definition).add("rawArgument", rawStatementArgument());
+        return toStringHelper.add("definition", definition).add("rawArgument", rawArgument());
     }
 }