final String rawArgument) {
super(def);
this.statementDeclSource = requireNonNull(ref);
- this.rawArgument = def.internArgument(rawArgument);
+ this.rawArgument = def.support().internArgument(rawArgument);
}
AbstractResumedStatement(final StatementDefinitionContext<A, D, E> def, final StatementSourceReference ref,
// FIXME: This is messy and is probably wrong in some corner case. Even if it is correct, the way how it is correct
// relies on hard-coded maps. At the end of the day, the logic needs to be controlled by statement's
// StatementSupport.
- // FIXME: YANGTOOLS-652: these maps look very much like those in UsesStatementImpl
+ // FIXME: YANGTOOLS-652: this map looks very much like UsesStatementSupport.TOP_REUSED_DEF_SET
private static final ImmutableSet<YangStmtMapping> REUSED_DEF_SET = ImmutableSet.of(
YangStmtMapping.TYPE,
YangStmtMapping.TYPEDEF,
YangStmtMapping.USES);
- private static final ImmutableSet<YangStmtMapping> NOCOPY_FROM_GROUPING_SET = ImmutableSet.of(
- YangStmtMapping.DESCRIPTION,
- YangStmtMapping.REFERENCE,
- YangStmtMapping.STATUS);
private void copySubstatement(final Mutable<?, ?, ?> substatement, final Collection<Mutable<?, ?, ?>> buffer) {
final StatementDefinition def = substatement.getPublicDefinition();
buffer.add(substatement);
return;
}
- // FIXME: YANGTOOLS-652: formerly known as "needToCopyByUses" (note inverted check, though)
- if (NOCOPY_FROM_GROUPING_SET.contains(def)) {
- // This is to say: if parent of source context is a grouping, ignore this statement.
- if (YangStmtMapping.GROUPING.equals(substatement.coerceParentContext().getPublicDefinition())) {
- LOG.debug("Skipping grouping statement {}", substatement);
- return;
- }
- }
- // FIXME: YANGTOOLS-694: we are forcing a copy here, hence even statements not affected by parent, copyType
- // or targetModule (and don't forget its substatements!). This really should be a callout
- // to StatementSupport. Note if that callout is allowed to return an Optional, it can
- // take care at least of the 'grouping from uses' case above.
- final Mutable<?, ?, ?> copy = childCopyOf(substatement, childCopyType, targetModule);
- LOG.debug("Copying substatement {} for {} as {}", substatement, this, copy);
- buffer.add(copy);
+ substatement.copyAsChildOf(this, childCopyType, targetModule).ifPresent(buffer::add);
}
// Statement copy mess ends here
addContextToNamespace(namespace, key, stmt);
}
+ @Override
+ public Optional<? extends Mutable<?, ?, ?>> copyAsChildOf(final Mutable<?, ?, ?> parent, final CopyType type,
+ final QNameModule targetModule) {
+ checkEffectiveModelCompleted(this);
+ return definition.support().copyAsChildOf(this, parent, type, targetModule);
+ }
+
@Override
public <X, Y extends DeclaredStatement<X>, Z extends EffectiveStatement<X, Y>> Mutable<X, Y, Z> childCopyOf(
final StmtContext<X, Y, Z> stmt, final CopyType type, final QNameModule targetModule) {
- checkState(stmt.getCompletedPhase() == ModelProcessingPhase.EFFECTIVE_MODEL,
- "Attempted to copy statement %s which has completed phase %s", stmt, stmt.getCompletedPhase());
-
+ checkEffectiveModelCompleted(stmt);
checkArgument(stmt instanceof StatementContextBase, "Unsupported statement %s", stmt);
return childCopyOf((StatementContextBase<X, Y, Z>)stmt, type, targetModule);
}
return result;
}
+ private static void checkEffectiveModelCompleted(final StmtContext<?, ?, ?> stmt) {
+ final ModelProcessingPhase phase = stmt.getCompletedPhase();
+ checkState(phase == ModelProcessingPhase.EFFECTIVE_MODEL,
+ "Attempted to copy statement %s which has completed phase %s", stmt, phase);
+ }
+
@Beta
public final boolean hasImplicitParentSupport() {
return definition.getFactory() instanceof ImplicitParentAwareStatementSupport;
if (fl != 0) {
return fl == SET_IGNORE_CONFIG;
}
- if (definition.isIgnoringConfig() || parent.isIgnoringConfig()) {
+ if (definition.support().isIgnoringConfig() || parent.isIgnoringConfig()) {
flags |= SET_IGNORE_CONFIG;
return true;
}
if (fl != 0) {
return fl == SET_IGNORE_IF_FEATURE;
}
- if (definition.isIgnoringIfFeatures() || parent.isIgnoringIfFeatures()) {
+ if (definition.support().isIgnoringIfFeatures() || parent.isIgnoringIfFeatures()) {
flags |= SET_IGNORE_IF_FEATURE;
return true;
}
return toStringHelper.add("statement", getStatementName());
}
- @NonNull StatementDefinitionContext<?, ?, ?> getSubDefinitionSpecificForArgument(final String argument) {
+ final @NonNull StatementDefinitionContext<?, ?, ?> getSubDefinitionSpecificForArgument(final String argument) {
if (!hasArgumentSpecificSubDefinitions()) {
return this;
}
return potential;
}
- boolean hasArgumentSpecificSubDefinitions() {
- return support.hasArgumentSpecificSupports();
+ final StatementSupport<A, D, E> support() {
+ return support;
}
- String internArgument(final String rawArgument) {
- return support.internArgument(rawArgument);
+ final boolean hasArgumentSpecificSubDefinitions() {
+ return support.hasArgumentSpecificSupports();
}
- StatementDefinitionContext<?, ?, ?> getAsUnknownStatementDefinition(
+ final StatementDefinitionContext<?, ?, ?> getAsUnknownStatementDefinition(
final StatementDefinitionContext<?, ?, ?> yangStmtDef) {
if (unknownStmtDefsOfYangStmts != null) {
final StatementDefinitionContext<?, ?, ?> existing = unknownStmtDefsOfYangStmts.get(yangStmtDef);
}
return ret;
}
-
- boolean isIgnoringIfFeatures() {
- return support.isIgnoringIfFeatures();
- }
-
- boolean isIgnoringConfig() {
- return support.isIgnoringConfig();
- }
}
package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.description;
import com.google.common.collect.ImmutableList;
+import java.util.Optional;
+import org.opendaylight.yangtools.yang.common.QNameModule;
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.stmt.DescriptionEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.DescriptionStatement;
import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.BaseStringStatementSupport;
+import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
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.meta.SubstatementValidator;
public final class DescriptionStatementSupport
return value;
}
+ @Override
+ public Optional<? extends Mutable<?, ?, ?>> copyAsChildOf(final Mutable<?, ?, ?> stmt,
+ final Mutable<?, ?, ?> parent, final CopyType type, final QNameModule targetModule) {
+ return StmtContextUtils.isChildOfGrouping(stmt) ? Optional.empty()
+ : super.copyAsChildOf(stmt, parent, type, targetModule);
+ }
+
@Override
protected SubstatementValidator getSubstatementValidator() {
return SUBSTATEMENT_VALIDATOR;
final DescriptionStatement declared) {
return new EmptyDescriptionEffectiveStatement(declared);
}
-}
\ No newline at end of file
+}
package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.reference;
import com.google.common.collect.ImmutableList;
+import java.util.Optional;
+import org.opendaylight.yangtools.yang.common.QNameModule;
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.stmt.ReferenceEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.ReferenceStatement;
import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.BaseStringStatementSupport;
+import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
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.meta.SubstatementValidator;
public final class ReferenceStatementSupport
return value;
}
+ @Override
+ public Optional<? extends Mutable<?, ?, ?>> copyAsChildOf(final Mutable<?, ?, ?> stmt,
+ final Mutable<?, ?, ?> parent, final CopyType type, final QNameModule targetModule) {
+ return StmtContextUtils.isChildOfGrouping(stmt) ? Optional.empty()
+ : super.copyAsChildOf(stmt, parent, type, targetModule);
+ }
+
@Override
protected SubstatementValidator getSubstatementValidator() {
return SUBSTATEMENT_VALIDATOR;
final ReferenceStatement declared) {
return new EmptyReferenceEffectiveStatement(declared);
}
-}
\ No newline at end of file
+}
package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.status;
import com.google.common.collect.ImmutableList;
+import java.util.Optional;
import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.common.QNameModule;
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.stmt.StatusEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.StatusStatement;
import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.BaseStatementSupport;
+import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
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.meta.SubstatementValidator;
import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
}
}
+ @Override
+ public Optional<? extends Mutable<?, ?, ?>> copyAsChildOf(final Mutable<?, ?, ?> stmt,
+ final Mutable<?, ?, ?> parent, final CopyType type, final QNameModule targetModule) {
+ return StmtContextUtils.isChildOfGrouping(stmt) ? Optional.empty()
+ : super.copyAsChildOf(stmt, parent, type, targetModule);
+ }
+
@Override
protected SubstatementValidator getSubstatementValidator() {
return SUBSTATEMENT_VALIDATOR;
return new EmptyStatusEffectiveStatement(declared);
}
}
-
-}
\ No newline at end of file
+}
*/
package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.uses;
-import com.google.common.base.Verify;
-import com.google.common.collect.ImmutableSet;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Optional;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.QNameModule;
-import org.opendaylight.yangtools.yang.common.YangVersion;
-import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
-import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
-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.UsesEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.UsesStatement;
-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.AbstractDeclaredStatement;
-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.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.ModuleCtxToModuleQName;
-import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
-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.reactor.StatementContextBase;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
final class UsesStatementImpl extends AbstractDeclaredStatement<QName> implements UsesStatement {
- private static final Logger LOG = LoggerFactory.getLogger(UsesStatementImpl.class);
-
UsesStatementImpl(final StmtContext<QName, UsesStatement, ?> context) {
super(context);
}
-
- /**
- * Copy statements from a grouping to a target node.
- *
- * @param sourceGrpStmtCtx
- * source grouping statement context
- * @param targetCtx
- * target context
- * @param usesNode
- * uses node
- * @throws SourceException
- * instance of SourceException
- */
- static void copyFromSourceToTarget(final Mutable<?, ?, ?> sourceGrpStmtCtx,
- final StatementContextBase<?, ?, ?> targetCtx,
- final Mutable<QName, UsesStatement, UsesEffectiveStatement> usesNode) {
- final Collection<? extends Mutable<?, ?, ?>> declared = sourceGrpStmtCtx.mutableDeclaredSubstatements();
- final Collection<? extends Mutable<?, ?, ?>> effective = sourceGrpStmtCtx.mutableEffectiveSubstatements();
- final Collection<Mutable<?, ?, ?>> buffer = new ArrayList<>(declared.size() + effective.size());
- final QNameModule newQNameModule = getNewQNameModule(targetCtx, sourceGrpStmtCtx);
-
- for (final Mutable<?, ?, ?> original : declared) {
- if (original.isSupportedByFeatures()) {
- copyStatement(original, targetCtx, newQNameModule, buffer);
- }
- }
-
- for (final Mutable<?, ?, ?> original : effective) {
- copyStatement(original, targetCtx, newQNameModule, buffer);
- }
-
- targetCtx.addEffectiveSubstatements(buffer);
- usesNode.addAsEffectOfStatement(buffer);
- }
-
- private static void copyStatement(final Mutable<?, ?, ?> original,
- final StatementContextBase<?, ?, ?> targetCtx, final QNameModule targetModule,
- final Collection<Mutable<?, ?, ?>> buffer) {
- if (needToCopyByUses(original)) {
- final Mutable<?, ?, ?> copy = targetCtx.childCopyOf(original, CopyType.ADDED_BY_USES, targetModule);
- buffer.add(copy);
- } else if (isReusedByUsesOnTop(original)) {
- buffer.add(original);
- }
- }
-
- // FIXME: YANGTOOLS-652: these maps look very much like those in InferredStatementContext
- private static final ImmutableSet<YangStmtMapping> TOP_REUSED_DEF_SET = ImmutableSet.of(
- YangStmtMapping.TYPE,
- YangStmtMapping.TYPEDEF);
-
- private static boolean isReusedByUsesOnTop(final StmtContext<?, ?, ?> stmtContext) {
- return TOP_REUSED_DEF_SET.contains(stmtContext.getPublicDefinition());
- }
-
- private static final ImmutableSet<YangStmtMapping> NOCOPY_FROM_GROUPING_SET = ImmutableSet.of(
- YangStmtMapping.DESCRIPTION,
- YangStmtMapping.REFERENCE,
- YangStmtMapping.STATUS);
- private static final ImmutableSet<YangStmtMapping> REUSED_DEF_SET = ImmutableSet.of(
- YangStmtMapping.TYPE,
- YangStmtMapping.TYPEDEF,
- YangStmtMapping.USES);
-
- public static boolean needToCopyByUses(final StmtContext<?, ?, ?> stmtContext) {
- final StatementDefinition def = stmtContext.getPublicDefinition();
- if (REUSED_DEF_SET.contains(def)) {
- LOG.trace("Will reuse {} statement {}", def, stmtContext);
- return false;
- }
- if (NOCOPY_FROM_GROUPING_SET.contains(def)) {
- return !YangStmtMapping.GROUPING.equals(stmtContext.coerceParentContext().getPublicDefinition());
- }
-
- LOG.trace("Will copy {} statement {}", def, stmtContext);
- return true;
- }
-
- public static void resolveUsesNode(final Mutable<QName, UsesStatement, UsesEffectiveStatement> usesNode,
- final StmtContext<?, ?, ?> targetNodeStmtCtx) {
- for (final Mutable<?, ?, ?> subStmtCtx : usesNode.mutableDeclaredSubstatements()) {
- if (StmtContextUtils.producesDeclared(subStmtCtx, RefineStatement.class)
- && areFeaturesSupported(subStmtCtx)) {
- performRefine(subStmtCtx, targetNodeStmtCtx);
- }
- }
- }
-
- private static boolean areFeaturesSupported(final StmtContext<?, ?, ?> subStmtCtx) {
- /*
- * In case of Yang 1.1, checks whether features are supported.
- */
- return !YangVersion.VERSION_1_1.equals(subStmtCtx.getRootVersion()) || subStmtCtx.isSupportedByFeatures();
- }
-
- private static void performRefine(final Mutable<?, ?, ?> subStmtCtx, final StmtContext<?, ?, ?> usesParentCtx) {
- final Object refineArgument = subStmtCtx.getStatementArgument();
- InferenceException.throwIf(!(refineArgument instanceof SchemaNodeIdentifier),
- subStmtCtx.getStatementSourceReference(),
- "Invalid refine argument %s. It must be instance of SchemaNodeIdentifier.", refineArgument);
-
- final Optional<StmtContext<?, ?, ?>> optRefineTargetCtx = ChildSchemaNodeNamespace.findNode(
- usesParentCtx, (SchemaNodeIdentifier) refineArgument);
- InferenceException.throwIf(!optRefineTargetCtx.isPresent(), subStmtCtx.getStatementSourceReference(),
- "Refine target node %s not found.", refineArgument);
-
- final StmtContext<?, ?, ?> refineTargetNodeCtx = optRefineTargetCtx.get();
- if (StmtContextUtils.isUnknownStatement(refineTargetNodeCtx)) {
- LOG.trace("Refine node '{}' in uses '{}' has target node unknown statement '{}'. "
- + "Refine has been skipped. At line: {}", subStmtCtx.getStatementArgument(),
- subStmtCtx.coerceParentContext().getStatementArgument(),
- refineTargetNodeCtx.getStatementArgument(), subStmtCtx.getStatementSourceReference());
- subStmtCtx.addAsEffectOfStatement(refineTargetNodeCtx);
- return;
- }
-
- Verify.verify(refineTargetNodeCtx instanceof StatementContextBase);
- addOrReplaceNodes(subStmtCtx, (StatementContextBase<?, ?, ?>) refineTargetNodeCtx);
- subStmtCtx.addAsEffectOfStatement(refineTargetNodeCtx);
- }
-
- private static void addOrReplaceNodes(final Mutable<?, ?, ?> subStmtCtx,
- final StatementContextBase<?, ?, ?> refineTargetNodeCtx) {
- for (final Mutable<?, ?, ?> refineSubstatementCtx : subStmtCtx.mutableDeclaredSubstatements()) {
- if (isSupportedRefineSubstatement(refineSubstatementCtx)) {
- addOrReplaceNode(refineSubstatementCtx, refineTargetNodeCtx);
- }
- }
- }
-
- private static void addOrReplaceNode(final Mutable<?, ?, ?> refineSubstatementCtx,
- final StatementContextBase<?, ?, ?> refineTargetNodeCtx) {
-
- final StatementDefinition refineSubstatementDef = refineSubstatementCtx.getPublicDefinition();
-
- SourceException.throwIf(!isSupportedRefineTarget(refineSubstatementCtx, refineTargetNodeCtx),
- refineSubstatementCtx.getStatementSourceReference(),
- "Error in module '%s' in the refine of uses '%s': can not perform refine of '%s' for the target '%s'.",
- refineSubstatementCtx.getRoot().getStatementArgument(),
- refineSubstatementCtx.coerceParentContext().getStatementArgument(),
- refineSubstatementCtx.getPublicDefinition(), refineTargetNodeCtx.getPublicDefinition());
-
- if (isAllowedToAddByRefine(refineSubstatementDef)) {
- refineTargetNodeCtx.addEffectiveSubstatement(refineSubstatementCtx);
- } else {
- refineTargetNodeCtx.removeStatementFromEffectiveSubstatements(refineSubstatementDef);
- refineTargetNodeCtx.addEffectiveSubstatement(refineSubstatementCtx);
- }
- }
-
- private static final ImmutableSet<YangStmtMapping> ALLOWED_TO_ADD_BY_REFINE_DEF_SET =
- ImmutableSet.of(YangStmtMapping.MUST);
-
- private static boolean isAllowedToAddByRefine(final StatementDefinition publicDefinition) {
- return ALLOWED_TO_ADD_BY_REFINE_DEF_SET.contains(publicDefinition);
- }
-
- private static boolean isSupportedRefineSubstatement(final StmtContext<?, ?, ?> refineSubstatementCtx) {
- final Collection<?> supportedRefineSubstatements = refineSubstatementCtx.getFromNamespace(
- ValidationBundlesNamespace.class, ValidationBundleType.SUPPORTED_REFINE_SUBSTATEMENTS);
-
- return supportedRefineSubstatements == null || supportedRefineSubstatements.isEmpty()
- || supportedRefineSubstatements.contains(refineSubstatementCtx.getPublicDefinition())
- || StmtContextUtils.isUnknownStatement(refineSubstatementCtx);
- }
-
- private static boolean isSupportedRefineTarget(final StmtContext<?, ?, ?> refineSubstatementCtx,
- final StmtContext<?, ?, ?> refineTargetNodeCtx) {
- final Collection<?> supportedRefineTargets = YangValidationBundles.SUPPORTED_REFINE_TARGETS
- .get(refineSubstatementCtx.getPublicDefinition());
-
- return supportedRefineTargets == null || supportedRefineTargets.isEmpty()
- || supportedRefineTargets.contains(refineTargetNodeCtx.getPublicDefinition());
- }
-
-
- private static QNameModule getNewQNameModule(final StmtContext<?, ?, ?> targetCtx,
- final StmtContext<?, ?, ?> stmtContext) {
- if (targetCtx.getParentContext() == null) {
- return targetCtx.getFromNamespace(ModuleCtxToModuleQName.class, targetCtx);
- }
- if (targetCtx.getPublicDefinition() == YangStmtMapping.AUGMENT) {
- return StmtContextUtils.getRootModuleQName(targetCtx);
- }
-
- final Object targetStmtArgument = targetCtx.getStatementArgument();
- final Object sourceStmtArgument = stmtContext.getStatementArgument();
- if (targetStmtArgument instanceof QName && sourceStmtArgument instanceof QName) {
- return ((QName) targetStmtArgument).getModule();
- }
-
- return null;
- }
}
*/
package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.uses;
+import com.google.common.base.Verify;
+import com.google.common.collect.ImmutableSet;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.Optional;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.common.YangVersion;
import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
+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.UsesEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.UsesStatement;
+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.GroupingNamespace;
import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractQNameStatementSupport;
+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.ModelActionBuilder;
import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.InferenceAction;
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.meta.SubstatementValidator;
+import org.opendaylight.yangtools.yang.parser.spi.source.ModuleCtxToModuleQName;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+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.reactor.StatementContextBase;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public final class UsesStatementSupport
extends AbstractQNameStatementSupport<UsesStatement, UsesEffectiveStatement> {
+ private static final Logger LOG = LoggerFactory.getLogger(UsesStatementSupport.class);
private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator.builder(YangStmtMapping
.USES)
.addAny(YangStmtMapping.AUGMENT)
final StatementContextBase<?, ?, ?> sourceGrpStmtCtx =
(StatementContextBase<?, ?, ?>) sourceGroupingPre.resolve(ctx);
- UsesStatementImpl.copyFromSourceToTarget(sourceGrpStmtCtx, targetNodeStmtCtx, usesNode);
- UsesStatementImpl.resolveUsesNode(usesNode, targetNodeStmtCtx);
+ copyFromSourceToTarget(sourceGrpStmtCtx, targetNodeStmtCtx, usesNode);
+ resolveUsesNode(usesNode, targetNodeStmtCtx);
StmtContextUtils.validateIfFeatureAndWhenOnListKeys(usesNode);
}
protected SubstatementValidator getSubstatementValidator() {
return SUBSTATEMENT_VALIDATOR;
}
-}
\ No newline at end of file
+
+ /**
+ * Copy statements from a grouping to a target node.
+ *
+ * @param sourceGrpStmtCtx
+ * source grouping statement context
+ * @param targetCtx
+ * target context
+ * @param usesNode
+ * uses node
+ * @throws SourceException
+ * instance of SourceException
+ */
+ private static void copyFromSourceToTarget(final Mutable<?, ?, ?> sourceGrpStmtCtx,
+ final StatementContextBase<?, ?, ?> targetCtx,
+ final Mutable<QName, UsesStatement, UsesEffectiveStatement> usesNode) {
+ final Collection<? extends Mutable<?, ?, ?>> declared = sourceGrpStmtCtx.mutableDeclaredSubstatements();
+ final Collection<? extends Mutable<?, ?, ?>> effective = sourceGrpStmtCtx.mutableEffectiveSubstatements();
+ final Collection<Mutable<?, ?, ?>> buffer = new ArrayList<>(declared.size() + effective.size());
+ final QNameModule newQNameModule = getNewQNameModule(targetCtx, sourceGrpStmtCtx);
+
+ for (final Mutable<?, ?, ?> original : declared) {
+ if (original.isSupportedByFeatures()) {
+ copyStatement(original, targetCtx, newQNameModule, buffer);
+ }
+ }
+
+ for (final Mutable<?, ?, ?> original : effective) {
+ copyStatement(original, targetCtx, newQNameModule, buffer);
+ }
+
+ targetCtx.addEffectiveSubstatements(buffer);
+ usesNode.addAsEffectOfStatement(buffer);
+ }
+
+ // FIXME: YANGTOOLS-652: this map looks very much like InferredStatementContext.REUSED_DEF_SET
+ private static final ImmutableSet<YangStmtMapping> TOP_REUSED_DEF_SET = ImmutableSet.of(
+ YangStmtMapping.TYPE,
+ YangStmtMapping.TYPEDEF);
+
+ private static void copyStatement(final Mutable<?, ?, ?> original,
+ final StatementContextBase<?, ?, ?> targetCtx, final QNameModule targetModule,
+ final Collection<Mutable<?, ?, ?>> buffer) {
+ final StatementDefinition def = original.getPublicDefinition();
+ if (TOP_REUSED_DEF_SET.contains(def)) {
+ buffer.add(original);
+ return;
+ }
+ // Do not propagate uses, as their effects have been accounted for in effective statements
+ // FIXME: YANGTOOLS-652: this check is different from InferredStatementContext. Why is that? We should express
+ // a common condition in our own implementation of copyAsChildOf()
+ if (!YangStmtMapping.USES.equals(def)) {
+ original.copyAsChildOf(targetCtx, CopyType.ADDED_BY_USES, targetModule).ifPresent(buffer::add);
+ }
+ }
+
+ private static QNameModule getNewQNameModule(final StmtContext<?, ?, ?> targetCtx,
+ final StmtContext<?, ?, ?> stmtContext) {
+ if (targetCtx.getParentContext() == null) {
+ return targetCtx.getFromNamespace(ModuleCtxToModuleQName.class, targetCtx);
+ }
+ if (targetCtx.getPublicDefinition() == YangStmtMapping.AUGMENT) {
+ return StmtContextUtils.getRootModuleQName(targetCtx);
+ }
+
+ final Object targetStmtArgument = targetCtx.getStatementArgument();
+ final Object sourceStmtArgument = stmtContext.getStatementArgument();
+ if (targetStmtArgument instanceof QName && sourceStmtArgument instanceof QName) {
+ return ((QName) targetStmtArgument).getModule();
+ }
+
+ return null;
+ }
+
+ private static void resolveUsesNode(final Mutable<QName, UsesStatement, UsesEffectiveStatement> usesNode,
+ final StmtContext<?, ?, ?> targetNodeStmtCtx) {
+ for (final Mutable<?, ?, ?> subStmtCtx : usesNode.mutableDeclaredSubstatements()) {
+ if (StmtContextUtils.producesDeclared(subStmtCtx, RefineStatement.class)
+ && areFeaturesSupported(subStmtCtx)) {
+ performRefine(subStmtCtx, targetNodeStmtCtx);
+ }
+ }
+ }
+
+ private static boolean areFeaturesSupported(final StmtContext<?, ?, ?> subStmtCtx) {
+ /*
+ * In case of Yang 1.1, checks whether features are supported.
+ */
+ return !YangVersion.VERSION_1_1.equals(subStmtCtx.getRootVersion()) || subStmtCtx.isSupportedByFeatures();
+ }
+
+ private static void performRefine(final Mutable<?, ?, ?> subStmtCtx, final StmtContext<?, ?, ?> usesParentCtx) {
+ final Object refineArgument = subStmtCtx.getStatementArgument();
+ InferenceException.throwIf(!(refineArgument instanceof SchemaNodeIdentifier),
+ subStmtCtx.getStatementSourceReference(),
+ "Invalid refine argument %s. It must be instance of SchemaNodeIdentifier.", refineArgument);
+
+ final Optional<StmtContext<?, ?, ?>> optRefineTargetCtx = ChildSchemaNodeNamespace.findNode(
+ usesParentCtx, (SchemaNodeIdentifier) refineArgument);
+ InferenceException.throwIf(!optRefineTargetCtx.isPresent(), subStmtCtx.getStatementSourceReference(),
+ "Refine target node %s not found.", refineArgument);
+
+ final StmtContext<?, ?, ?> refineTargetNodeCtx = optRefineTargetCtx.get();
+ if (StmtContextUtils.isUnknownStatement(refineTargetNodeCtx)) {
+ LOG.trace("Refine node '{}' in uses '{}' has target node unknown statement '{}'. "
+ + "Refine has been skipped. At line: {}", subStmtCtx.getStatementArgument(),
+ subStmtCtx.coerceParentContext().getStatementArgument(),
+ refineTargetNodeCtx.getStatementArgument(), subStmtCtx.getStatementSourceReference());
+ subStmtCtx.addAsEffectOfStatement(refineTargetNodeCtx);
+ return;
+ }
+
+ Verify.verify(refineTargetNodeCtx instanceof StatementContextBase);
+ addOrReplaceNodes(subStmtCtx, (StatementContextBase<?, ?, ?>) refineTargetNodeCtx);
+ subStmtCtx.addAsEffectOfStatement(refineTargetNodeCtx);
+ }
+
+ private static void addOrReplaceNodes(final Mutable<?, ?, ?> subStmtCtx,
+ final StatementContextBase<?, ?, ?> refineTargetNodeCtx) {
+ for (final Mutable<?, ?, ?> refineSubstatementCtx : subStmtCtx.mutableDeclaredSubstatements()) {
+ if (isSupportedRefineSubstatement(refineSubstatementCtx)) {
+ addOrReplaceNode(refineSubstatementCtx, refineTargetNodeCtx);
+ }
+ }
+ }
+
+ private static void addOrReplaceNode(final Mutable<?, ?, ?> refineSubstatementCtx,
+ final StatementContextBase<?, ?, ?> refineTargetNodeCtx) {
+
+ final StatementDefinition refineSubstatementDef = refineSubstatementCtx.getPublicDefinition();
+
+ SourceException.throwIf(!isSupportedRefineTarget(refineSubstatementCtx, refineTargetNodeCtx),
+ refineSubstatementCtx.getStatementSourceReference(),
+ "Error in module '%s' in the refine of uses '%s': can not perform refine of '%s' for the target '%s'.",
+ refineSubstatementCtx.getRoot().getStatementArgument(),
+ refineSubstatementCtx.coerceParentContext().getStatementArgument(),
+ refineSubstatementCtx.getPublicDefinition(), refineTargetNodeCtx.getPublicDefinition());
+
+ if (isAllowedToAddByRefine(refineSubstatementDef)) {
+ refineTargetNodeCtx.addEffectiveSubstatement(refineSubstatementCtx);
+ } else {
+ refineTargetNodeCtx.removeStatementFromEffectiveSubstatements(refineSubstatementDef);
+ refineTargetNodeCtx.addEffectiveSubstatement(refineSubstatementCtx);
+ }
+ }
+
+ private static boolean isAllowedToAddByRefine(final StatementDefinition publicDefinition) {
+ return YangStmtMapping.MUST.equals(publicDefinition);
+ }
+
+ private static boolean isSupportedRefineSubstatement(final StmtContext<?, ?, ?> refineSubstatementCtx) {
+ final Collection<?> supportedRefineSubstatements = refineSubstatementCtx.getFromNamespace(
+ ValidationBundlesNamespace.class, ValidationBundleType.SUPPORTED_REFINE_SUBSTATEMENTS);
+
+ return supportedRefineSubstatements == null || supportedRefineSubstatements.isEmpty()
+ || supportedRefineSubstatements.contains(refineSubstatementCtx.getPublicDefinition())
+ || StmtContextUtils.isUnknownStatement(refineSubstatementCtx);
+ }
+
+ private static boolean isSupportedRefineTarget(final StmtContext<?, ?, ?> refineSubstatementCtx,
+ final StmtContext<?, ?, ?> refineTargetNodeCtx) {
+ final Collection<?> supportedRefineTargets = YangValidationBundles.SUPPORTED_REFINE_TARGETS.get(
+ refineSubstatementCtx.getPublicDefinition());
+
+ return supportedRefineTargets == null || supportedRefineTargets.isEmpty()
+ || supportedRefineTargets.contains(refineTargetNodeCtx.getPublicDefinition());
+ }
+}
import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Objects.requireNonNull;
+import java.util.Optional;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.yang.common.QNameModule;
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.parser.spi.meta.StmtContext.Mutable;
/**
* Class providing necessary support for processing a YANG statement. This class is intended to be subclassed
@Override
public boolean hasArgumentSpecificSupports() {
- // Most of statement supports don't have any argument specific
- // supports, so return 'false'.
+ // Most of statement supports don't have any argument specific supports, so return 'false'.
return false;
}
@Override
public StatementSupport<?, ?, ?> getSupportSpecificForArgument(final String argument) {
- // Most of statement supports don't have any argument specific
- // supports, so return null.
+ // Most of statement supports don't have any argument specific supports, so return null.
return null;
}
+ @Override
+ public Optional<? extends Mutable<?, ?, ?>> copyAsChildOf(final Mutable<?, ?, ?> stmt,
+ final Mutable<?, ?, ?> parent, final CopyType copyType, final QNameModule targetModule) {
+ // Most of statement supports will just want to copy the statement
+ // FIXME: YANGTOOLS-694: that is not strictly true. Subclasses of this should indicate if they are themselves
+ // copy-sensitive:
+ // 1) if they are not and cannot be targeted by inference, and all their current
+ // substatements are also non-sensitive, we want to return the same context.
+ // 2) if they are not and their current substatements are sensitive, we want to copy
+ // as a lazily-instantiated interceptor to let it deal with substatements when needed
+ // (YANGTOOLS-1067 prerequisite)
+ // 3) otherwise perform this eager copy
+ return Optional.of(parent.childCopyOf(stmt, copyType, targetModule));
+ }
+
/**
* Returns corresponding substatement validator of a statement support.
*
import com.google.common.annotations.Beta;
import com.google.common.collect.ForwardingObject;
+import java.util.Optional;
+import org.opendaylight.yangtools.yang.common.QNameModule;
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;
public StatementSupport<?, ?, ?> getSupportSpecificForArgument(final String argument) {
return delegate().getSupportSpecificForArgument(argument);
}
+
+ @Override
+ public Optional<? extends Mutable<?, ?, ?>> copyAsChildOf(final Mutable<?, ?, ?> stmt,
+ final Mutable<?, ?, ?> parent, final CopyType type, final QNameModule targetModule) {
+ return delegate().copyAsChildOf(stmt, parent, type, targetModule);
+ }
}
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.parser.spi.meta.StmtContext.Mutable;
import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
/**
*/
public interface StatementSupport<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
extends StatementDefinition, StatementFactory<A, D, E> {
-
/**
* Returns public statement definition, which will be present in built statements.
*
/**
* Adapts the argument value to match a new module.
*
- * @param ctx
- * Context, which may be used to access source-specific
- * namespaces required for parsing.
- * @param targetModule
- * Target module, may not be null.
+ * @param ctx Context, which may be used to access source-specific namespaces required for parsing.
+ * @param targetModule Target module, may not be null.
* @return Adapted argument value. The default implementation returns original value stored in context.
*/
default A adaptArgumentValue(final StmtContext<A, D, E> ctx, final QNameModule targetModule) {
* accessible via {@link StmtContext#getParentContext()}. One such use is populating the parent's namespaces to
* allow it to locate this child statement.
*
- * @param stmt
- * Context of added statement. No substatements are available.
+ * @param stmt Context of added statement. No substatements are available.
*/
void onStatementAdded(StmtContext.Mutable<A, D, E> stmt);
* Implementation may use method to perform actions on this event or register modification action using
* {@link StmtContext.Mutable#newInferenceAction(ModelProcessingPhase)}.
*
- * @param stmt
- * Context of added statement.
+ * @param stmt Context of added statement.
*/
void onPreLinkageDeclared(StmtContext.Mutable<A, D, E> stmt);
* Implementation may use method to perform actions on this event or register modification action using
* {@link StmtContext.Mutable#newInferenceAction(ModelProcessingPhase)}.
*
- * @param stmt
- * Context of added statement.
- * @throws SourceException
- * when an inconsistency is detected.
+ * @param stmt Context of added statement.
+ * @throws SourceException when an inconsistency is detected.
*/
void onLinkageDeclared(StmtContext.Mutable<A, D, E> stmt);
* Implementation may use method to perform actions on this event or register modification action using
* {@link StmtContext.Mutable#newInferenceAction(ModelProcessingPhase)}.
*
- * @param stmt
- * Context of added statement. Argument and statement parent is
- * accessible.
- * @throws SourceException
- * when an inconsistency is detected.
+ * @param stmt Context of added statement. Argument and statement parent is accessible.
+ * @throws SourceException when an inconsistency is detected.
*/
void onStatementDefinitionDeclared(StmtContext.Mutable<A, D, E> stmt);
* Implementation may use method to perform actions on this event or register modification action using
* {@link StmtContext.Mutable#newInferenceAction(ModelProcessingPhase)}.
*
- * @param stmt
- * Context of added statement. Argument and statement parent is
- * accessible.
- * @throws SourceException
- * when an inconsistency is detected.
+ * @param stmt Context of added statement. Argument and statement parent is accessible.
+ * @throws SourceException when an inconsistency is detected.
*/
void onFullDefinitionDeclared(StmtContext.Mutable<A, D, E> stmt);
* If this support has argument specific supports, the method returns support specific for given argument
* (e.g. type statement support need to be specialized based on its argument), otherwise returns null.
*
- * @param argument
- * argument of statement
+ * @param argument argument of statement
* @return statement support specific for supplied argument or null
*/
@Nullable StatementSupport<?, ?, ?> getSupportSpecificForArgument(String argument);
+ /**
+ * Create an optional copy of specified statement as a substatement of parent.
+ *
+ * <p>
+ * Note that while it may be tempting to return the same context, this is not safe in general case. It is only safe
+ * if the entire subtree is unaffected by changes to parent/namespace/history. This includes the semantics of this
+ * statement (it cannot be a target of any inference effects) as well as any substatements -- an extension statement
+ * is allowed pretty much anywhere and if its semantics are context-dependent, a simple instance reuse will not
+ * work.
+ *
+ * @param stmt Context of statement to be copied statement.
+ * @param parent Parent statement context
+ * @param type Type of copy being performed
+ * @param targetModule Target module, if present
+ * @return Empty if the statement should be ignored, or present with an instance that should be copied into parent.
+ */
+ @NonNull Optional<? extends Mutable<?, ?, ?>> copyAsChildOf(Mutable<?, ?, ?> stmt, Mutable<?, ?, ?> parent,
+ CopyType type, @Nullable QNameModule targetModule);
+
/**
* Given a raw string representation of an argument, try to use a shared representation.
*
- * @param rawArgument
- * Argument string
+ * @param rawArgument Argument string
* @return A potentially-shard instance
*/
default String internArgument(final String rawArgument) {
/**
* Returns unknown statement form of a regular YANG statement supplied as a parameter to the method.
*
- * @param yangStmtDef
- * statement definition of a regular yang statement
- * @return Optional of unknown statement form of a regular yang statement or
- * Optional.empty() if it is not supported by this statement support
+ * @param yangStmtDef statement definition of a regular YANG statement
+ * @return Optional of unknown statement form of a regular YANG statement or empty() if it is not supported by this
+ * statement support
*/
default Optional<StatementSupport<?, ?, ?>> getUnknownStatementDefinitionOf(final StatementDefinition yangStmtDef) {
return Optional.empty();
import static com.google.common.base.Verify.verifyNotNull;
+import com.google.common.annotations.Beta;
import com.google.common.base.VerifyException;
import com.google.common.collect.Iterables;
import com.google.common.collect.Streams;
return childCopyOf(stmt, type, null);
}
+ @Beta
+ @NonNull Optional<? extends Mutable<?, ?, ?>> copyAsChildOf(Mutable<?, ?, ?> parent, CopyType type,
+ @Nullable QNameModule targetModule);
+
@Override
default Collection<? extends StmtContext<?, ?, ?>> declaredSubstatements() {
return mutableDeclaredSubstatements();
import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Objects.requireNonNull;
+import com.google.common.annotations.Beta;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import java.util.Collection;
}
return Optional.ofNullable(revision);
}
+
+ /**
+ * Determine if a specific statetement context is a child of a statement context which produces a grouping.
+ *
+ * @param stmt Statement to examine
+ * @return True if parent context is that of a grouping.
+ */
+ @Beta
+ public static boolean isChildOfGrouping(final StmtContext<?, ?, ?> stmt) {
+ final StmtContext<?, ?, ?> parent = stmt.getParentContext();
+ return parent != null && parent.getPublicDefinition() == YangStmtMapping.GROUPING;
+ }
}