BUG-7052: move copy operation to StatementContextBase 02/61302/7
authorRobert Varga <robert.varga@pantheon.tech>
Tue, 8 Aug 2017 01:39:21 +0000 (03:39 +0200)
committerRobert Varga <nite@hq.sk>
Thu, 24 Aug 2017 10:36:40 +0000 (10:36 +0000)
The copy operation works on top of StatementContextBase concepts
aside from argument adaptation. Move the copy operation around,
cleaning up some of the access patterns along the way.

Change-Id: I34413c7d2c4d314503e9c9adffc7e2f0d2ea2531
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementMap.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SubstatementContext.java

index 712bc83f135ed308fc2e93ffe416d361e278d7cc..2d1c74533334c900cfffc86d8ccf123d4ea83985 100644 (file)
@@ -13,6 +13,7 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableCollection;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Multimap;
 import com.google.common.collect.Multimaps;
 import java.util.ArrayList;
@@ -24,9 +25,11 @@ import java.util.Iterator;
 import java.util.Optional;
 import java.util.Set;
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import org.opendaylight.yangtools.util.OptionalBoolean;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
@@ -645,9 +648,77 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
     @Override
     public <X, Y extends DeclaredStatement<X>, Z extends EffectiveStatement<X, Y>> Mutable<X, Y, Z> childCopyOf(
             final StmtContext<X, Y, Z> stmt, final CopyType type, final QNameModule targetModule) {
+        Preconditions.checkState(stmt.getCompletedPhase() == ModelProcessingPhase.EFFECTIVE_MODEL,
+                "Attempted to copy statement %s which has completed phase %s", stmt, stmt.getCompletedPhase());
+
         Preconditions.checkArgument(stmt instanceof SubstatementContext, "Unsupported statement %s", stmt);
+
         final SubstatementContext<X, Y, Z> original = (SubstatementContext<X, Y, Z>)stmt;
-        return original.createCopy(targetModule, this, type);
+        final SubstatementContext<X, Y, Z> copy = new SubstatementContext<>(original, this, type, targetModule);
+
+        original.definition().onStatementAdded(copy);
+        original.copyTo(copy, type, targetModule);
+
+        return copy;
+    }
+
+    final void copyTo(final StatementContextBase<?, ?, ?> target, final CopyType typeOfCopy,
+            @Nullable final QNameModule targetModule) {
+        final Collection<Mutable<?, ?, ?>> buffer = new ArrayList<>(substatements.size() + effective.size());
+
+        for (final Mutable<?, ?, ?> stmtContext : substatements.values()) {
+            if (stmtContext.isSupportedByFeatures()) {
+                copySubstatement(stmtContext, target, typeOfCopy, targetModule, buffer);
+            }
+        }
+
+        for (final Mutable<?, ?, ?> stmtContext : effective) {
+            copySubstatement(stmtContext, target, typeOfCopy, targetModule, buffer);
+        }
+
+        target.addEffectiveSubstatements(buffer);
+    }
+
+    private void copySubstatement(final Mutable<?, ?, ?> stmtContext,  final Mutable<?, ?, ?> target,
+            final CopyType typeOfCopy, final QNameModule newQNameModule, final Collection<Mutable<?, ?, ?>> buffer) {
+        if (needToCopyByUses(stmtContext)) {
+            final Mutable<?, ?, ?> copy = target.childCopyOf(stmtContext, typeOfCopy, newQNameModule);
+            LOG.debug("Copying substatement {} for {} as", stmtContext, this, copy);
+            buffer.add(copy);
+        } else if (isReusedByUses(stmtContext)) {
+            LOG.debug("Reusing substatement {} for {}", stmtContext, this);
+            buffer.add(stmtContext);
+        } else {
+            LOG.debug("Skipping statement {}", stmtContext);
+        }
+    }
+
+    // FIXME: revise this, as it seems to be wrong
+    private static final Set<YangStmtMapping> NOCOPY_FROM_GROUPING_SET = ImmutableSet.of(
+        YangStmtMapping.DESCRIPTION,
+        YangStmtMapping.REFERENCE,
+        YangStmtMapping.STATUS);
+    private static final Set<YangStmtMapping> REUSED_DEF_SET = ImmutableSet.of(
+        YangStmtMapping.TYPE,
+        YangStmtMapping.TYPEDEF,
+        YangStmtMapping.USES);
+
+    private static boolean needToCopyByUses(final StmtContext<?, ?, ?> stmtContext) {
+        final StatementDefinition def = stmtContext.getPublicDefinition();
+        if (REUSED_DEF_SET.contains(def)) {
+            LOG.debug("Will reuse {} statement {}", def, stmtContext);
+            return false;
+        }
+        if (NOCOPY_FROM_GROUPING_SET.contains(def)) {
+            return !YangStmtMapping.GROUPING.equals(stmtContext.getParentContext().getPublicDefinition());
+        }
+
+        LOG.debug("Will copy {} statement {}", def, stmtContext);
+        return true;
+    }
+
+    private static boolean isReusedByUses(final StmtContext<?, ?, ?> stmtContext) {
+        return REUSED_DEF_SET.contains(stmtContext.getPublicDefinition());
     }
 
     @Override
