Refactor ContainerEffectiveStatementImpl 61/86861/17
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 13:29:25 +0000 (14:29 +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>
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 a64b32333d84cd4a73d9bf8c0753c04e8150431a..87f8e3c9bdfb94274ef8c1c0e7006a800409f4c5 100644 (file)
  */
 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;
 
-final class ContainerEffectiveStatementImpl extends AbstractEffectiveContainerSchemaNode<ContainerStatement>
-        implements ContainerEffectiveStatement, DerivableSchemaNode {
-    private final @NonNull ImmutableSet<ActionDefinition> actions;
-    private final @NonNull ImmutableSet<NotificationDefinition> notifications;
+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