Extract AbstractResumedStatement
[yangtools.git] / yang / yang-parser-reactor / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / reactor / StatementContextBase.java
index cace674f04c2cd4e8572b172c846811169e86753..a26cd970555db57d08be7ef0e511b92ff832ad20 100644 (file)
@@ -59,7 +59,6 @@ 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.StatementWriter.ResumedStatement;
 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;
@@ -75,7 +74,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>, ResumedStatement {
+        extends NamespaceStorageSupport implements Mutable<A, D, E> {
     /**
      * Event listener when an item is added to model namespace.
      */
@@ -135,17 +134,20 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
     private Multimap<ModelProcessingPhase, ContextMutation> phaseMutation = ImmutableMultimap.of();
     private List<Mutable<?, ?, ?>> effective = ImmutableList.of();
     private List<StmtContext<?, ?, ?>> effectOfStatement = ImmutableList.of();
-    private StatementMap substatements = StatementMap.empty();
 
     private @Nullable ModelProcessingPhase completedPhase;
     private @Nullable D declaredInstance;
     private @Nullable E effectiveInstance;
 
-    // Common state bits
+    // Master flag controlling whether this context can yield an effective statement
+    // FIXME: investigate the mechanics that are being supported by this, as it would be beneficial if we can get rid
+    //        of this flag -- eliminating the initial alignment shadow used by below gap-filler fields.
     private boolean isSupportedToBuildEffective = true;
+
+    // Flag for use with AbstractResumedStatement. This is hiding in the alignment shadow created by above boolean
     private boolean fullyDefined;
 
-    // Flags for use with SubstatementContext. These are hiding in the alignment shadow created by above booleans and
+    // Flags for use with SubstatementContext. These are hiding in the alignment shadow created by above boolean and
     // hence improve memory layout.
     private byte flags;
 
@@ -185,7 +187,6 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
         this.copyHistory = original.getCopyHistory();
         this.originalCtx = original.getOriginalCtx().orElse(original);
         this.prevCopyCtx = original;
-        this.substatements = original.substatements;
         this.effective = original.effective;
     }
 
@@ -307,14 +308,7 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
     }
 
     @Override
-    public Collection<? extends StmtContext<?, ?, ?>> declaredSubstatements() {
-        return substatements.values();
-    }
-
-    @Override
-    public Collection<? extends Mutable<?, ?, ?>> mutableDeclaredSubstatements() {
-        return substatements.values();
-    }
+    public abstract Collection<? extends StatementContextBase<?, ?, ?>> mutableDeclaredSubstatements();
 
     @Override
     public Collection<? extends StmtContext<?, ?, ?>> effectiveSubstatements() {
@@ -402,6 +396,19 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
         shrinkEffective();
     }
 
+    // YANG example: RPC/action statements always have 'input' and 'output' defined
+    @Beta
+    public <X, Y extends DeclaredStatement<X>, Z extends EffectiveStatement<X, Y>> @NonNull Mutable<X, Y, Z>
+            appendImplicitSubstatement(final StatementSupport<X, Y, Z> support, final String rawArg) {
+        // 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);
+        support.onStatementAdded(ret);
+        addEffectiveSubstatement(ret);
+        return ret;
+    }
+
     /**
      * Adds an effective statement to collection of substatements.
      *
@@ -446,74 +453,14 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
         }
     }
 
-    /**
-     * Create a new substatement at the specified offset.
-     *
-     * @param offset Substatement offset
-     * @param def definition context
-     * @param ref source reference
-     * @param argument statement argument
-     * @param <X> new substatement argument type
-     * @param <Y> new substatement declared type
-     * @param <Z> new substatement effective type
-     * @return A new substatement
-     */
-    @SuppressWarnings("checkstyle:methodTypeParameterName")
-    public final <X, Y extends DeclaredStatement<X>, Z extends EffectiveStatement<X, Y>>
-            StatementContextBase<X, Y, Z> createSubstatement(final int offset,
-                    final StatementDefinitionContext<X, Y, Z> def, final StatementSourceReference ref,
-                    final String argument) {
-        final ModelProcessingPhase inProgressPhase = getRoot().getSourceContext().getInProgressPhase();
-        checkState(inProgressPhase != ModelProcessingPhase.EFFECTIVE_MODEL,
-                "Declared statement cannot be added in effective phase at: %s", getStatementSourceReference());
-
-        final Optional<StatementSupport<?, ?, ?>> implicitParent = definition.getImplicitParentFor(def.getPublicView());
-        if (implicitParent.isPresent()) {
-            return createImplicitParent(offset, implicitParent.get(), ref, argument).createSubstatement(offset, def,
-                    ref, argument);
-        }
-
-        final StatementContextBase<X, Y, Z> ret = new SubstatementContext<>(this, def, ref, argument);
-        substatements = substatements.put(offset, ret);
-        def.onStatementAdded(ret);
-        return ret;
-    }
-
-    private StatementContextBase<?, ?, ?> createImplicitParent(final int offset,
-            final StatementSupport<?, ?, ?> implicitParent, final StatementSourceReference ref, final String argument) {
-        final StatementDefinitionContext<?, ?, ?> def = new StatementDefinitionContext<>(implicitParent);
-        return createSubstatement(offset, def, ImplicitSubstatement.of(ref), argument);
-    }
-
-    public void appendImplicitStatement(final StatementSupport<?, ?, ?> statementToAdd) {
-        createSubstatement(substatements.capacity(), new StatementDefinitionContext<>(statementToAdd),
-                ImplicitSubstatement.of(getStatementSourceReference()), null);
-    }
-
-    /**
-     * Lookup substatement by its offset in this statement.
-     *
-     * @param offset Substatement offset
-     * @return Substatement, or null if substatement does not exist.
-     */
-    final StatementContextBase<?, ?, ?> lookupSubstatement(final int offset) {
-        return substatements.get(offset);
+    // Exists only due to memory optimization
+    final boolean fullyDefined() {
+        return fullyDefined;
     }
 
+    // Exists only due to memory optimization, should live in AbstractResumedStatement
     final void setFullyDefined() {
-        this.fullyDefined = true;
-    }
-
-    final void resizeSubstatements(final int expectedSize) {
-        substatements = substatements.ensureCapacity(expectedSize);
-    }
-
-    final void walkChildren(final ModelProcessingPhase phase) {
-        checkState(fullyDefined);
-        substatements.values().forEach(stmt -> {
-            stmt.walkChildren(phase);
-            stmt.endDeclared(phase);
-        });
+        fullyDefined = true;
     }
 
     @Override
@@ -566,7 +513,7 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
             }
         }
 
