Refactor ContainerEffectiveStatementImpl 87/86887/1
authorRobert Varga <robert.varga@pantheon.tech>
Mon, 13 Jan 2020 12:42:04 +0000 (13:42 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Tue, 14 Jan 2020 15:30:42 +0000 (16:30 +0100)
The story here is very similar to ListEffectiveStatementImpl,
with the additional simplifications that containers are pretty
much same.

Size reduction from this refactor ends up being typical 104 bytes
to 40 bytes typical, eliminating a bunch of static collections
in the process.

JIRA: YANGTOOLS-1065
Change-Id: I1050c4e8f82f60274c78e810fc31896daccba389
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
(cherry picked from commit bbdfd546e8f79773f2162717f607551bb79fcbda)

yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/EffectiveStatementMixins.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/container/AbstractContainerStatementSupport.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/container/ContainerEffectiveStatementImpl.java

index 1584c90d12d7ac45f6cf5506d06e05857c0ed71b..b87da7e799ae67bccb3f28e124ae3160bbb26dc3 100644 (file)
@@ -263,6 +263,18 @@ public final class EffectiveStatementMixins {
         }
     }
 
+    /**
+     * Bridge between {@link EffectiveStatementWithFlags} and {@code presence} statement.
+     *
+     * @param <A> Argument type ({@link Void} if statement does not have argument.)
+     * @param <D> Class representing declared version of this statement.
+     */
+    public interface PresenceMixin<A, D extends DeclaredStatement<A>> extends EffectiveStatementWithFlags<A, D> {
+        default boolean presence() {
+            return (flags() & FlagsBuilder.PRESENCE) != 0;
+        }
+    }
+
     /**
      * Bridge between {@link EffectiveStatementWithFlags} and {@link SchemaNode}.
      *
@@ -320,7 +332,7 @@ public final class EffectiveStatementMixins {
 
         @NonNullByDefault
         final class FlagsBuilder implements Mutable {
-            // We still have 25 flags remaining
+            // We still have 24 flags remaining
             static final int STATUS_CURRENT       = 0x0001;
             static final int STATUS_DEPRECATED    = 0x0002;
             static final int STATUS_OBSOLETE      = 0x0003;
@@ -334,6 +346,7 @@ public final class EffectiveStatementMixins {
             private static final int MASK_HISTORY = 0x0030;
 
             static final int USER_ORDERED         = 0x0040;
+            static final int PRESENCE             = 0x0080;
 
             private int flags;
 
@@ -373,6 +386,15 @@ public final class EffectiveStatementMixins {
                 return this;
             }
 
+            public FlagsBuilder setPresence(final boolean presence) {
+                if (presence) {
+                    flags |= PRESENCE;
+                } else {
+                    flags &= ~PRESENCE;
+                }
+                return this;
+            }
+
             public FlagsBuilder setStatus(final Status status) {
                 final int bits;
                 switch (status) {
index 809158dcc7bb4ff8d57fcba9911c8c7878406c6d..b3081c994d9eb27b40922117237a16afad3fc83c 100644 (file)
@@ -7,19 +7,27 @@
  */
 package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.container;
 
+import com.google.common.collect.ImmutableList;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.Status;
 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ContainerEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.ContainerStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.PresenceEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.StatusEffectiveStatement;
 import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.ChildSchemaNodeNamespace;
-import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractQNameStatementSupport;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.BaseQNameStatementSupport;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStatementMixins.EffectiveStatementWithFlags.FlagsBuilder;
 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.StatementSourceReference;
 
 abstract class AbstractContainerStatementSupport
