From 62d7ddd750e36387d7be16e366064ea7e794f502 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Tue, 4 Feb 2020 16:27:13 +0100 Subject: [PATCH] Migrate choice statement implementations 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 --- .../api/stmt/ChoiceEffectiveStatement.java | 9 +- .../yang/model/api/stmt/ChoiceStatement.java | 6 + .../stmt/AbstractEffectiveDataSchemaNode.java | 1 + .../AbstractChoiceStatementSupport.java | 84 ++++++++++++-- .../choice/ChoiceEffectiveStatementImpl.java | 108 +++++++----------- .../stmt/choice/EmptyChoiceStatement.java | 18 +++ ...tImpl.java => RegularChoiceStatement.java} | 12 +- 7 files changed, 153 insertions(+), 85 deletions(-) create mode 100644 yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/choice/EmptyChoiceStatement.java rename yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/choice/{ChoiceStatementImpl.java => RegularChoiceStatement.java} (50%) diff --git a/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/ChoiceEffectiveStatement.java b/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/ChoiceEffectiveStatement.java index 6c555623fc..3bb503d37b 100644 --- a/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/ChoiceEffectiveStatement.java +++ b/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/ChoiceEffectiveStatement.java @@ -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, - SchemaTreeAwareEffectiveStatement { - + SchemaTreeAwareEffectiveStatement { + @Override + default StatementDefinition statementDefinition() { + return YangStmtMapping.CHOICE; + } } diff --git a/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/ChoiceStatement.java b/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/ChoiceStatement.java index c1e9f7a6b1..0fae809f28 100644 --- a/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/ChoiceStatement.java +++ b/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/ChoiceStatement.java @@ -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, DefaultStatementAwareDeclaredStatement, MandatoryStatementAwareDeclaredStatement { + @Override + default StatementDefinition statementDefinition() { + return YangStmtMapping.CHOICE; + } default @NonNull Collection getCases() { return declaredSubstatements(CaseStatement.class); diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/AbstractEffectiveDataSchemaNode.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/AbstractEffectiveDataSchemaNode.java index 88956b96b4..b7c6afad59 100644 --- a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/AbstractEffectiveDataSchemaNode.java +++ b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/AbstractEffectiveDataSchemaNode.java @@ -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> extends AbstractEffectiveSchemaNode implements DataSchemaNode { diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/choice/AbstractChoiceStatementSupport.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/choice/AbstractChoiceStatementSupport.java index 3606979c79..6df064d9d5 100644 --- a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/choice/AbstractChoiceStatementSupport.java +++ b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/choice/AbstractChoiceStatementSupport.java @@ -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 + extends BaseQNameStatementSupport implements ImplicitParentAwareStatementSupport { AbstractChoiceStatementSupport() { super(YangStmtMapping.CHOICE); @@ -36,10 +51,8 @@ abstract class AbstractChoiceStatementSupport @Override public final Optional> 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 ctx) { - return new ChoiceStatementImpl(ctx); + protected final ChoiceStatement createDeclared(@NonNull final StmtContext ctx, + final ImmutableList> substatements) { + return new RegularChoiceStatement(ctx.coerceStatementArgument(), substatements); + } + + @Override + protected final ChoiceStatement createEmptyDeclared(@NonNull final StmtContext ctx) { + return new EmptyChoiceStatement(ctx.coerceStatementArgument()); + } + + @Override + protected final ChoiceEffectiveStatement createEffective( + final StmtContext ctx, + final ChoiceStatement declared, final ImmutableList> substatements) { + // FIXME: YANGTOOLS-652: this is rather unnecessary + final SortedMap 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 ctx) { - return new ChoiceEffectiveStatementImpl(ctx); + protected final ChoiceEffectiveStatement createEmptyEffective( + final StmtContext ctx, final ChoiceStatement declared) { + return createEffective(ctx, declared, ImmutableList.of()); } abstract StatementSupport implictCase(); diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/choice/ChoiceEffectiveStatementImpl.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/choice/ChoiceEffectiveStatementImpl.java index 75cbaab4cd..bb8aef96a1 100644 --- a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/choice/ChoiceEffectiveStatementImpl.java +++ b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/choice/ChoiceEffectiveStatementImpl.java @@ -7,91 +7,72 @@ */ 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.Collection; -import java.util.LinkedHashSet; 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 - implements ChoiceEffectiveStatement, ChoiceSchemaNode, DerivableSchemaNode { - - private final ImmutableSet augmentations; +final class ChoiceEffectiveStatementImpl extends WithSubstatements + implements ChoiceEffectiveStatement, ChoiceSchemaNode, DerivableSchemaNode, + DataSchemaNodeMixin, AugmentationTargetMixin, + MandatoryMixin { private final ImmutableSortedMap cases; private final CaseSchemaNode defaultCase; private final ChoiceSchemaNode original; - private final boolean mandatory; - - ChoiceEffectiveStatementImpl(final StmtContext ctx) { - super(ctx); - this.original = (ChoiceSchemaNode) ctx.getOriginalCtx().map(StmtContext::buildEffective).orElse(null); - - // initSubstatementCollectionsAndFields - final Set augmentationsInit = new LinkedHashSet<>(); - final SortedMap 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 ctx, + final ImmutableList> substatements, final int flags, + final SortedMap 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 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 getOriginal() { - return Optional.ofNullable(original); + public int flags() { + return flags; } @Override - public Collection getAvailableAugmentations() { - return augmentations; + public Optional getOriginal() { + return Optional.ofNullable(original); } @Override @@ -104,11 +85,6 @@ final class ChoiceEffectiveStatementImpl extends AbstractEffectiveDataSchemaNode return Optional.ofNullable(defaultCase); } - @Override - public boolean isMandatory() { - return mandatory; - } - @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 index 0000000000..e3b25906e5 --- /dev/null +++ b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/choice/EmptyChoiceStatement.java @@ -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); + } +} diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/choice/ChoiceStatementImpl.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/choice/RegularChoiceStatement.java similarity index 50% rename from yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/choice/ChoiceStatementImpl.java rename to yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/choice/RegularChoiceStatement.java index f985bb8b55..56651eaf00 100644 --- a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/choice/ChoiceStatementImpl.java +++ b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/choice/RegularChoiceStatement.java @@ -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 - implements ChoiceStatement { - ChoiceStatementImpl(final StmtContext context) { - super(context); +final class RegularChoiceStatement extends WithSubstatements implements ChoiceStatement { + RegularChoiceStatement(final QName argument, final ImmutableList> substatements) { + super(argument, substatements); } } -- 2.36.6