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%2Frfc6020%2FGroupingUtils.java;h=5c7954526e8ea4df4817614f9579d0e620677a30;hb=35691e4c2baa44e60dd8a882319e9b63b3b1b43e;hp=44f91489ab9045b41b0a2d560e135e7d2a6ed99e;hpb=f1c55073f8d7631007c01a401346cc83383e5745;p=yangtools.git diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/GroupingUtils.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/GroupingUtils.java index 44f91489ab..5c7954526e 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/GroupingUtils.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/GroupingUtils.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the @@ -7,152 +7,231 @@ */ package org.opendaylight.yangtools.yang.parser.stmt.rfc6020; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableSet; import java.util.Collection; -import java.util.HashSet; +import java.util.Set; 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.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.RefineStatement; +import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier; import org.opendaylight.yangtools.yang.model.api.stmt.UsesStatement; -import org.opendaylight.yangtools.yang.model.api.stmt.WhenStatement; +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.StmtContextUtils; 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; + +public final class GroupingUtils { -public class GroupingUtils { + private static final Logger LOG = LoggerFactory.getLogger(GroupingUtils.class); + + private GroupingUtils() { + throw new UnsupportedOperationException(); + } /** * @param sourceGrpStmtCtx + * source grouping statement context * @param targetCtx + * target context + * @param usesNode + * uses node * @throws SourceException + * instance of SourceException */ - public static void copyFromSourceToTarget( - StatementContextBase sourceGrpStmtCtx, - StatementContextBase targetCtx) throws SourceException { - - QNameModule newQNameModule = getNewQNameModule(targetCtx, - sourceGrpStmtCtx); - copyDeclaredStmts(sourceGrpStmtCtx, targetCtx, newQNameModule); - copyEffectiveStmts(sourceGrpStmtCtx, targetCtx, newQNameModule); + public static void copyFromSourceToTarget(final StatementContextBase sourceGrpStmtCtx, + final StatementContextBase targetCtx, + final StmtContext.Mutable> usesNode) { + final QNameModule newQNameModule = getNewQNameModule(targetCtx, sourceGrpStmtCtx); + copyDeclaredStmts(sourceGrpStmtCtx, targetCtx, usesNode, newQNameModule); + copyEffectiveStmts(sourceGrpStmtCtx, targetCtx, usesNode, newQNameModule); } - public static void copyDeclaredStmts( - StatementContextBase sourceGrpStmtCtx, - StatementContextBase targetCtx, QNameModule newQNameModule) - throws SourceException { - Collection> declaredSubstatements = sourceGrpStmtCtx - .declaredSubstatements(); - for (StatementContextBase originalStmtCtx : declaredSubstatements) { + public static void copyDeclaredStmts(final StatementContextBase sourceGrpStmtCtx, + final StatementContextBase targetCtx, + final StmtContext.Mutable> usesNode, + final QNameModule newQNameModule) { + for (final StatementContextBase originalStmtCtx : sourceGrpStmtCtx.declaredSubstatements()) { + if (!StmtContextUtils.areFeaturesSupported(originalStmtCtx)) { + continue; + } if (needToCopyByUses(originalStmtCtx)) { - StatementContextBase copy = originalStmtCtx - .createCopy(newQNameModule, targetCtx); + final StatementContextBase copy = originalStmtCtx.createCopy(newQNameModule, targetCtx, + CopyType.ADDED_BY_USES); targetCtx.addEffectiveSubstatement(copy); - } else if (isReusedByUses(originalStmtCtx)) { + usesNode.addAsEffectOfStatement(copy); + } else if (isReusedByUsesOnTop(originalStmtCtx)) { targetCtx.addEffectiveSubstatement(originalStmtCtx); + usesNode.addAsEffectOfStatement(originalStmtCtx); } } } - public static void copyEffectiveStmts( - StatementContextBase sourceGrpStmtCtx, - StatementContextBase targetCtx, QNameModule newQNameModule) - throws SourceException { - Collection> effectiveSubstatements = sourceGrpStmtCtx - .effectiveSubstatements(); - for (StatementContextBase originalStmtCtx : effectiveSubstatements) { + public static void copyEffectiveStmts(final StatementContextBase sourceGrpStmtCtx, + final StatementContextBase targetCtx, + final StmtContext.Mutable> usesNode, + final QNameModule newQNameModule) { + for (final StatementContextBase originalStmtCtx : sourceGrpStmtCtx.effectiveSubstatements()) { if (needToCopyByUses(originalStmtCtx)) { - StatementContextBase copy = originalStmtCtx - .createCopy(newQNameModule, targetCtx); + final StatementContextBase copy = originalStmtCtx.createCopy(newQNameModule, targetCtx, + CopyType.ADDED_BY_USES); targetCtx.addEffectiveSubstatement(copy); - } else if (isReusedByUses(originalStmtCtx)) { + usesNode.addAsEffectOfStatement(copy); + } else if (isReusedByUsesOnTop(originalStmtCtx)) { targetCtx.addEffectiveSubstatement(originalStmtCtx); + usesNode.addAsEffectOfStatement(originalStmtCtx); } } } - public static QNameModule getNewQNameModule( - StatementContextBase targetCtx, - StmtContext stmtContext) { + public static QNameModule getNewQNameModule(final StatementContextBase targetCtx, + final StmtContext stmtContext) { if (needToCreateNewQName(stmtContext.getPublicDefinition())) { - Object targetStmtArgument = targetCtx.getStatementArgument(); - Object sourceStmtArgument = stmtContext.getStatementArgument(); - if (targetStmtArgument instanceof QName - && sourceStmtArgument instanceof QName) { - QName targetQName = (QName) targetStmtArgument; - QNameModule targetQNameModule = targetQName.getModule(); - - QName sourceQName = (QName) sourceStmtArgument; - QNameModule sourceQNameModule = sourceQName.getModule(); - - if (targetQNameModule.equals(sourceQNameModule)) - return null; - else - return targetQNameModule; - } else + if (targetCtx.isRootContext()) { + return targetCtx.getFromNamespace(ModuleCtxToModuleQName.class, targetCtx); + } + if (targetCtx.getPublicDefinition() == Rfc6020Mapping.AUGMENT) { + return targetCtx.getFromNamespace(ModuleCtxToModuleQName.class, targetCtx.getRoot()); + } + + final Object targetStmtArgument = targetCtx.getStatementArgument(); + final Object sourceStmtArgument = stmtContext.getStatementArgument(); + if (targetStmtArgument instanceof QName && sourceStmtArgument instanceof QName) { + return ((QName) targetStmtArgument).getModule(); + } else { return null; - } else + } + } else { return null; + } } - public static boolean needToCreateNewQName( - StatementDefinition publicDefinition) { + public static boolean needToCreateNewQName(final StatementDefinition publicDefinition) { return true; } - public static boolean needToCopyByUses(StmtContext stmtContext) { + private static final Set NOCOPY_DEF_SET = ImmutableSet.of(Rfc6020Mapping.USES, + Rfc6020Mapping.TYPEDEF, Rfc6020Mapping.TYPE); + 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.TYPEDEF, + Rfc6020Mapping.TYPE, Rfc6020Mapping.USES); + private static final Set TOP_REUSED_DEF_SET = ImmutableSet.of(Rfc6020Mapping.TYPEDEF, + Rfc6020Mapping.TYPE); - HashSet noCopyDefSet = new HashSet(); - noCopyDefSet.add(Rfc6020Mapping.USES); + public static boolean needToCopyByUses(final StmtContext stmtContext) { + final StatementDefinition def = stmtContext.getPublicDefinition(); - StatementDefinition def = stmtContext.getPublicDefinition(); - if (noCopyDefSet.contains(def)) - return false; - else - return true; + return !(NOCOPY_DEF_SET.contains(def) || (NOCOPY_FROM_GROUPING_SET.contains(def) && Rfc6020Mapping.GROUPING + .equals(stmtContext.getParentContext().getPublicDefinition()))); } - public static boolean isReusedByUses(StmtContext stmtContext) { - - HashSet reusedDefSet = new HashSet(); - reusedDefSet.add(Rfc6020Mapping.TYPEDEF); + public static boolean isReusedByUses(final StmtContext stmtContext) { + return REUSED_DEF_SET.contains(stmtContext.getPublicDefinition()); + } - StatementDefinition def = stmtContext.getPublicDefinition(); - if (reusedDefSet.contains(def)) - return true; - else - return false; + public static boolean isReusedByUsesOnTop(final StmtContext stmtContext) { + return TOP_REUSED_DEF_SET.contains(stmtContext.getPublicDefinition()); } public static void resolveUsesNode( - Mutable> usesNode, - StatementContextBase targetNodeStmtCtx) - throws SourceException { - - Collection> declaredSubstatements = usesNode - .declaredSubstatements(); - for (StatementContextBase subStmtCtx : declaredSubstatements) { - if (StmtContextUtils.producesDeclared(subStmtCtx, - WhenStatement.class)) { - StatementContextBase copy = subStmtCtx.createCopy( - null, targetNodeStmtCtx); - targetNodeStmtCtx.addEffectiveSubstatement(copy); - } - if (StmtContextUtils.producesDeclared(subStmtCtx, - RefineStatement.class)) { - // :TODO resolve and perform refine statement + final Mutable> usesNode, + final StatementContextBase targetNodeStmtCtx) { + for (final StatementContextBase subStmtCtx : usesNode.declaredSubstatements()) { + if (StmtContextUtils.producesDeclared(subStmtCtx, RefineStatement.class)) { + performRefine(subStmtCtx, targetNodeStmtCtx); } - if (StmtContextUtils.producesDeclared(subStmtCtx, - AugmentStatement.class)) { - // :TODO find target node and perform augmentation + } + } + + private static void performRefine(final StatementContextBase refineCtx, + final StatementContextBase usesParentCtx) { + + final Object refineArgument = refineCtx.getStatementArgument(); + Preconditions.checkArgument(refineArgument instanceof SchemaNodeIdentifier, + "Invalid refine argument %s. It must be instance of SchemaNodeIdentifier. At %s", refineArgument, + refineCtx.getStatementSourceReference()); + + final SchemaNodeIdentifier refineTargetNodeIdentifier = (SchemaNodeIdentifier) refineArgument; + final StatementContextBase refineTargetNodeCtx = Utils.findNode(usesParentCtx, + refineTargetNodeIdentifier); + Preconditions.checkArgument(refineTargetNodeCtx != null, "Refine target node %s not found. At %s", + refineTargetNodeIdentifier, refineCtx.getStatementSourceReference()); + if (StmtContextUtils.isUnknownStatement(refineTargetNodeCtx)) { + LOG.debug( + "Refine node '{}' in uses '{}' has target node unknown statement '{}'. Refine has been skipped. At line: {}", + refineCtx.getStatementArgument(), refineCtx.getParentContext().getStatementArgument(), + refineTargetNodeCtx.getStatementArgument(), refineCtx.getStatementSourceReference()); + refineCtx.addAsEffectOfStatement(refineTargetNodeCtx); + return; + } + + addOrReplaceNodes(refineCtx, refineTargetNodeCtx); + refineCtx.addAsEffectOfStatement(refineTargetNodeCtx); + } + + private static void addOrReplaceNodes(final StatementContextBase refineCtx, + final StatementContextBase refineTargetNodeCtx) { + for (final StatementContextBase refineSubstatementCtx : refineCtx.declaredSubstatements()) { + if (isSupportedRefineSubstatement(refineSubstatementCtx)) { + addOrReplaceNode(refineSubstatementCtx, refineTargetNodeCtx); } - // :TODO resolve other uses substatements } } + private static void addOrReplaceNode(final StatementContextBase 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.getParentContext() + .getStatementArgument(), refineSubstatementCtx.getPublicDefinition(), refineTargetNodeCtx + .getPublicDefinition()); + + if (isAllowedToAddByRefine(refineSubstatementDef)) { + refineTargetNodeCtx.addEffectiveSubstatement(refineSubstatementCtx); + } else { + refineTargetNodeCtx.removeStatementFromEffectiveSubstatements(refineSubstatementDef); + refineTargetNodeCtx.addEffectiveSubstatement(refineSubstatementCtx); + } + } + + private static final Set ALLOWED_TO_ADD_BY_REFINE_DEF_SET = ImmutableSet.of(Rfc6020Mapping.MUST); + + private static boolean isAllowedToAddByRefine(final StatementDefinition publicDefinition) { + return ALLOWED_TO_ADD_BY_REFINE_DEF_SET.contains(publicDefinition); + } + + private static boolean isSupportedRefineSubstatement(final StatementContextBase 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 StatementContextBase refineSubstatementCtx, + final StatementContextBase refineTargetNodeCtx) { + + final Collection supportedRefineTargets = YangValidationBundles.SUPPORTED_REFINE_TARGETS + .get(refineSubstatementCtx.getPublicDefinition()); + + return supportedRefineTargets == null || supportedRefineTargets.isEmpty() + || supportedRefineTargets.contains(refineTargetNodeCtx.getPublicDefinition()); + } }