Migrate choice statement implementations 75/87475/3
authorRobert Varga <robert.varga@pantheon.tech>
Tue, 4 Feb 2020 15:27:13 +0000 (16:27 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Thu, 6 Feb 2020 11:14:46 +0000 (12:14 +0100)
Choice statement is rather large in terms of size, improve the
situation by refactoring both declared and effective statements,
shedding ~50% of shallow size.

JIRA: YANGTOOLS-1065
Change-Id: I3189b5f0a99ff16feab4996d2fdab54401fda7e7
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/ChoiceEffectiveStatement.java
yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/ChoiceStatement.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/AbstractEffectiveDataSchemaNode.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/choice/AbstractChoiceStatementSupport.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/choice/ChoiceEffectiveStatementImpl.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/choice/EmptyChoiceStatement.java [new file with mode: 0644]
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/choice/RegularChoiceStatement.java [moved from yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/choice/ChoiceStatementImpl.java with 50% similarity]

index 6c555623fcdd892125bdfecc8dc411965ddf7110..3bb503d37b53f2d8639e120fa353c627cc12aacc 100644 (file)
@@ -9,9 +9,14 @@ package org.opendaylight.yangtools.yang.model.api.stmt;
 
 import com.google.common.annotations.Beta;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
 
 @Beta
 public interface ChoiceEffectiveStatement extends SchemaTreeEffectiveStatement<ChoiceStatement>,
-    SchemaTreeAwareEffectiveStatement<QName, ChoiceStatement> {
-
+        SchemaTreeAwareEffectiveStatement<QName, ChoiceStatement> {
+    @Override
+    default StatementDefinition statementDefinition() {
+        return YangStmtMapping.CHOICE;
+    }
 }
index c1e9f7a6b19ea60842f43ee406fe17631f29df99..0fae809f28cf2b4da01b0e7ba9c8c00d317e3997 100644 (file)
@@ -10,9 +10,15 @@ package org.opendaylight.yangtools.yang.model.api.stmt;
 import java.util.Collection;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
 
 public interface ChoiceStatement extends DataDefinitionStatement, ConfigStatementAwareDeclaredStatement<QName>,
         DefaultStatementAwareDeclaredStatement, MandatoryStatementAwareDeclaredStatement<QName> {
+    @Override
+    default StatementDefinition statementDefinition() {
+        return YangStmtMapping.CHOICE;
+    }
 
     default @NonNull Collection<? extends CaseStatement> getCases() {
         return declaredSubstatements(CaseStatement.class);
index 10c3f499cbb7261f8e3c2d5a9e220d9ca62770bb..829ad7d635985c5a532c1797d7febfea00745e48 100644 (file)
@@ -17,6 +17,7 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.CopyHistory;
 import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 
+@Deprecated(forRemoval = true)
 public abstract class AbstractEffectiveDataSchemaNode<D extends DeclaredStatement<QName>> extends
         AbstractEffectiveSchemaNode<D> implements DataSchemaNode {
 
index 3606979c797db9470ddc11f075e3e16690645f30..6df064d9d54baebf6d684d15110098a52cd237fd 100644 (file)
@@ -7,23 +7,38 @@
  */
 package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.choice;
 
+import com.google.common.collect.ImmutableList;
 import java.util.Optional;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Status;
 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.ChoiceEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.DefaultEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.MandatoryEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.StatusEffectiveStatement;
 import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.ChildSchemaNodeNamespace;
 import org.opendaylight.yangtools.yang.parser.rfc7950.reactor.YangValidationBundles;
-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.ImplicitParentAwareStatementSupport;
+import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
 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.SourceException;
 
 abstract class AbstractChoiceStatementSupport
-        extends AbstractQNameStatementSupport<ChoiceStatement, ChoiceEffectiveStatement>
+        extends BaseQNameStatementSupport<ChoiceStatement, ChoiceEffectiveStatement>
         implements ImplicitParentAwareStatementSupport {
     AbstractChoiceStatementSupport() {
         super(YangStmtMapping.CHOICE);
@@ -36,10 +51,8 @@ abstract class AbstractChoiceStatementSupport
 
     @Override
     public final Optional<StatementSupport<?, ?, ?>> getImplicitParentFor(final StatementDefinition stmtDef) {
-        if (YangValidationBundles.SUPPORTED_CASE_SHORTHANDS.contains(stmtDef)) {
-            return Optional.of(implictCase());
-        }
-        return Optional.empty();
+        return YangValidationBundles.SUPPORTED_CASE_SHORTHANDS.contains(stmtDef) ? Optional.of(implictCase())
+                : Optional.empty();
     }
 
     @Override
@@ -48,14 +61,63 @@ abstract class AbstractChoiceStatementSupport
     }
 
     @Override
-    public final ChoiceStatement createDeclared(final StmtContext<QName, ChoiceStatement, ?> ctx) {
-        return new ChoiceStatementImpl(ctx);
+    protected final ChoiceStatement createDeclared(@NonNull final StmtContext<QName, ChoiceStatement, ?> ctx,
+            final ImmutableList<? extends DeclaredStatement<?>> substatements) {
+        return new RegularChoiceStatement(ctx.coerceStatementArgument(), substatements);
+    }
+
+    @Override
+    protected final ChoiceStatement createEmptyDeclared(@NonNull final StmtContext<QName, ChoiceStatement, ?> ctx) {
+        return new EmptyChoiceStatement(ctx.coerceStatementArgument());
+    }
+
+    @Override
+    protected final ChoiceEffectiveStatement createEffective(
+            final StmtContext<QName, ChoiceStatement, ChoiceEffectiveStatement> ctx,
+            final ChoiceStatement declared, final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
+        // FIXME: YANGTOOLS-652: this is rather unnecessary
+        final SortedMap<QName, CaseSchemaNode> cases = new TreeMap<>();
+        for (final EffectiveStatement<?, ?> effectiveStatement : substatements) {
+            if (effectiveStatement instanceof CaseSchemaNode) {
+                final CaseSchemaNode choiceCaseNode = (CaseSchemaNode) effectiveStatement;
+                // FIXME: we may be overwriting a previous entry, is that really okay?
+                cases.put(choiceCaseNode.getQName(), choiceCaseNode);
+            }
+        }
+
+        final String defaultArg = findFirstArgument(substatements, DefaultEffectiveStatement.class, null);
+        final CaseSchemaNode defaultCase;
+        if (defaultArg != null) {
+            final QName qname;
+            try {
+                qname = QName.create(ctx.coerceStatementArgument(), defaultArg);
+            } catch (IllegalArgumentException e) {
+                throw new SourceException(ctx.getStatementSourceReference(), "Default statement has invalid name '%s'",
+                    defaultArg, e);
+            }
+
+            // FIXME: this does not work with submodules, as they are
+            defaultCase = InferenceException.throwIfNull(cases.get(qname), ctx.getStatementSourceReference(),
+                "Default statement refers to missing case %s", qname);
+        } else {
+            defaultCase = null;
+        }
+
+        final int flags = new FlagsBuilder()
+                .setHistory(ctx.getCopyHistory())
+                .setStatus(findFirstArgument(substatements, StatusEffectiveStatement.class, Status.CURRENT))
+                .setConfiguration(ctx.isConfiguration())
+                .setMandatory(findFirstArgument(substatements, MandatoryEffectiveStatement.class, Boolean.FALSE))
+                .toFlags();
+
+        return new ChoiceEffectiveStatementImpl(declared, ctx, substatements, flags, cases, defaultCase,
+            (ChoiceSchemaNode) ctx.getOriginalCtx().map(StmtContext::buildEffective).orElse(null));
     }
 
     @Override
-    public final ChoiceEffectiveStatement createEffective(
-            final StmtContext<QName, ChoiceStatement, ChoiceEffectiveStatement> ctx) {
-        return new ChoiceEffectiveStatementImpl(ctx);
+    protected final ChoiceEffectiveStatement createEmptyEffective(
+            final StmtContext<QName, ChoiceStatement, ChoiceEffectiveStatement> ctx, final ChoiceStatement declared) {
+        return createEffective(ctx, declared, ImmutableList.of());
     }
 
     abstract StatementSupport<?, ?, ?> implictCase();
index cc92780e9763303decdc51a59f8ae0608c4fdd5c..9949d9ac734b3ce7b25b2be731ae6caca83edd17 100644 (file)
@@ -7,91 +7,73 @@
  */
 package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.choice;
 
-import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSortedMap;
-import java.util.LinkedHashSet;
 import java.util.Objects;
 import java.util.Optional;
-import java.util.Set;
 import java.util.SortedMap;
-import java.util.TreeMap;
+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.AugmentationSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
+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.ChoiceEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.DefaultEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.MandatoryEffectiveStatement;
-import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.AbstractEffectiveDataSchemaNode;
-import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.AbstractDeclaredEffectiveStatement.DefaultWithSchemaTree.WithSubstatements;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStatementMixins.AugmentationTargetMixin;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStatementMixins.DataSchemaNodeMixin;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStatementMixins.MandatoryMixin;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
-import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
 
-final class ChoiceEffectiveStatementImpl extends AbstractEffectiveDataSchemaNode<ChoiceStatement>
-        implements ChoiceEffectiveStatement, ChoiceSchemaNode, DerivableSchemaNode {
-
-    private final ImmutableSet<AugmentationSchemaNode> augmentations;
+final class ChoiceEffectiveStatementImpl extends WithSubstatements<QName, ChoiceStatement, ChoiceEffectiveStatement>
+        implements ChoiceEffectiveStatement, ChoiceSchemaNode, DerivableSchemaNode,
+                   DataSchemaNodeMixin<QName, ChoiceStatement>, AugmentationTargetMixin<QName, ChoiceStatement>,
+                   MandatoryMixin<QName, ChoiceStatement> {
     private final ImmutableSortedMap<QName, CaseSchemaNode> cases;
     private final CaseSchemaNode defaultCase;
     private final ChoiceSchemaNode original;
-    private final boolean mandatory;
-
-    ChoiceEffectiveStatementImpl(final StmtContext<QName, ChoiceStatement, ChoiceEffectiveStatement> ctx) {
-        super(ctx);
-        this.original = (ChoiceSchemaNode) ctx.getOriginalCtx().map(StmtContext::buildEffective).orElse(null);
-
-        // initSubstatementCollectionsAndFields
-        final Set<AugmentationSchemaNode> augmentationsInit = new LinkedHashSet<>();
-        final SortedMap<QName, CaseSchemaNode> casesInit = new TreeMap<>();
-
-        for (final EffectiveStatement<?, ?> effectiveStatement : effectiveSubstatements()) {
-            if (effectiveStatement instanceof AugmentationSchemaNode) {
-                final AugmentationSchemaNode augmentationSchema = (AugmentationSchemaNode) effectiveStatement;
-                augmentationsInit.add(augmentationSchema);
-            }
-            if (effectiveStatement instanceof CaseSchemaNode) {
-                final CaseSchemaNode choiceCaseNode = (CaseSchemaNode) effectiveStatement;
-                // FIXME: we may be overwriting a previous entry, is that really okay?
-                casesInit.put(choiceCaseNode.getQName(), choiceCaseNode);
-            }
-        }
-
-        this.augmentations = ImmutableSet.copyOf(augmentationsInit);
-        this.cases = ImmutableSortedMap.copyOfSorted(casesInit);
+    private final @NonNull SchemaPath path;
+    private final int flags;
+
+    ChoiceEffectiveStatementImpl(final ChoiceStatement declared,
+            final StmtContext<QName, ChoiceStatement, ChoiceEffectiveStatement> ctx,
+            final ImmutableList<? extends EffectiveStatement<?, ?>> substatements, final int flags,
+            final SortedMap<QName, CaseSchemaNode> cases, final @Nullable CaseSchemaNode defaultCase,
+            final @Nullable ChoiceSchemaNode original) {
+        super(declared, ctx, substatements);
+        this.flags = flags;
+        this.path = ctx.getSchemaPath().get();
+        this.cases = ImmutableSortedMap.copyOfSorted(cases);
+        this.defaultCase = defaultCase;
+        this.original = original;
+    }
 
-        final Optional<String> defaultArg = findFirstEffectiveSubstatementArgument(DefaultEffectiveStatement.class);
-        if (defaultArg.isPresent()) {
-            final String arg = defaultArg.get();
-            final QName qname;
-            try {
-                qname = QName.create(getQName(), arg);
-            } catch (IllegalArgumentException e) {
-                throw new SourceException(ctx.getStatementSourceReference(), "Default statement has invalid name '%s'",
-                    arg, e);
-            }
+    @Override
+    public @NonNull QName argument() {
+        return path.getLastComponent();
+    }
 
-            // FIXME: this does not work with submodules, as they are
-            defaultCase = InferenceException.throwIfNull(cases.get(qname), ctx.getStatementSourceReference(),
-                "Default statement refers to missing case %s", qname);
-        } else {
-            defaultCase = null;
-        }
+    @Override
+    public QName getQName() {
+        return argument();
+    }
 
-        mandatory = findFirstEffectiveSubstatementArgument(MandatoryEffectiveStatement.class).orElse(Boolean.FALSE)
-                .booleanValue();
+    @Override
+    public SchemaPath getPath() {
+        return path;
     }
 
     @Override
-    public Optional<ChoiceSchemaNode> getOriginal() {
-        return Optional.ofNullable(original);
+    public int flags() {
+        return flags;
     }
 
     @Override
-    public Set<AugmentationSchemaNode> getAvailableAugmentations() {
-        return augmentations;
+    public Optional<ChoiceSchemaNode> getOriginal() {
+        return Optional.ofNullable(original);
     }
 
     @Override
@@ -104,11 +86,6 @@ final class ChoiceEffectiveStatementImpl extends AbstractEffectiveDataSchemaNode
         return Optional.ofNullable(defaultCase);
     }
 
-    @Override
-    public boolean isMandatory() {
-        return mandatory;
-    }
-
     @Override
     public int hashCode() {
         final int prime = 31;
@@ -134,6 +111,7 @@ final class ChoiceEffectiveStatementImpl extends AbstractEffectiveDataSchemaNode
     }
 
     @Override
+
     public String toString() {
         return ChoiceEffectiveStatementImpl.class.getSimpleName() + "["
                 + "qname=" + getQName()
diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/choice/EmptyChoiceStatement.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/choice/EmptyChoiceStatement.java
new file mode 100644 (file)
index 0000000..e3b2590
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.choice;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceStatement;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.AbstractDeclaredStatement.WithQNameArgument;
+
+final class EmptyChoiceStatement extends WithQNameArgument implements ChoiceStatement {
+    EmptyChoiceStatement(final QName argument) {
+        super(argument);
+    }
+}
@@ -7,14 +7,14 @@
  */
 package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.choice;
 
+import com.google.common.collect.ImmutableList;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceStatement;
-import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractDeclaredStatement;
-import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.AbstractDeclaredStatement.WithQNameArgument.WithSubstatements;
 
-final class ChoiceStatementImpl extends AbstractDeclaredStatement<QName>
-        implements ChoiceStatement {
-    ChoiceStatementImpl(final StmtContext<QName, ChoiceStatement, ?> context) {
-        super(context);
+final class RegularChoiceStatement extends WithSubstatements implements ChoiceStatement {
+    RegularChoiceStatement(final QName argument, final ImmutableList<? extends DeclaredStatement<?>> substatements) {
+        super(argument, substatements);
     }
 }