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.Iterator;
11 import javax.annotation.Nullable;
13 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.TypeOfCopy;
14 import java.util.Collection;
15 import java.util.HashSet;
16 import java.util.LinkedList;
17 import java.util.List;
20 import org.opendaylight.yangtools.yang.common.QName;
21 import org.opendaylight.yangtools.yang.common.QNameModule;
22 import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
23 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
24 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
25 import org.opendaylight.yangtools.yang.model.api.stmt.AugmentStatement;
26 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
27 import org.opendaylight.yangtools.yang.model.api.stmt.UsesStatement;
28 import org.opendaylight.yangtools.yang.parser.spi.NamespaceToModule;
29 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
30 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
31 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
32 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleNameToModuleQName;
33 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
34 import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase;
36 public final class AugmentUtils {
38 private static final String REGEX_PATH_REL1 = "\\.\\.?\\s*/(.+)";
39 private static final String REGEX_PATH_REL2 = "//.*";
41 private AugmentUtils() {
44 public static Iterable<QName> parseAugmentPath(StmtContext<?, ?, ?> ctx,
47 if (path.matches(REGEX_PATH_REL1) || path.matches(REGEX_PATH_REL2)) {
48 throw new IllegalArgumentException(
49 "An argument for augment can be only absolute path; or descendant if used in uses");
52 return Utils.parseXPath(ctx, path);
55 public static void copyFromSourceToTarget(
56 StatementContextBase<?, ?, ?> sourceCtx,
57 StatementContextBase<?, ?, ?> targetCtx) throws SourceException {
59 QNameModule newQNameModule = getNewQNameModule(targetCtx, sourceCtx);
60 copyDeclaredStmts(sourceCtx, targetCtx, newQNameModule);
61 copyEffectiveStmts(sourceCtx, targetCtx, newQNameModule);
65 public static void copyDeclaredStmts(
66 StatementContextBase<?, ?, ?> sourceCtx,
67 StatementContextBase<?, ?, ?> targetCtx, QNameModule newQNameModule)
68 throws SourceException {
69 Collection<? extends StatementContextBase<?, ?, ?>> declaredSubstatements = sourceCtx
70 .declaredSubstatements();
71 for (StatementContextBase<?, ?, ?> originalStmtCtx : declaredSubstatements) {
72 if (needToCopyByAugment(originalStmtCtx)) {
73 StatementContextBase<?, ?, ?> copy = originalStmtCtx
74 .createCopy(newQNameModule, targetCtx,
75 TypeOfCopy.ADDED_BY_AUGMENTATION);
76 targetCtx.addEffectiveSubstatement(copy);
77 } else if (isReusedByAugment(originalStmtCtx)) {
78 targetCtx.addEffectiveSubstatement(originalStmtCtx);
83 public static void copyEffectiveStmts(
84 StatementContextBase<?, ?, ?> sourceCtx,
85 StatementContextBase<?, ?, ?> targetCtx, QNameModule newQNameModule)
86 throws SourceException {
87 Collection<? extends StatementContextBase<?, ?, ?>> effectiveSubstatements = sourceCtx
88 .effectiveSubstatements();
89 for (StatementContextBase<?, ?, ?> originalStmtCtx : effectiveSubstatements) {
90 if (needToCopyByAugment(originalStmtCtx)) {
91 StatementContextBase<?, ?, ?> copy = originalStmtCtx
92 .createCopy(newQNameModule, targetCtx,
93 TypeOfCopy.ADDED_BY_AUGMENTATION);
94 targetCtx.addEffectiveSubstatement(copy);
95 } else if (isReusedByAugment(originalStmtCtx)) {
96 targetCtx.addEffectiveSubstatement(originalStmtCtx);
101 public static QNameModule getNewQNameModule(
102 StatementContextBase<?, ?, ?> targetCtx,
103 StatementContextBase<?, ?, ?> sourceCtx) {
104 Object targetStmtArgument = targetCtx.getStatementArgument();
106 final StatementContextBase<?, ?, ?> root = sourceCtx.getRoot();
107 final String moduleName = (String) root.getStatementArgument();
108 final QNameModule sourceQNameModule = root.getFromNamespace(
109 ModuleNameToModuleQName.class, moduleName);
111 if (targetStmtArgument instanceof QName) {
112 QName targetQName = (QName) targetStmtArgument;
113 QNameModule targetQNameModule = targetQName.getModule();
115 if (targetQNameModule.equals(sourceQNameModule)) {
118 return targetQNameModule;
125 public static boolean needToCopyByAugment(StmtContext<?, ?, ?> stmtContext) {
127 Set<StatementDefinition> noCopyDefSet = new HashSet<>();
128 noCopyDefSet.add(Rfc6020Mapping.USES);
130 StatementDefinition def = stmtContext.getPublicDefinition();
131 return !noCopyDefSet.contains(def);
134 public static boolean isReusedByAugment(StmtContext<?, ?, ?> stmtContext) {
136 Set<StatementDefinition> reusedDefSet = new HashSet<>();
137 reusedDefSet.add(Rfc6020Mapping.TYPEDEF);
139 StatementDefinition def = stmtContext.getPublicDefinition();
141 return reusedDefSet.contains(def);
144 public static StatementContextBase<?, ?, ?> getAugmentTargetCtx(
145 final Mutable<SchemaNodeIdentifier, AugmentStatement, EffectiveStatement<SchemaNodeIdentifier, AugmentStatement>> augmentNode) {
147 final SchemaNodeIdentifier augmentTargetNode = augmentNode
148 .getStatementArgument();
149 if (augmentTargetNode == null) {
150 throw new IllegalArgumentException(
151 "Augment argument null, something bad happened in some of previous parsing phases");
154 List<StatementContextBase<?, ?, ?>> rootStatementCtxList = new LinkedList<>();
156 if (augmentTargetNode.isAbsolute()) {
158 QNameModule module = augmentTargetNode.getPathFromRoot().iterator()
161 StatementContextBase<?, ?, ?> rootStatementCtx = (StatementContextBase<?, ?, ?>) augmentNode
162 .getFromNamespace(NamespaceToModule.class, module);
163 rootStatementCtxList.add(rootStatementCtx);
165 final Map<?, ?> subModules = rootStatementCtx
166 .getAllFromNamespace(IncludedModuleContext.class);
167 if (subModules != null) {
169 .addAll((Collection<? extends StatementContextBase<?, ?, ?>>) subModules
174 StatementContextBase<?, ?, ?> parent = (StatementContextBase<?, ?, ?>) augmentNode
176 if (StmtContextUtils.producesDeclared(parent, UsesStatement.class)) {
177 rootStatementCtxList.add(parent.getParentContext());
183 StatementContextBase<?, ?, ?> augmentTargetCtx = null;
184 for (final StatementContextBase<?, ?, ?> rootStatementCtx : rootStatementCtxList) {
185 augmentTargetCtx = findCtxOfNodeInRoot(rootStatementCtx,
187 if (augmentTargetCtx != null)
191 return augmentTargetCtx;
195 public static StatementContextBase<?, ?, ?> findCtxOfNodeInSubstatements(
196 StatementContextBase<?, ?, ?> rootStmtCtx,
197 final Iterable<QName> path) {
199 StatementContextBase<?, ?, ?> parent = rootStmtCtx;
201 Iterator<QName> pathIter = path.iterator();
202 while (pathIter.hasNext()) {
203 QName nextPathQName = pathIter.next();
204 StatementContextBase<?, ?, ?> foundSubstatement = getSubstatementByQName(
205 parent, nextPathQName);
207 if (foundSubstatement == null) {
210 if (!pathIter.hasNext()) {
211 return foundSubstatement;
214 parent = foundSubstatement;
220 public static StatementContextBase<?, ?, ?> getSubstatementByQName(
221 StatementContextBase<?, ?, ?> parent, QName nextPathQName) {
223 Collection<StatementContextBase<?, ?, ?>> declaredSubstatement = parent
224 .declaredSubstatements();
225 Collection<StatementContextBase<?, ?, ?>> effectiveSubstatement = parent
226 .effectiveSubstatements();
228 Collection<StatementContextBase<?, ?, ?>> allSubstatements = new LinkedList<>();
229 allSubstatements.addAll(declaredSubstatement);
230 allSubstatements.addAll(effectiveSubstatement);
232 for (StatementContextBase<?, ?, ?> substatement : allSubstatements) {
233 if (isAllowedAugmentTarget(substatement)
235 .equals(substatement.getStatementArgument())) {
243 public static boolean isAllowedAugmentTarget(
244 StatementContextBase<?, ?, ?> substatement) {
247 * :TODO Substatement must be allowed augment target type e.g.
248 * Container, etc... and must be not for example grouping, identity etc.
249 * It is problem in case when more than one substatements have the same
250 * QName, for example Grouping and Container are siblings and they have the
251 * same QName. We must find the Container and the Grouping must be ignored
252 * as disallowed augment target.
259 public static StatementContextBase<?, ?, ?> findCtxOfNodeInRoot(
260 StatementContextBase<?, ?, ?> rootStmtCtx,
261 final SchemaNodeIdentifier node) {
262 return findCtxOfNodeInSubstatements(rootStmtCtx, node.getPathFromRoot());