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=8106aa6350fd0d086d7d6ddaa2df73502e89e7b3;hb=17f092cc375493891b15139cc0f57584298ba18e;hp=c1194deec5e3749eeebd0627a2a5f811252e681b;hpb=c4dc5b33e7d24670b59cc81b65e15b37a3268608;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 c1194deec5..8106aa6350 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,89 +7,104 @@ */ 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.StmtContext; import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable; +import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.TypeOfCopy; 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 { + private static final Logger LOG = LoggerFactory.getLogger(GroupingUtils.class); + private GroupingUtils() { + throw new UnsupportedOperationException(); } /** - * @param sourceGrpStmtCtx - * @param targetCtx - * @throws SourceException + * @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) + throws SourceException { + + 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) throws SourceException { + for (StatementContextBase originalStmtCtx : sourceGrpStmtCtx.declaredSubstatements()) { if (needToCopyByUses(originalStmtCtx)) { - StatementContextBase copy = originalStmtCtx.createCopy(newQNameModule, targetCtx); + StatementContextBase copy = originalStmtCtx.createCopy(newQNameModule, targetCtx, + TypeOfCopy.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) throws SourceException { + for (StatementContextBase originalStmtCtx : sourceGrpStmtCtx.effectiveSubstatements()) { if (needToCopyByUses(originalStmtCtx)) { - StatementContextBase copy = originalStmtCtx.createCopy(newQNameModule, targetCtx); + StatementContextBase copy = originalStmtCtx.createCopy(newQNameModule, targetCtx, + TypeOfCopy.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())) { + if (targetCtx.isRootContext()) { + return targetCtx.getFromNamespace(ModuleCtxToModuleQName.class, targetCtx); + } + if (targetCtx.getPublicDefinition() == Rfc6020Mapping.AUGMENT) { + return targetCtx.getFromNamespace(ModuleCtxToModuleQName.class, targetCtx.getRoot()); + } + 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; - } + return ((QName) targetStmtArgument).getModule(); } else { return null; } @@ -98,46 +113,119 @@ public final class GroupingUtils { } } - 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); + 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); - Set noCopyDefSet = new HashSet(); - noCopyDefSet.add(Rfc6020Mapping.USES); + public static boolean needToCopyByUses(final StmtContext stmtContext) { + final StatementDefinition def = stmtContext.getPublicDefinition(); - StatementDefinition def = stmtContext.getPublicDefinition(); - return !noCopyDefSet.contains(def); + return !(NOCOPY_DEF_SET.contains(def) || (NOCOPY_FROM_GROUPING_SET.contains(def) + && Rfc6020Mapping.GROUPING.equals(stmtContext.getParentContext().getPublicDefinition()))); } - public static boolean isReusedByUses(StmtContext stmtContext) { - - Set 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(); - return reusedDefSet.contains(def); + 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); - } + final Mutable> usesNode, + final StatementContextBase targetNodeStmtCtx) throws SourceException { + for (StatementContextBase subStmtCtx : usesNode.declaredSubstatements()) { if (StmtContextUtils.producesDeclared(subStmtCtx, RefineStatement.class)) { - // :TODO resolve and perform refine statement + 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) { + + Object refineArgument = refineCtx.getStatementArgument(); + Preconditions.checkArgument(refineArgument instanceof SchemaNodeIdentifier, + "Invalid refine argument %s. It must be instance of SchemaNodeIdentifier. At %s", refineArgument, + refineCtx.getStatementSourceReference()); + + SchemaNodeIdentifier refineTargetNodeIdentifier = (SchemaNodeIdentifier) refineArgument; + 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.warn("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 (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) { + + 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) { + 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) { + + Collection supportedRefineTargets = YangValidationBundles.SUPPORTED_REFINE_TARGETS.get( + refineSubstatementCtx.getPublicDefinition()); + + return supportedRefineTargets == null || supportedRefineTargets.isEmpty() + || supportedRefineTargets.contains(refineTargetNodeCtx.getPublicDefinition()); + } }