/**
* Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.yangtools.yang.parser.stmt.rfc6020;
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.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.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 parseAugmentPath(StmtContext, ?, ?> ctx, String path) {
if (path.matches(REGEX_PATH_REL1) || path.matches(REGEX_PATH_REL2)) {
throw new IllegalArgumentException(
"An argument for augment can be only absolute path; or descendant if used in uses");
}
return Utils.parseXPath(ctx, path);
}
public static void copyFromSourceToTarget(StatementContextBase, ?, ?> sourceCtx,
StatementContextBase, ?, ?> targetCtx) throws SourceException {
QNameModule newQNameModule = getNewQNameModule(targetCtx, sourceCtx);
copyDeclaredStmts(sourceCtx, targetCtx, newQNameModule);
copyEffectiveStmts(sourceCtx, targetCtx, newQNameModule);
}
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);
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();
for (StatementContextBase, ?, ?> originalStmtCtx : effectiveSubstatements) {
if (needToCopyByAugment(originalStmtCtx)) {
StatementContextBase, ?, ?> copy = originalStmtCtx.createCopy(newQNameModule, targetCtx);
targetCtx.addEffectiveSubstatement(copy);
} else if (isReusedByAugment(originalStmtCtx)) {
targetCtx.addEffectiveSubstatement(originalStmtCtx);
}
}
}
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);
if (targetStmtArgument instanceof QName) {
QName targetQName = (QName) targetStmtArgument;
QNameModule targetQNameModule = targetQName.getModule();
if (targetQNameModule.equals(sourceQNameModule)) {
return null;
} else {
return targetQNameModule;
}
} else {
return null;
}
}
public static boolean needToCopyByAugment(StmtContext, ?, ?> stmtContext) {
Set noCopyDefSet = new HashSet<>();
noCopyDefSet.add(Rfc6020Mapping.USES);
StatementDefinition def = stmtContext.getPublicDefinition();
return (!noCopyDefSet.contains(def));
}
public static boolean isReusedByAugment(StmtContext, ?, ?> stmtContext) {
HashSet reusedDefSet = new HashSet<>();
reusedDefSet.add(Rfc6020Mapping.TYPEDEF);
StatementDefinition def = stmtContext.getPublicDefinition();
if (reusedDefSet.contains(def))
return true;
else
return false;
}
public static StatementContextBase, ?, ?> getAugmentTargetCtx(
final Mutable> augmentNode) {
final SchemaNodeIdentifier augmentTargetNode = augmentNode.getStatementArgument();
List> rootStatementCtxList = new LinkedList<>();
if (augmentTargetNode.isAbsolute()) {
QNameModule module;
if (augmentTargetNode != null) {
module = augmentTargetNode.getPathFromRoot().iterator().next().getModule();
} else {
throw new IllegalArgumentException(
"Augment argument null, something bad happened in some of previous parsing phases");
}
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
}
}
List augmentTargetPath = new LinkedList<>();
augmentTargetPath.addAll((Collection extends QName>) augmentTargetNode.getPathFromRoot());
StatementContextBase, ?, ?> augmentTargetCtx = null;
for (final StatementContextBase, ?, ?> rootStatementCtx : rootStatementCtxList) {
augmentTargetCtx = Utils.findCtxOfNodeInRoot(rootStatementCtx,
augmentTargetPath);
if (augmentTargetCtx != null) break;
}
if (augmentTargetCtx == null) {
throw new NullPointerException(String.format(
"Augment path %s not found in target model so its resulting context is null",
augmentNode.rawStatementArgument()));
}
return augmentTargetCtx;
}
}