X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=yang%2Fyang-parser-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fparser%2Fstmt%2Freactor%2FSubstatementContext.java;h=1c78ae16c096664129221ca05b7e18452e9fa0ed;hb=c24d6e2f39acbb11e22b5676bb7481ed52bec461;hp=4b1773c6a33e97a9611131d3807cf070489d007c;hpb=3903d34ece7e98167a071e1c2bb9a89ef35790c6;p=yangtools.git diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SubstatementContext.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SubstatementContext.java index 4b1773c6a3..1c78ae16c0 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SubstatementContext.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SubstatementContext.java @@ -10,60 +10,69 @@ package org.opendaylight.yangtools.yang.parser.stmt.reactor; import com.google.common.base.Optional; 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.Set; +import javax.annotation.Nonnull; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.QNameModule; +import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping; import org.opendaylight.yangtools.yang.model.api.SchemaPath; 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; import org.opendaylight.yangtools.yang.model.api.stmt.KeyStatement; import org.opendaylight.yangtools.yang.model.api.stmt.RefineStatement; 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.NamespaceBehaviour.NamespaceStorageNode; import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.Registry; import org.opendaylight.yangtools.yang.parser.spi.meta.QNameCacheNamespace; import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext; import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils; -import org.opendaylight.yangtools.yang.parser.spi.source.SourceException; +import org.opendaylight.yangtools.yang.parser.spi.source.AugmentToChoiceNamespace; import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace; import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace.ValidationBundleType; -import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.GroupingUtils; import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.Utils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -final class SubstatementContext, E extends EffectiveStatement> - extends StatementContextBase { +final class SubstatementContext, E extends EffectiveStatement> extends + StatementContextBase { + private static final Logger LOG = LoggerFactory.getLogger(SubstatementContext.class); private final StatementContextBase parent; private final A argument; private volatile SchemaPath schemaPath; - SubstatementContext(final StatementContextBase parent, - final ContextBuilder builder) throws SourceException { + SubstatementContext(final StatementContextBase parent, final ContextBuilder builder) { super(builder); this.parent = Preconditions.checkNotNull(parent, "Parent must not be null"); this.argument = builder.getDefinition().parseArgumentValue(this, builder.getRawArgument()); } @SuppressWarnings("unchecked") - SubstatementContext(final SubstatementContext original, - final QNameModule newQNameModule, - final StatementContextBase newParent, final TypeOfCopy typeOfCopy) { + SubstatementContext(final SubstatementContext original, final QNameModule newQNameModule, + final StatementContextBase newParent, final CopyType typeOfCopy) { super(original); this.parent = newParent; if (newQNameModule != null) { - if (original.argument instanceof QName) { - QName originalQName = (QName) original.argument; - this.argument = (A) - getFromNamespace(QNameCacheNamespace.class, - QName.create(newQNameModule, originalQName.getLocalName())); + final A originalArg = original.argument; + if (originalArg instanceof QName) { + final QName originalQName = (QName) originalArg; + this.argument = (A) getFromNamespace(QNameCacheNamespace.class, + QName.create(newQNameModule, originalQName.getLocalName())); } else if (StmtContextUtils.producesDeclared(original, KeyStatement.class)) { this.argument = (A) StmtContextUtils.replaceModuleQNameForKey( - (StmtContext, KeyStatement, ?>) original, - newQNameModule); + (StmtContext, KeyStatement, ?>) original, newQNameModule); } else { this.argument = original.argument; } @@ -72,39 +81,6 @@ final class SubstatementContext, E extends Eff } } - - private void copyDeclaredStmts(final SubstatementContext original, - final QNameModule newQNameModule, final TypeOfCopy typeOfCopy) - throws SourceException { - Collection> originalDeclaredSubstatements = original - .declaredSubstatements(); - for (StatementContextBase stmtContext : originalDeclaredSubstatements) { - if (GroupingUtils.needToCopyByUses(stmtContext)) { - StatementContextBase copy = stmtContext.createCopy( - newQNameModule, this, typeOfCopy); - this.addEffectiveSubstatement(copy); - } else if (GroupingUtils.isReusedByUses(stmtContext)) { - this.addEffectiveSubstatement(stmtContext); - } - } - } - - private void copyEffectiveStmts(final SubstatementContext original, - final QNameModule newQNameModule, final TypeOfCopy typeOfCopy) - throws SourceException { - Collection> originalEffectiveSubstatements = original - .effectiveSubstatements(); - for (StatementContextBase stmtContext : originalEffectiveSubstatements) { - if (GroupingUtils.needToCopyByUses(stmtContext)) { - StatementContextBase copy = stmtContext.createCopy( - newQNameModule, this, typeOfCopy); - this.addEffectiveSubstatement(copy); - } else if (GroupingUtils.isReusedByUses(stmtContext)) { - this.addEffectiveSubstatement(stmtContext); - } - } - } - @Override public StatementContextBase getParentContext() { return parent; @@ -120,6 +96,7 @@ final class SubstatementContext, E extends Eff return parent.getBehaviourRegistry(); } + @Nonnull @Override public RootStatementContext getRoot() { return parent.getRoot(); @@ -131,22 +108,22 @@ final class SubstatementContext, E extends Eff } @Override - public StatementContextBase createCopy( - final StatementContextBase newParent, final TypeOfCopy typeOfCopy) - throws SourceException { + public StatementContextBase createCopy(final StatementContextBase newParent, + final CopyType typeOfCopy) { return createCopy(null, newParent, typeOfCopy); } @Override public StatementContextBase createCopy(final QNameModule newQNameModule, - final StatementContextBase newParent, final TypeOfCopy typeOfCopy) - throws SourceException { - SubstatementContext copy = new SubstatementContext<>(this, newQNameModule, newParent, typeOfCopy); + final StatementContextBase newParent, final CopyType typeOfCopy) { + Preconditions.checkState(getCompletedPhase() == ModelProcessingPhase.EFFECTIVE_MODEL, + "Attempted to copy statement {} which has completed phase {}", this, getCompletedPhase()); - copy.addAllToCopyHistory(this.getCopyHistory()); - copy.addToCopyHistory(typeOfCopy); + final SubstatementContext copy = new SubstatementContext<>(this, newQNameModule, newParent, typeOfCopy); - if(this.getOriginalCtx() != null) { + copy.appendCopyHistory(typeOfCopy, this.getCopyHistory()); + + if (this.getOriginalCtx() != null) { copy.setOriginalCtx(this.getOriginalCtx()); } else { copy.setOriginalCtx(this); @@ -154,11 +131,72 @@ final class SubstatementContext, E extends Eff definition().onStatementAdded(copy); - copy.copyDeclaredStmts(this, newQNameModule, typeOfCopy); - copy.copyEffectiveStmts(this, newQNameModule, typeOfCopy); + copy.copyStatements(this, newQNameModule, typeOfCopy); return copy; } + private void copyStatements(final SubstatementContext original, final QNameModule newQNameModule, + final CopyType typeOfCopy) { + final Collection> declared = original.declaredSubstatements(); + final Collection> effective = original.effectiveSubstatements(); + final Collection> buffer = new ArrayList<>(declared.size() + effective.size()); + + for (final StatementContextBase stmtContext : declared) { + if (StmtContextUtils.areFeaturesSupported(stmtContext)) { + copySubstatement(stmtContext, newQNameModule, typeOfCopy, buffer); + } + } + + for (final StatementContextBase stmtContext : effective) { + copySubstatement(stmtContext, newQNameModule, typeOfCopy, buffer); + } + + addEffectiveSubstatements(buffer); + } + + private void copySubstatement(final StatementContextBase stmtContext, + final QNameModule newQNameModule, final CopyType typeOfCopy, + final Collection> buffer) { + if (needToCopyByUses(stmtContext)) { + final StatementContextBase copy = stmtContext.createCopy(newQNameModule, this, typeOfCopy); + 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 NOCOPY_FROM_GROUPING_SET = ImmutableSet.of( + Rfc6020Mapping.DESCRIPTION, + Rfc6020Mapping.REFERENCE, + Rfc6020Mapping.STATUS); + private static final Set REUSED_DEF_SET = ImmutableSet.of( + Rfc6020Mapping.TYPE, + Rfc6020Mapping.TYPEDEF, + Rfc6020Mapping.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 !Rfc6020Mapping.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); @@ -171,13 +209,14 @@ final class SubstatementContext, E extends Eff final SchemaPath parentPath = maybeParentPath.get(); if (argument instanceof QName) { - QName qname = (QName) argument; + final QName qname = (QName) argument; if (StmtContextUtils.producesDeclared(this, UsesStatement.class)) { return maybeParentPath.orNull(); } final SchemaPath path; - if (StmtContextUtils.producesDeclared(getParentContext(), ChoiceStatement.class) + if ((StmtContextUtils.producesDeclared(getParentContext(), ChoiceStatement.class) + || Boolean.TRUE.equals(parent.getFromNamespace(AugmentToChoiceNamespace.class, parent))) && isSupportedAsShorthandCase()) { path = parentPath.createChild(qname); } else { @@ -188,13 +227,13 @@ final class SubstatementContext, E extends Eff if (argument instanceof String) { // FIXME: This may yield illegal argument exceptions final StatementContextBase originalCtx = getOriginalCtx(); - final QName qname = (originalCtx != null) ? Utils.qNameFromArgument(originalCtx, (String) argument) - : Utils.qNameFromArgument(this, (String) argument); + final QName qname = (originalCtx != null) ? Utils.qNameFromArgument(originalCtx, (String) argument) : Utils + .qNameFromArgument(this, (String) argument); return parentPath.createChild(qname); } - if (argument instanceof SchemaNodeIdentifier && - (StmtContextUtils.producesDeclared(this, AugmentStatement.class) - || StmtContextUtils.producesDeclared(this, RefineStatement.class))) { + if (argument instanceof SchemaNodeIdentifier + && (StmtContextUtils.producesDeclared(this, AugmentStatement.class) || StmtContextUtils + .producesDeclared(this, RefineStatement.class))) { return parentPath.createChild(((SchemaNodeIdentifier) argument).getPathFromRoot()); } @@ -206,6 +245,7 @@ final class SubstatementContext, E extends Eff return maybeParentPath.orNull(); } + @Nonnull @Override public Optional getSchemaPath() { SchemaPath local = schemaPath; @@ -227,4 +267,43 @@ final class SubstatementContext, E extends Eff public boolean isRootContext() { return false; } + + @Override + public boolean isConfiguration() { + final StmtContext configStatement = StmtContextUtils.findFirstSubstatement(this, + ConfigStatement.class); + + /* + * If "config" statement is not specified, the default is the same as + * the parent schema node's "config" value. + */ + if (configStatement == null) { + return parent.isConfiguration(); + } + + /* + * If a parent node has "config" set to "true", the node underneath it + * can have "config" set to "true" or "false". + */ + if (parent.isConfiguration()) { + return configStatement.getStatementArgument(); + } + + /* + * If a parent node has "config" set to "false", no node underneath it + * can have "config" set to "true", therefore only "false" is permitted. + */ + if (!configStatement.getStatementArgument()) { + return false; + } + + throw new InferenceException( + "Parent node has config statement set to false, therefore no node underneath it can have config set to true", + getStatementSourceReference()); + } + + @Override + public boolean isEnabledSemanticVersioning() { + return parent.isEnabledSemanticVersioning(); + } }