2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.yang.parser.stmt.rfc6020;
10 import java.util.Collection;
11 import java.util.HashSet;
12 import java.util.LinkedList;
13 import java.util.List;
17 import org.opendaylight.yangtools.yang.common.QName;
18 import org.opendaylight.yangtools.yang.common.QNameModule;
19 import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
20 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
21 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
22 import org.opendaylight.yangtools.yang.model.api.stmt.AugmentStatement;
23 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
24 import org.opendaylight.yangtools.yang.model.api.stmt.UsesStatement;
25 import org.opendaylight.yangtools.yang.parser.spi.NamespaceToModule;
26 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
27 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
28 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
29 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleNameToModuleQName;
30 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
31 import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase;
33 public final class AugmentUtils {
35 private static final String REGEX_PATH_REL1 = "\\.\\.?\\s*/(.+)";
36 private static final String REGEX_PATH_REL2 = "//.*";
38 private AugmentUtils() {
41 public static Iterable<QName> parseAugmentPath(StmtContext<?, ?, ?> ctx, String path) {
43 if (path.matches(REGEX_PATH_REL1) || path.matches(REGEX_PATH_REL2)) {
44 throw new IllegalArgumentException(
45 "An argument for augment can be only absolute path; or descendant if used in uses");
48 return Utils.parseXPath(ctx, path);
51 public static void copyFromSourceToTarget(StatementContextBase<?, ?, ?> sourceCtx,
52 StatementContextBase<?, ?, ?> targetCtx) throws SourceException {
54 QNameModule newQNameModule = getNewQNameModule(targetCtx, sourceCtx);
55 copyDeclaredStmts(sourceCtx, targetCtx, newQNameModule);
56 copyEffectiveStmts(sourceCtx, targetCtx, newQNameModule);
60 public static void copyDeclaredStmts(StatementContextBase<?, ?, ?> sourceCtx,
61 StatementContextBase<?, ?, ?> targetCtx, QNameModule newQNameModule) throws SourceException {
62 Collection<? extends StatementContextBase<?, ?, ?>> declaredSubstatements = sourceCtx.declaredSubstatements();
63 for (StatementContextBase<?, ?, ?> originalStmtCtx : declaredSubstatements) {
64 if (needToCopyByAugment(originalStmtCtx)) {
65 StatementContextBase<?, ?, ?> copy = originalStmtCtx.createCopy(newQNameModule, targetCtx);
66 targetCtx.addEffectiveSubstatement(copy);
67 } else if (isReusedByAugment(originalStmtCtx)) {
68 targetCtx.addEffectiveSubstatement(originalStmtCtx);
73 public static void copyEffectiveStmts(StatementContextBase<?, ?, ?> sourceCtx,
74 StatementContextBase<?, ?, ?> targetCtx, QNameModule newQNameModule) throws SourceException {
75 Collection<? extends StatementContextBase<?, ?, ?>> effectiveSubstatements = sourceCtx.effectiveSubstatements();
76 for (StatementContextBase<?, ?, ?> originalStmtCtx : effectiveSubstatements) {
77 if (needToCopyByAugment(originalStmtCtx)) {
78 StatementContextBase<?, ?, ?> copy = originalStmtCtx.createCopy(newQNameModule, targetCtx);
79 targetCtx.addEffectiveSubstatement(copy);
80 } else if (isReusedByAugment(originalStmtCtx)) {
81 targetCtx.addEffectiveSubstatement(originalStmtCtx);
86 public static QNameModule getNewQNameModule(StatementContextBase<?, ?, ?> targetCtx,
87 StatementContextBase<?, ?, ?> sourceCtx) {
88 Object targetStmtArgument = targetCtx.getStatementArgument();
90 final StatementContextBase<?, ?, ?> root = sourceCtx.getRoot();
91 final String moduleName = (String) root.getStatementArgument();
92 final QNameModule sourceQNameModule = root.getFromNamespace(ModuleNameToModuleQName.class, moduleName);
94 if (targetStmtArgument instanceof QName) {
95 QName targetQName = (QName) targetStmtArgument;
96 QNameModule targetQNameModule = targetQName.getModule();
98 if (targetQNameModule.equals(sourceQNameModule)) {
101 return targetQNameModule;
108 public static boolean needToCopyByAugment(StmtContext<?, ?, ?> stmtContext) {
110 Set<StatementDefinition> noCopyDefSet = new HashSet<>();
111 noCopyDefSet.add(Rfc6020Mapping.USES);
113 StatementDefinition def = stmtContext.getPublicDefinition();
114 return !noCopyDefSet.contains(def);
117 public static boolean isReusedByAugment(StmtContext<?, ?, ?> stmtContext) {
119 Set<StatementDefinition> reusedDefSet = new HashSet<>();
120 reusedDefSet.add(Rfc6020Mapping.TYPEDEF);
122 StatementDefinition def = stmtContext.getPublicDefinition();
124 return reusedDefSet.contains(def);
127 public static StatementContextBase<?, ?, ?> getAugmentTargetCtx(
128 final Mutable<SchemaNodeIdentifier, AugmentStatement, EffectiveStatement<SchemaNodeIdentifier, AugmentStatement>> augmentNode) {
130 final SchemaNodeIdentifier augmentTargetNode = augmentNode.getStatementArgument();
132 List<StatementContextBase<?, ?, ?>> rootStatementCtxList = new LinkedList<>();
134 if (augmentTargetNode.isAbsolute()) {
137 if (augmentTargetNode != null) {
138 module = augmentTargetNode.getPathFromRoot().iterator().next().getModule();
140 throw new IllegalArgumentException(
141 "Augment argument null, something bad happened in some of previous parsing phases");
144 StatementContextBase<?, ?, ?> rootStatementCtx = (StatementContextBase<?, ?, ?>) augmentNode.getFromNamespace(
145 NamespaceToModule.class, module);
146 rootStatementCtxList.add(rootStatementCtx);
148 final Map<?, ?> subModules = rootStatementCtx.getAllFromNamespace(IncludedModuleContext.class);
149 if (subModules != null) {
150 rootStatementCtxList.addAll((Collection<? extends StatementContextBase<?, ?, ?>>) subModules.values());
154 StatementContextBase<?, ?, ?> parent = (StatementContextBase<?, ?, ?>) augmentNode.getParentContext();
155 if (StmtContextUtils.producesDeclared(parent, UsesStatement.class)) {
156 rootStatementCtxList.add(parent.getParentContext());
162 List<QName> augmentTargetPath = new LinkedList<>();
164 augmentTargetPath.addAll((Collection<? extends QName>) augmentTargetNode.getPathFromRoot());
166 StatementContextBase<?, ?, ?> augmentTargetCtx = null;
167 for (final StatementContextBase<?, ?, ?> rootStatementCtx : rootStatementCtxList) {
168 augmentTargetCtx = Utils.findCtxOfNodeInRoot(rootStatementCtx,
170 if (augmentTargetCtx != null) break;
174 if (augmentTargetCtx == null) {
176 throw new NullPointerException(String.format(
177 "Augment path %s not found in target model so its resulting context is null",
178 augmentNode.rawStatementArgument()));
182 return augmentTargetCtx;