Make getOriginalCtx() give out an Optional
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / reactor / SubstatementContext.java
index 7c4f6a19bf6e3222cd32ff311bca963087921047..9b35dcaca2f8913e22addc3a51f97a996e7a2afc 100644 (file)
@@ -7,12 +7,12 @@
  */
 package org.opendaylight.yangtools.yang.parser.stmt.reactor;
 
-import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Verify;
 import com.google.common.collect.ImmutableSet;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Optional;
 import java.util.Set;
 import javax.annotation.Nonnull;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -46,7 +46,6 @@ import org.opendaylight.yangtools.yang.parser.spi.source.AugmentToChoiceNamespac
 import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
 import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace.ValidationBundleType;
-import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.Utils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -67,6 +66,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,14 +75,14 @@ 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")
-    SubstatementContext(final SubstatementContext<A, D, E> original, final QNameModule newQNameModule,
-            final StatementContextBase<?, ?, ?> newParent, final CopyType typeOfCopy) {
-        super(original);
-        this.parent = newParent;
+    private SubstatementContext(final SubstatementContext<A, D, E> original, final QNameModule newQNameModule,
+            final StatementContextBase<?, ?, ?> newParent, final CopyType copyType) {
+        super(original, copyType);
+        this.parent = Preconditions.checkNotNull(newParent);
 
         if (newQNameModule != null) {
             final A originalArg = original.argument;
@@ -132,7 +133,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,18 +142,10 @@ 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);
 
-        copy.appendCopyHistory(typeOfCopy, this.getCopyHistory());
-
-        if (this.getOriginalCtx() != null) {
-            copy.setOriginalCtx(this.getOriginalCtx());
-        } else {
-            copy.setOriginalCtx(this);
-        }
-
         definition().onStatementAdded(copy);
 
         copy.copyStatements(this, newQNameModule, typeOfCopy);
@@ -161,28 +154,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,10 +224,13 @@ 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 (StmtContextUtils.isUnknownNode(this)) {
+            return parentPath.createChild(getPublicDefinition().getStatementName());
+        }
         if (argument instanceof QName) {
             final QName qname = (QName) argument;
             if (StmtContextUtils.producesDeclared(this, UsesStatement.class)) {
-                return maybeParentPath.orNull();
+                return maybeParentPath.orElse(null);
             }
 
             final SchemaPath path;
@@ -250,24 +245,20 @@ 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
-                    .qNameFromArgument(this, (String) argument);
+            final Optional<StmtContext<?, ?, ?>> originalCtx = getOriginalCtx();
+            final QName qname = StmtContextUtils.qnameFromArgument(originalCtx.orElse(this), (String) argument);
             return parentPath.createChild(qname);
         }
         if (argument instanceof SchemaNodeIdentifier
-                && (StmtContextUtils.producesDeclared(this, AugmentStatement.class) || StmtContextUtils
-                        .producesDeclared(this, RefineStatement.class) || StmtContextUtils
-                .producesDeclared(this, DeviationStatement.class))) {
+                && (StmtContextUtils.producesDeclared(this, AugmentStatement.class)
+                        || StmtContextUtils.producesDeclared(this, RefineStatement.class)
+                        || StmtContextUtils.producesDeclared(this, DeviationStatement.class))) {
 
             return parentPath.createChild(((SchemaNodeIdentifier) argument).getPathFromRoot());
         }
-        if (Utils.isUnknownNode(this)) {
-            return parentPath.createChild(getPublicDefinition().getStatementName());
-        }
 
         // FIXME: this does not look right
-        return maybeParentPath.orNull();
+        return maybeParentPath.orElse(null);
     }
 
     @Nonnull
@@ -285,16 +276,18 @@ final class SubstatementContext<A, D extends DeclaredStatement<A>, E extends Eff
 
         }
 
-        return Optional.fromNullable(local);
-    }
-
-    @Override
-    public boolean isRootContext() {
-        return false;
+        return Optional.ofNullable(local);
     }
 
     @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 +314,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();