BUG-7052: reduce StatementContextBase proliferation even more
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / reactor / SubstatementContext.java
index 7c4f6a19bf6e3222cd32ff311bca963087921047..2710f0802ad025bb3fc26f1f233b8f40487acc7a 100644 (file)
@@ -67,6 +67,8 @@ final class SubstatementContext<A, D extends DeclaredStatement<A>, E extends Eff
      */
     private boolean haveConfiguration;
     private boolean configuration;
+    private boolean wasCheckedIfInYangDataExtensionBody;
+    private boolean isInYangDataExtensionBody;
 
     private volatile SchemaPath schemaPath;
 
@@ -74,7 +76,7 @@ final class SubstatementContext<A, D extends DeclaredStatement<A>, E extends Eff
             final StatementSourceReference ref, final String rawArgument) {
         super(def, ref, rawArgument);
         this.parent = Preconditions.checkNotNull(parent, "Parent must not be null");
-        this.argument = def.parseArgumentValue(this, rawArgument);
+        this.argument = def.parseArgumentValue(this, rawStatementArgument());
     }
 
     @SuppressWarnings("unchecked")
@@ -132,7 +134,7 @@ final class SubstatementContext<A, D extends DeclaredStatement<A>, E extends Eff
     }
 
     @Override
-    public StatementContextBase<?, ?, ?> createCopy(final StatementContextBase<?, ?, ?> newParent,
+    public StatementContextBase<A, D, E> createCopy(final StatementContextBase<?, ?, ?> newParent,
             final CopyType typeOfCopy) {
         return createCopy(null, newParent, typeOfCopy);
     }
@@ -141,7 +143,7 @@ final class SubstatementContext<A, D extends DeclaredStatement<A>, E extends Eff
     public StatementContextBase<A, D, E> createCopy(final QNameModule newQNameModule,
             final StatementContextBase<?, ?, ?> newParent, final CopyType typeOfCopy) {
         Preconditions.checkState(getCompletedPhase() == ModelProcessingPhase.EFFECTIVE_MODEL,
-                "Attempted to copy statement {} which has completed phase {}", this, getCompletedPhase());
+                "Attempted to copy statement %s which has completed phase %s", this, getCompletedPhase());
 
         final SubstatementContext<A, D, E> copy = new SubstatementContext<>(this, newQNameModule, newParent, typeOfCopy);
 
@@ -161,28 +163,27 @@ final class SubstatementContext<A, D extends DeclaredStatement<A>, E extends Eff
 
     private void copyStatements(final SubstatementContext<A, D, E> original, final QNameModule newQNameModule,
             final CopyType typeOfCopy) {
-        final Collection<StatementContextBase<?, ?, ?>> declared = original.declaredSubstatements();
-        final Collection<StatementContextBase<?, ?, ?>> effective = original.effectiveSubstatements();
-        final Collection<StatementContextBase<?, ?, ?>> buffer = new ArrayList<>(declared.size() + effective.size());
+        final Collection<? extends Mutable<?, ?, ?>> declared = original.mutableDeclaredSubstatements();
+        final Collection<? extends Mutable<?, ?, ?>> effective = original.mutableEffectiveSubstatements();
+        final Collection<Mutable<?, ?, ?>> buffer = new ArrayList<>(declared.size() + effective.size());
 
-        for (final StatementContextBase<?, ?, ?> stmtContext : declared) {
-            if (StmtContextUtils.areFeaturesSupported(stmtContext)) {
+        for (final Mutable<?, ?, ?> stmtContext : declared) {
+            if (stmtContext.isSupportedByFeatures()) {
                 copySubstatement(stmtContext, newQNameModule, typeOfCopy, buffer);
             }
         }
 
-        for (final StatementContextBase<?, ?, ?> stmtContext : effective) {
+        for (final Mutable<?, ?, ?> stmtContext : effective) {
             copySubstatement(stmtContext, newQNameModule, typeOfCopy, buffer);
         }
 
         addEffectiveSubstatements(buffer);
     }
 
-    private void copySubstatement(final StatementContextBase<?, ?, ?> stmtContext,
-            final QNameModule newQNameModule, final CopyType typeOfCopy,
-            final Collection<StatementContextBase<?, ?, ?>> buffer) {
+    private void copySubstatement(final Mutable<?, ?, ?> stmtContext, final QNameModule newQNameModule,
+            final CopyType typeOfCopy, final Collection<Mutable<?, ?, ?>> buffer) {
         if (needToCopyByUses(stmtContext)) {
-            final StatementContextBase<?, ?, ?> copy = stmtContext.createCopy(newQNameModule, this, typeOfCopy);
+            final Mutable<?, ?, ?> copy = stmtContext.createCopy(newQNameModule, this, typeOfCopy);
             LOG.debug("Copying substatement {} for {} as", stmtContext, this, copy);
             buffer.add(copy);
         } else if (isReusedByUses(stmtContext)) {
@@ -232,6 +233,9 @@ final class SubstatementContext<A, D extends DeclaredStatement<A>, E extends Eff
         Verify.verify(maybeParentPath.isPresent(), "Parent %s does not have a SchemaPath", parent);
         final SchemaPath parentPath = maybeParentPath.get();
 
+        if (Utils.isUnknownNode(this)) {
+            return parentPath.createChild(getPublicDefinition().getStatementName());
+        }
         if (argument instanceof QName) {
             final QName qname = (QName) argument;
             if (StmtContextUtils.producesDeclared(this, UsesStatement.class)) {
@@ -250,8 +254,8 @@ final class SubstatementContext<A, D extends DeclaredStatement<A>, E extends Eff
         }
         if (argument instanceof String) {
             // FIXME: This may yield illegal argument exceptions
-            final StatementContextBase<?, ?, ?> originalCtx = getOriginalCtx();
-            final QName qname = (originalCtx != null) ? Utils.qNameFromArgument(originalCtx, (String) argument) : Utils
+            final StmtContext<?, ?, ?> originalCtx = getOriginalCtx();
+            final QName qname = originalCtx != null ? Utils.qNameFromArgument(originalCtx, (String) argument) : Utils
                     .qNameFromArgument(this, (String) argument);
             return parentPath.createChild(qname);
         }
@@ -262,9 +266,6 @@ final class SubstatementContext<A, D extends DeclaredStatement<A>, E extends Eff
 
             return parentPath.createChild(((SchemaNodeIdentifier) argument).getPathFromRoot());
         }
-        if (Utils.isUnknownNode(this)) {
-            return parentPath.createChild(getPublicDefinition().getStatementName());
-        }
 
         // FIXME: this does not look right
         return maybeParentPath.orNull();
@@ -295,6 +296,13 @@ final class SubstatementContext<A, D extends DeclaredStatement<A>, E extends Eff
 
     @Override
     public boolean isConfiguration() {
+        // if this statement is within a 'yang-data' extension body, config substatements are ignored as if
+        // they were not declared. As 'yang-data' is always a top-level node, all configs that are within it are
+        // automatically true
+        if (isInYangDataExtensionBody()) {
+            return true;
+        }
+
         if (haveConfiguration) {
             return configuration;
         }
@@ -321,6 +329,23 @@ final class SubstatementContext<A, D extends DeclaredStatement<A>, E extends Eff
         return isConfig;
     }
 
+    @Override
+    public boolean isInYangDataExtensionBody() {
+        if (wasCheckedIfInYangDataExtensionBody) {
+            return isInYangDataExtensionBody;
+        }
+
+        final boolean parentIsInYangDataExtensionBody = parent.isInYangDataExtensionBody();
+        if (parentIsInYangDataExtensionBody) {
+            isInYangDataExtensionBody = parentIsInYangDataExtensionBody;
+        } else {
+            isInYangDataExtensionBody = StmtContextUtils.hasYangDataExtensionParent(this);
+        }
+
+        wasCheckedIfInYangDataExtensionBody = true;
+        return isInYangDataExtensionBody;
+    }
+
     @Override
     public boolean isEnabledSemanticVersioning() {
         return parent.isEnabledSemanticVersioning();