-        for (final StatementContextBase<?, ?, ?> child : substatements.values()) {
+        for (final StatementContextBase<?, ?, ?> child : mutableDeclaredSubstatements()) {
             finished &= child.tryToCompletePhase(phase);
         }
         for (final Mutable<?, ?, ?> child : effective) {
@@ -796,7 +743,7 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
 
         if (implicitParent.isPresent()) {
             final StatementDefinitionContext<?, ?, ?> def = new StatementDefinitionContext<>(implicitParent.get());
-            result = new SubstatementContext(this, def, original.getSourceReference(),
+            result = new SubstatementContext(this, def, original.getStatementSourceReference(),
                 original.rawStatementArgument(), original.getStatementArgument(), type);
 
             final CopyType childCopyType;
@@ -824,21 +771,6 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
         return result;
     }
 
-    @Override
-    public @NonNull StatementDefinition getDefinition() {
-        return getPublicDefinition();
-    }
-
-    @Override
-    public @NonNull StatementSourceReference getSourceReference() {
-        return getStatementSourceReference();
-    }
-
-    @Override
-    public boolean isFullyDefined() {
-        return fullyDefined;
-    }
-
     @Beta
     public final boolean hasImplicitParentSupport() {
         return definition.getFactory() instanceof ImplicitParentAwareStatementSupport;
@@ -858,11 +790,13 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
             original.getStatementSourceReference(), original.rawStatementArgument(), original.getStatementArgument(),
             type);
 
-        result.addEffectiveSubstatement(new SubstatementContext<>(original, result));
+        result.addEffectiveSubstatement(original.reparent(result));
         result.setCompletedPhase(original.getCompletedPhase());
         return result;
     }
 
+    abstract StatementContextBase<A, D, E> reparent(StatementContextBase<?, ?, ?> newParent);
+
     /**
      * 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
@@ -954,14 +888,14 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
 
     final void copyTo(final StatementContextBase<?, ?, ?> target, final CopyType typeOfCopy,
             @Nullable final QNameModule targetModule) {
-        final Collection<Mutable<?, ?, ?>> buffer = new ArrayList<>(substatements.size() + effective.size());
+        final Collection<? extends StatementContextBase<?, ?, ?>> declared = mutableDeclaredSubstatements();
+        final Collection<Mutable<?, ?, ?>> buffer = new ArrayList<>(declared.size() + effective.size());
 
-        for (final Mutable<?, ?, ?> stmtContext : substatements.values()) {
+        for (final Mutable<?, ?, ?> stmtContext : declared) {
             if (stmtContext.isSupportedByFeatures()) {
                 copySubstatement(stmtContext, target, typeOfCopy, targetModule, buffer);
             }
         }
-
         for (final Mutable<?, ?, ?> stmtContext : effective) {
             copySubstatement(stmtContext, target, typeOfCopy, targetModule, buffer);
         }