-        extends AbstractQNameStatementSupport<ContainerStatement, EffectiveStatement<QName, ContainerStatement>> {
-
+        extends BaseQNameStatementSupport<ContainerStatement, ContainerEffectiveStatement> {
     AbstractContainerStatementSupport() {
         super(YangStmtMapping.CONTAINER);
     }
@@ -30,8 +38,7 @@ abstract class AbstractContainerStatementSupport
     }
 
     @Override
-    public final void onStatementAdded(
-            final Mutable<QName, ContainerStatement, EffectiveStatement<QName, ContainerStatement>> stmt) {
+    public final void onStatementAdded(final Mutable<QName, ContainerStatement, ContainerEffectiveStatement> stmt) {
         stmt.coerceParentContext().addToNs(ChildSchemaNodeNamespace.class, stmt.coerceStatementArgument(), stmt);
     }
 
@@ -41,8 +48,27 @@ abstract class AbstractContainerStatementSupport
     }
 
     @Override
-    public final EffectiveStatement<QName,ContainerStatement> createEffective(
-            final StmtContext<QName, ContainerStatement, EffectiveStatement<QName,ContainerStatement>> ctx) {
-        return new ContainerEffectiveStatementImpl(ctx);
+    protected final ContainerEffectiveStatement createEffective(
+            final StmtContext<QName, ContainerStatement, ContainerEffectiveStatement> ctx,
+            final ContainerStatement declared, final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
+
+        final StatementSourceReference ref = ctx.getStatementSourceReference();
+        final SchemaPath path = ctx.getSchemaPath().get();
+        final ContainerSchemaNode original = (ContainerSchemaNode) ctx.getOriginalCtx().map(StmtContext::buildEffective)
+                .orElse(null);
+        final int flags = new FlagsBuilder()
+                .setHistory(ctx.getCopyHistory())
+                .setStatus(findFirstArgument(substatements, StatusEffectiveStatement.class, Status.CURRENT))
+                .setConfiguration(ctx.isConfiguration())
+                .setPresence(findFirstStatement(substatements, PresenceEffectiveStatement.class) != null)
+                .toFlags();
+        return new ContainerEffectiveStatementImpl(declared, path, flags, ctx, substatements, original);
+    }
+
+    @Override
+    protected final ContainerEffectiveStatement createEmptyEffective(
+            final StmtContext<QName, ContainerStatement, ContainerEffectiveStatement> ctx,
+            final ContainerStatement declared) {
+        return createEffective(ctx, declared, ImmutableList.of());
     }
-}
\ No newline at end of file
+}
index 7881a9de7668ace8abaf5c3ed9ea58afe4c7cfcc..2033def96cac20708339abef5b44cfb6fcaf97ef 100644 (file)
@@ -7,23 +7,33 @@
  */
 package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.container;
 
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSet.Builder;
+import static com.google.common.base.Verify.verify;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.ImmutableList;
 import java.util.Objects;
 import java.util.Optional;
-import java.util.Set;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.ContainerEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.ContainerStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.PresenceEffectiveStatement;
-import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.AbstractEffectiveContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.stmt.compat.ActionNodeContainerCompat;
+import org.opendaylight.yangtools.yang.model.api.stmt.compat.NotificationNodeContainerCompat;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.AbstractDeclaredEffectiveStatement.DefaultWithDataTree;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStatementMixins.ActionNodeContainerMixin;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStatementMixins.AugmentationTargetMixin;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStatementMixins.DataNodeContainerMixin;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStatementMixins.DataSchemaNodeMixin;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStatementMixins.MustConstraintMixin;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStatementMixins.NotificationNodeContainerMixin;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStatementMixins.PresenceMixin;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStmtUtils;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 
 /**
@@ -33,52 +43,75 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
  */
 // FIXME: 4.0.0: hide this class
 @Deprecated
