*/
package org.opendaylight.yangtools.yang.parser.stmt.rfc6020;
+import java.util.Iterator;
+import javax.annotation.Nullable;
+
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.TypeOfCopy;
import java.util.Collection;
import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
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.StatementDefinition;
import org.opendaylight.yangtools.yang.model.api.stmt.AugmentStatement;
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.NamespaceToModule;
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.ModuleNameToModuleQName;
import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase;
public final class AugmentUtils {
- private AugmentUtils() {
- }
-
private static final String REGEX_PATH_REL1 = "\\.\\.?\\s*/(.+)";
private static final String REGEX_PATH_REL2 = "//.*";
- public static Iterable<QName> parseAugmentPath(StmtContext<?, ?, ?> ctx, String path) {
+ private AugmentUtils() {
+ }
+
+ public static Iterable<QName> parseAugmentPath(StmtContext<?, ?, ?> ctx,
+ String path) {
if (path.matches(REGEX_PATH_REL1) || path.matches(REGEX_PATH_REL2)) {
throw new IllegalArgumentException(
return Utils.parseXPath(ctx, path);
}
- public static void copyFromSourceToTarget(StatementContextBase<?, ?, ?> sourceCtx,
+ public static void copyFromSourceToTarget(
+ StatementContextBase<?, ?, ?> sourceCtx,
StatementContextBase<?, ?, ?> targetCtx) throws SourceException {
QNameModule newQNameModule = getNewQNameModule(targetCtx, sourceCtx);
}
- public static void copyDeclaredStmts(StatementContextBase<?, ?, ?> sourceCtx,
- StatementContextBase<?, ?, ?> targetCtx, QNameModule newQNameModule) throws SourceException {
- Collection<? extends StatementContextBase<?, ?, ?>> declaredSubstatements = sourceCtx.declaredSubstatements();
+ public static void copyDeclaredStmts(
+ StatementContextBase<?, ?, ?> sourceCtx,
+ StatementContextBase<?, ?, ?> targetCtx, QNameModule newQNameModule)
+ throws SourceException {
+ Collection<? extends StatementContextBase<?, ?, ?>> declaredSubstatements = sourceCtx
+ .declaredSubstatements();
for (StatementContextBase<?, ?, ?> originalStmtCtx : declaredSubstatements) {
if (needToCopyByAugment(originalStmtCtx)) {
- StatementContextBase<?, ?, ?> copy = originalStmtCtx.createCopy(newQNameModule, targetCtx);
+ StatementContextBase<?, ?, ?> copy = originalStmtCtx
+ .createCopy(newQNameModule, targetCtx,
+ TypeOfCopy.ADDED_BY_AUGMENTATION);
targetCtx.addEffectiveSubstatement(copy);
} else if (isReusedByAugment(originalStmtCtx)) {
targetCtx.addEffectiveSubstatement(originalStmtCtx);
}
}
- public static void copyEffectiveStmts(StatementContextBase<?, ?, ?> sourceCtx,
- StatementContextBase<?, ?, ?> targetCtx, QNameModule newQNameModule) throws SourceException {
- Collection<? extends StatementContextBase<?, ?, ?>> effectiveSubstatements = sourceCtx.effectiveSubstatements();
+ public static void copyEffectiveStmts(
+ StatementContextBase<?, ?, ?> sourceCtx,
+ StatementContextBase<?, ?, ?> targetCtx, QNameModule newQNameModule)
+ throws SourceException {
+ Collection<? extends StatementContextBase<?, ?, ?>> effectiveSubstatements = sourceCtx
+ .effectiveSubstatements();
for (StatementContextBase<?, ?, ?> originalStmtCtx : effectiveSubstatements) {
if (needToCopyByAugment(originalStmtCtx)) {
- StatementContextBase<?, ?, ?> copy = originalStmtCtx.createCopy(newQNameModule, targetCtx);
+ StatementContextBase<?, ?, ?> copy = originalStmtCtx
+ .createCopy(newQNameModule, targetCtx,
+ TypeOfCopy.ADDED_BY_AUGMENTATION);
targetCtx.addEffectiveSubstatement(copy);
} else if (isReusedByAugment(originalStmtCtx)) {
targetCtx.addEffectiveSubstatement(originalStmtCtx);
}
}
- public static QNameModule getNewQNameModule(StatementContextBase<?, ?, ?> targetCtx,
+ public static QNameModule getNewQNameModule(
+ StatementContextBase<?, ?, ?> targetCtx,
StatementContextBase<?, ?, ?> sourceCtx) {
Object targetStmtArgument = targetCtx.getStatementArgument();
final StatementContextBase<?, ?, ?> root = sourceCtx.getRoot();
final String moduleName = (String) root.getStatementArgument();
- final QNameModule sourceQNameModule = root.getFromNamespace(ModuleNameToModuleQName.class, moduleName);
+ final QNameModule sourceQNameModule = root.getFromNamespace(
+ ModuleNameToModuleQName.class, moduleName);
if (targetStmtArgument instanceof QName) {
QName targetQName = (QName) targetStmtArgument;
noCopyDefSet.add(Rfc6020Mapping.USES);
StatementDefinition def = stmtContext.getPublicDefinition();
- return (!noCopyDefSet.contains(def));
+ return !noCopyDefSet.contains(def);
}
public static boolean isReusedByAugment(StmtContext<?, ?, ?> stmtContext) {
- HashSet<StatementDefinition> reusedDefSet = new HashSet<>();
+ Set<StatementDefinition> reusedDefSet = new HashSet<>();
reusedDefSet.add(Rfc6020Mapping.TYPEDEF);
StatementDefinition def = stmtContext.getPublicDefinition();
- if (reusedDefSet.contains(def))
- return true;
- else
- return false;
+
+ return reusedDefSet.contains(def);
}
public static StatementContextBase<?, ?, ?> getAugmentTargetCtx(
final Mutable<SchemaNodeIdentifier, AugmentStatement, EffectiveStatement<SchemaNodeIdentifier, AugmentStatement>> augmentNode) {
- final SchemaNodeIdentifier augmentTargetPath = augmentNode.getStatementArgument();
-
- QNameModule module;
- if (augmentTargetPath != null) {
- module = augmentTargetPath.getPathFromRoot().iterator().next().getModule();
- } else {
+ final SchemaNodeIdentifier augmentTargetNode = augmentNode
+ .getStatementArgument();
+ if (augmentTargetNode == null) {
throw new IllegalArgumentException(
"Augment argument null, something bad happened in some of previous parsing phases");
}
- StatementContextBase<?, ?, ?> rootStatementCtx = (StatementContextBase<?, ?, ?>) augmentNode.getFromNamespace(
- NamespaceToModule.class, module);
+ List<StatementContextBase<?, ?, ?>> rootStatementCtxList = new LinkedList<>();
- final StatementContextBase<?, ?, ?> augmentTargetCtx = Utils.findCtxOfNodeInRoot(rootStatementCtx,
- augmentTargetPath);
+ if (augmentTargetNode.isAbsolute()) {
- if (augmentTargetCtx == null) {
+ QNameModule module = augmentTargetNode.getPathFromRoot().iterator()
+ .next().getModule();
- throw new NullPointerException(String.format(
- "Augment path %s not found in target model so its resulting context is null",
- augmentNode.rawStatementArgument()));
+ StatementContextBase<?, ?, ?> rootStatementCtx = (StatementContextBase<?, ?, ?>) augmentNode
+ .getFromNamespace(NamespaceToModule.class, module);
+ rootStatementCtxList.add(rootStatementCtx);
+ final Map<?, ?> subModules = rootStatementCtx
+ .getAllFromNamespace(IncludedModuleContext.class);
+ if (subModules != null) {
+ rootStatementCtxList
+ .addAll((Collection<? extends StatementContextBase<?, ?, ?>>) subModules
+ .values());
+ }
+
+ } else {
+ StatementContextBase<?, ?, ?> parent = (StatementContextBase<?, ?, ?>) augmentNode
+ .getParentContext();
+ if (StmtContextUtils.producesDeclared(parent, UsesStatement.class)) {
+ rootStatementCtxList.add(parent.getParentContext());
+ } else {
+ // error
+ }
+ }
+
+ StatementContextBase<?, ?, ?> augmentTargetCtx = null;
+ for (final StatementContextBase<?, ?, ?> rootStatementCtx : rootStatementCtxList) {
+ augmentTargetCtx = findCtxOfNodeInRoot(rootStatementCtx,
+ augmentTargetNode);
+ if (augmentTargetCtx != null)
+ break;
}
return augmentTargetCtx;
}
+
+ @Nullable
+ public static StatementContextBase<?, ?, ?> findCtxOfNodeInSubstatements(
+ StatementContextBase<?, ?, ?> rootStmtCtx,
+ final Iterable<QName> path) {
+
+ StatementContextBase<?, ?, ?> parent = rootStmtCtx;
+
+ Iterator<QName> pathIter = path.iterator();
+ while (pathIter.hasNext()) {
+ QName nextPathQName = pathIter.next();
+ StatementContextBase<?, ?, ?> foundSubstatement = getSubstatementByQName(
+ parent, nextPathQName);
+
+ if (foundSubstatement == null) {
+ return null;
+ }
+ if (!pathIter.hasNext()) {
+ return foundSubstatement;
+ }
+
+ parent = foundSubstatement;
+ }
+
+ return null;
+ }
+
+ public static StatementContextBase<?, ?, ?> getSubstatementByQName(
+ StatementContextBase<?, ?, ?> parent, QName nextPathQName) {
+
+ Collection<StatementContextBase<?, ?, ?>> declaredSubstatement = parent
+ .declaredSubstatements();
+ Collection<StatementContextBase<?, ?, ?>> effectiveSubstatement = parent
+ .effectiveSubstatements();
+
+ Collection<StatementContextBase<?, ?, ?>> allSubstatements = new LinkedList<>();
+ allSubstatements.addAll(declaredSubstatement);
+ allSubstatements.addAll(effectiveSubstatement);
+
+ for (StatementContextBase<?, ?, ?> substatement : allSubstatements) {
+ if (isAllowedAugmentTarget(substatement)
+ && nextPathQName
+ .equals(substatement.getStatementArgument())) {
+ return substatement;
+ }
+ }
+
+ return null;
+ }
+
+ public static boolean isAllowedAugmentTarget(
+ StatementContextBase<?, ?, ?> substatement) {
+
+ /*
+ * :TODO Substatement must be allowed augment target type e.g.
+ * Container, etc... and must be not for example grouping, identity etc.
+ * It is problem in case when more than one substatements have the same
+ * QName, for example Grouping and Container are siblings and they have the
+ * same QName. We must find the Container and the Grouping must be ignored
+ * as disallowed augment target.
+ */
+
+ return true;
+ }
+
+ @Nullable
+ public static StatementContextBase<?, ?, ?> findCtxOfNodeInRoot(
+ StatementContextBase<?, ?, ?> rootStmtCtx,
+ final SchemaNodeIdentifier node) {
+ return findCtxOfNodeInSubstatements(rootStmtCtx, node.getPathFromRoot());
+ }
}