index 246351e35a12f8b6717c92905e6b53907bed10cc..028f9067de34cd81354abaec1dcff64bd6c483ee 100644 (file)
@@ -40,6 +40,11 @@ abstract class StatementMap {
         Collection<StatementContextBase<?, ?, ?>> values() {
             return ImmutableList.of();
         }
+
+        @Override
+        int size() {
+            return 0;
+        }
     }
 
     private static final class Regular extends StatementMap {
@@ -82,6 +87,23 @@ abstract class StatementMap {
         Collection<StatementContextBase<?, ?, ?>> values() {
             return new RegularAsCollection<>(elements);
         }
+
+        @Override
+        int size() {
+            return countElements(elements);
+       }
+    }
+
+    static int countElements(final Object[] elements) {
+        // Optimized for non-sparse case
+        int nulls = 0;
+        for (Object e : elements) {
+            if (e == null) {
+                nulls++;
+            }
+        }
+
+        return elements.length - nulls;
     }
 
     private static final class RegularAsCollection<T> extends AbstractCollection<T> {
@@ -127,19 +149,10 @@ abstract class StatementMap {
 
         @Override
         public int size() {
-            // Optimized for non-sparse case
-            int nulls = 0;
-            for (T e : elements) {
-                if (e == null) {
-                    nulls++;
-                }
-            }
-
-            return elements.length - nulls;
+            return countElements(elements);
         }
     }
 
-
     private static final class Singleton extends StatementMap {
         private final StatementContextBase<?, ?, ?> object;
 
@@ -162,6 +175,11 @@ abstract class StatementMap {
         Collection<StatementContextBase<?, ?, ?>> values() {
             return ImmutableList.of(object);
         }
+
+        @Override
+        int size() {
+            return 1;
+        }
     }
 
     private static final StatementMap EMPTY = new Empty();
@@ -196,4 +214,6 @@ abstract class StatementMap {
      * @return Read-only view of available statements.
      */
     abstract @Nonnull Collection<StatementContextBase<?, ?, ?>> values();
+
+    abstract int size();
 }
index 002b9bc50cd32cb4e4391646a003b80f6086fe5e..8fa166e0a47bb84dcdbd38b673f74de2795efc5c 100644 (file)
@@ -9,11 +9,8 @@ package org.opendaylight.yangtools.yang.parser.stmt.reactor;
 
 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.util.OptionalBoolean;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -21,10 +18,8 @@ import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.common.YangVersion;
 import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
-import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
 import org.opendaylight.yangtools.yang.model.api.stmt.AugmentStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.ConfigStatement;
@@ -34,7 +29,6 @@ import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
 import org.opendaylight.yangtools.yang.model.api.stmt.UsesStatement;
 import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
-import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
 import org.opendaylight.yangtools.yang.parser.spi.meta.MutableStatement;
 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.NamespaceStorageNode;
 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.Registry;
@@ -45,13 +39,9 @@ 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.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 final class SubstatementContext<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>> extends
         StatementContextBase<A, D, E> {
-    private static final Logger LOG = LoggerFactory.getLogger(SubstatementContext.class);
-
     private final StatementContextBase<?, ?, ?> parent;
     private final A argument;
 
@@ -90,10 +80,11 @@ final class SubstatementContext<A, D extends DeclaredStatement<A>, E extends Eff
     }
 
     SubstatementContext(final StatementContextBase<A, D, E> original, final StatementContextBase<?, ?, ?> parent,
-            final A argument, final CopyType copyType) {
+            final CopyType copyType, final QNameModule targetModule) {
         super(original, copyType);
         this.parent = Preconditions.checkNotNull(parent);
-        this.argument = argument;
+        this.argument = targetModule == null ? original.getStatementArgument()
+                : original.definition().adaptArgumentValue(original, targetModule);
     }
 
     @Override
@@ -127,82 +118,6 @@ final class SubstatementContext<A, D extends DeclaredStatement<A>, E extends Eff
         return argument;
     }
 
-    StatementContextBase<A, D, E> createCopy(final QNameModule newQNameModule,
-            final StatementContextBase<?, ?, ?> newParent, final CopyType typeOfCopy) {
-        Preconditions.checkState(getCompletedPhase() == ModelProcessingPhase.EFFECTIVE_MODEL,
-                "Attempted to copy statement %s which has completed phase %s", this, getCompletedPhase());
-
-        final A argumentCopy = newQNameModule == null ? argument
-                : definition().adaptArgumentValue(this, newQNameModule);
-        final SubstatementContext<A, D, E> copy = new SubstatementContext<>(this, newParent, argumentCopy, typeOfCopy);
-
-        definition().onStatementAdded(copy);
-
-        copy.copyStatements(this, newQNameModule, typeOfCopy);
-        return copy;
-    }
-
-    private void copyStatements(final SubstatementContext<A, D, E> original, final QNameModule newQNameModule,
-            final CopyType typeOfCopy) {
-        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 Mutable<?, ?, ?> stmtContext : declared) {
-            if (stmtContext.isSupportedByFeatures()) {
-                copySubstatement(stmtContext, newQNameModule, typeOfCopy, buffer);
-            }
-        }
-
-        for (final Mutable<?, ?, ?> stmtContext : effective) {
-            copySubstatement(stmtContext, newQNameModule, typeOfCopy, buffer);
-        }
-
-        addEffectiveSubstatements(buffer);
-    }
-
-    private void copySubstatement(final Mutable<?, ?, ?> stmtContext, final QNameModule newQNameModule,
-            final CopyType typeOfCopy, final Collection<Mutable<?, ?, ?>> buffer) {
-        if (needToCopyByUses(stmtContext)) {
-            final Mutable<?, ?, ?> copy = childCopyOf(stmtContext, typeOfCopy, newQNameModule);
-            LOG.debug("Copying substatement {} for {} as", stmtContext, this, copy);
-            buffer.add(copy);
-        } else if (isReusedByUses(stmtContext)) {
-            LOG.debug("Reusing substatement {} for {}", stmtContext, this);
-            buffer.add(stmtContext);
-        } else {
-            LOG.debug("Skipping statement {}", stmtContext);
-        }
-    }
-
-    // FIXME: revise this, as it seems to be wrong
-    private static final Set<YangStmtMapping> NOCOPY_FROM_GROUPING_SET = ImmutableSet.of(
-        YangStmtMapping.DESCRIPTION,
-        YangStmtMapping.REFERENCE,
-        YangStmtMapping.STATUS);
-    private static final Set<YangStmtMapping> REUSED_DEF_SET = ImmutableSet.of(
-        YangStmtMapping.TYPE,
-        YangStmtMapping.TYPEDEF,
-        YangStmtMapping.USES);
-
-    private static boolean needToCopyByUses(final StmtContext<?, ?, ?> stmtContext) {
-        final StatementDefinition def = stmtContext.getPublicDefinition();
-        if (REUSED_DEF_SET.contains(def)) {
-            LOG.debug("Will reuse {} statement {}", def, stmtContext);
-            return false;
-        }
-        if (NOCOPY_FROM_GROUPING_SET.contains(def)) {
-            return !YangStmtMapping.GROUPING.equals(stmtContext.getParentContext().getPublicDefinition());
-        }
-
-        LOG.debug("Will copy {} statement {}", def, stmtContext);
-        return true;
-    }
-
-    private static boolean isReusedByUses(final StmtContext<?, ?, ?> stmtContext) {
-        return REUSED_DEF_SET.contains(stmtContext.getPublicDefinition());
-    }
-
     private boolean isSupportedAsShorthandCase() {
         final Collection<?> supportedCaseShorthands = getFromNamespace(ValidationBundlesNamespace.class,
                 ValidationBundleType.SUPPORTED_CASE_SHORTHANDS);
@@ -263,7 +178,6 @@ final class SubstatementContext<A, D extends DeclaredStatement<A>, E extends Eff
                     schemaPath = local;
                 }
             }
-
         }
 
         return Optional.ofNullable(local);