-public final class ContainerEffectiveStatementImpl extends AbstractEffectiveContainerSchemaNode<ContainerStatement>
-        implements ContainerEffectiveStatement, DerivableSchemaNode {
-    private final @NonNull ImmutableSet<ActionDefinition> actions;
-    private final @NonNull ImmutableSet<NotificationDefinition> notifications;
+public final class ContainerEffectiveStatementImpl
+        extends DefaultWithDataTree<QName, ContainerStatement, ContainerEffectiveStatement>
+        implements ContainerEffectiveStatement, ContainerSchemaNode, DerivableSchemaNode,
+            DataSchemaNodeMixin<QName, ContainerStatement>, DataNodeContainerMixin<QName, ContainerStatement>,
+            ActionNodeContainerMixin<QName, ContainerStatement>,
+            ActionNodeContainerCompat<QName, ContainerStatement>,
+            NotificationNodeContainerMixin<QName, ContainerStatement>,
+            NotificationNodeContainerCompat<QName, ContainerStatement>,
+            MustConstraintMixin<QName, ContainerStatement>, PresenceMixin<QName, ContainerStatement>,
+            AugmentationTargetMixin<QName, ContainerStatement> {
+
+    private final int flags;
+    private final @NonNull Object substatements;
+    private final @NonNull SchemaPath path;
     private final @Nullable ContainerSchemaNode original;
-    private final boolean presence;
-
-    ContainerEffectiveStatementImpl(
-            final StmtContext<QName, ContainerStatement, EffectiveStatement<QName, ContainerStatement>> ctx) {
-        super(ctx);
-        this.original = (ContainerSchemaNode) ctx.getOriginalCtx().map(StmtContext::buildEffective).orElse(null);
-        final ImmutableSet.Builder<ActionDefinition> actionsBuilder = ImmutableSet.builder();
-        final Builder<NotificationDefinition> notificationsBuilder = ImmutableSet.builder();
-        for (final EffectiveStatement<?, ?> effectiveStatement : effectiveSubstatements()) {
-            if (effectiveStatement instanceof ActionDefinition) {
-                actionsBuilder.add((ActionDefinition) effectiveStatement);
-            }
-
-            if (effectiveStatement instanceof NotificationDefinition) {
-                notificationsBuilder.add((NotificationDefinition) effectiveStatement);
-            }
+
+    ContainerEffectiveStatementImpl(final ContainerStatement declared, final SchemaPath path, final int flags,
+                final StmtContext<?, ?, ?> ctx, final ImmutableList<? extends EffectiveStatement<?, ?>> substatements,
+                final ContainerSchemaNode original) {
+        super(declared, ctx, substatements);
+
+        EffectiveStmtUtils.checkUniqueGroupings(ctx, substatements);
+        EffectiveStmtUtils.checkUniqueTypedefs(ctx, substatements);
+        EffectiveStmtUtils.checkUniqueUses(ctx, substatements);
+
+        this.substatements = substatements.size() == 1 ? substatements.get(0) : substatements;
+        this.path = requireNonNull(path);
+        this.original = original;
+        this.flags = flags;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public ImmutableList<? extends EffectiveStatement<?, ?>> effectiveSubstatements() {
+        if (substatements instanceof ImmutableList) {
+            return (ImmutableList<? extends EffectiveStatement<?, ?>>) substatements;
         }
+        verify(substatements instanceof EffectiveStatement, "Unexpected substatement %s", substatements);
+        return ImmutableList.of((EffectiveStatement<?, ?>) substatements);
+    }
 
-        this.actions = actionsBuilder.build();
-        this.notifications = notificationsBuilder.build();
-        presence = findFirstEffectiveSubstatement(PresenceEffectiveStatement.class).isPresent();
+    @Override
+    public int flags() {
+        return flags;
     }
 
     @Override
-    public Optional<ContainerSchemaNode> getOriginal() {
-        return Optional.ofNullable(original);
+    public QName argument() {
+        return getQName();
     }
 
     @Override
-    public Set<ActionDefinition> getActions() {
-        return actions;
+    public SchemaPath getPath() {
+        return path;
     }
 
     @Override
-    public Set<NotificationDefinition> getNotifications() {
-        return notifications;
+    public Optional<ContainerSchemaNode> getOriginal() {
+        return Optional.ofNullable(original);
     }
 
     @Override
     public boolean isPresenceContainer() {
-        return presence;
+        return presence();
+    }
+
+    @Override
+    public Optional<DataSchemaNode> findDataChildByName(final QName name) {
+        return findDataSchemaNode(name);
     }
 
     @Override