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 org.opendaylight.yangtools.yang.parser.spi.source.ModuleCtxToModuleQName;
12 import org.opendaylight.yangtools.yang.parser.stmt.reactor.RootStatementContext;
13 import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace.ValidationBundleType;
14 import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace;
15 import java.util.Iterator;
16 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
17 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.TypeOfCopy;
18 import java.util.Collection;
19 import java.util.HashSet;
21 import org.opendaylight.yangtools.yang.common.QName;
22 import org.opendaylight.yangtools.yang.common.QNameModule;
23 import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
24 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
25 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
26 import org.opendaylight.yangtools.yang.model.api.stmt.RefineStatement;
27 import org.opendaylight.yangtools.yang.model.api.stmt.UsesStatement;
28 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
29 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
30 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
31 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
32 import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase;
34 public final class GroupingUtils {
36 private GroupingUtils() {
40 * @param sourceGrpStmtCtx
42 * @throws SourceException
44 public static void copyFromSourceToTarget(
45 StatementContextBase<?, ?, ?> sourceGrpStmtCtx,
46 StatementContextBase<?, ?, ?> targetCtx,
47 StmtContext.Mutable<QName, UsesStatement, EffectiveStatement<QName, UsesStatement>> usesNode)
48 throws SourceException {
50 QNameModule newQNameModule = getNewQNameModule(targetCtx,
52 copyDeclaredStmts(sourceGrpStmtCtx, targetCtx, usesNode, newQNameModule);
53 copyEffectiveStmts(sourceGrpStmtCtx, targetCtx, usesNode,
58 public static void copyDeclaredStmts(
59 StatementContextBase<?, ?, ?> sourceGrpStmtCtx,
60 StatementContextBase<?, ?, ?> targetCtx,
61 StmtContext.Mutable<QName, UsesStatement, EffectiveStatement<QName, UsesStatement>> usesNode,
62 QNameModule newQNameModule) throws SourceException {
63 Collection<? extends StatementContextBase<?, ?, ?>> declaredSubstatements = sourceGrpStmtCtx
64 .declaredSubstatements();
65 for (StatementContextBase<?, ?, ?> originalStmtCtx : declaredSubstatements) {
66 if (needToCopyByUses(originalStmtCtx)) {
67 StatementContextBase<?, ?, ?> copy = originalStmtCtx
68 .createCopy(newQNameModule, targetCtx,
69 TypeOfCopy.ADDED_BY_USES);
70 targetCtx.addEffectiveSubstatement(copy);
71 usesNode.addAsEffectOfStatement(copy);
72 } else if (isReusedByUses(originalStmtCtx)) {
73 targetCtx.addEffectiveSubstatement(originalStmtCtx);
74 usesNode.addAsEffectOfStatement(originalStmtCtx);
79 public static void copyEffectiveStmts(
80 StatementContextBase<?, ?, ?> sourceGrpStmtCtx,
81 StatementContextBase<?, ?, ?> targetCtx,
82 StmtContext.Mutable<QName, UsesStatement, EffectiveStatement<QName, UsesStatement>> usesNode,
83 QNameModule newQNameModule) throws SourceException {
84 Collection<? extends StatementContextBase<?, ?, ?>> effectiveSubstatements = sourceGrpStmtCtx
85 .effectiveSubstatements();
86 for (StatementContextBase<?, ?, ?> originalStmtCtx : effectiveSubstatements) {
87 if (needToCopyByUses(originalStmtCtx)) {
88 StatementContextBase<?, ?, ?> copy = originalStmtCtx
89 .createCopy(newQNameModule, targetCtx,
90 TypeOfCopy.ADDED_BY_USES);
91 targetCtx.addEffectiveSubstatement(copy);
92 usesNode.addAsEffectOfStatement(copy);
93 } else if (isReusedByUses(originalStmtCtx)) {
94 targetCtx.addEffectiveSubstatement(originalStmtCtx);
95 usesNode.addAsEffectOfStatement(originalStmtCtx);
100 public static QNameModule getNewQNameModule(
101 StatementContextBase<?, ?, ?> targetCtx,
102 StmtContext<?, ?, ?> stmtContext) {
103 if (needToCreateNewQName(stmtContext.getPublicDefinition())) {
104 if (targetCtx.isRootContext()) {
105 return targetCtx.getFromNamespace(
106 ModuleCtxToModuleQName.class,
109 if(targetCtx.getPublicDefinition() == Rfc6020Mapping.AUGMENT) {
110 RootStatementContext<?, ?, ?> root = targetCtx.getRoot();
111 return targetCtx.getFromNamespace(
112 ModuleCtxToModuleQName.class,
116 Object targetStmtArgument = targetCtx.getStatementArgument();
117 Object sourceStmtArgument = stmtContext.getStatementArgument();
118 if (targetStmtArgument instanceof QName
119 && sourceStmtArgument instanceof QName) {
120 QName targetQName = (QName) targetStmtArgument;
121 QNameModule targetQNameModule = targetQName.getModule();
123 QName sourceQName = (QName) sourceStmtArgument;
124 QNameModule sourceQNameModule = sourceQName.getModule();
126 if (targetQNameModule.equals(sourceQNameModule)) {
129 return targetQNameModule;
139 public static boolean needToCreateNewQName(
140 StatementDefinition publicDefinition) {
144 public static boolean needToCopyByUses(StmtContext<?, ?, ?> stmtContext) {
146 Set<StatementDefinition> noCopyDefSet = new HashSet<>();
147 noCopyDefSet.add(Rfc6020Mapping.USES);
148 noCopyDefSet.add(Rfc6020Mapping.TYPEDEF);
149 noCopyDefSet.add(Rfc6020Mapping.TYPE);
151 StatementDefinition def = stmtContext.getPublicDefinition();
152 return !noCopyDefSet.contains(def);
155 public static boolean isReusedByUses(StmtContext<?, ?, ?> stmtContext) {
157 Set<StatementDefinition> reusedDefSet = new HashSet<>();
158 reusedDefSet.add(Rfc6020Mapping.TYPEDEF);
159 reusedDefSet.add(Rfc6020Mapping.TYPE);
161 StatementDefinition def = stmtContext.getPublicDefinition();
162 return reusedDefSet.contains(def);
165 public static void resolveUsesNode(
166 Mutable<QName, UsesStatement, EffectiveStatement<QName, UsesStatement>> usesNode,
167 StatementContextBase<?, ?, ?> targetNodeStmtCtx)
168 throws SourceException {
170 Collection<StatementContextBase<?, ?, ?>> declaredSubstatements = usesNode
171 .declaredSubstatements();
172 for (StatementContextBase<?, ?, ?> subStmtCtx : declaredSubstatements) {
173 if (StmtContextUtils.producesDeclared(subStmtCtx,
174 RefineStatement.class)) {
175 performRefine(subStmtCtx, targetNodeStmtCtx);
180 private static void performRefine(StatementContextBase<?, ?, ?> refineCtx,
181 StatementContextBase<?, ?, ?> usesParentCtx) {
183 Object refineArgument = refineCtx.getStatementArgument();
185 SchemaNodeIdentifier refineTargetNodeIdentifier;
186 if (refineArgument instanceof SchemaNodeIdentifier) {
187 refineTargetNodeIdentifier = (SchemaNodeIdentifier) refineArgument;
189 throw new IllegalArgumentException(
190 "Invalid refine argument. It must be instance of SchemaNodeIdentifier");
193 StatementContextBase<?, ?, ?> refineTargetNodeCtx = Utils.findNode(
194 usesParentCtx, refineTargetNodeIdentifier);
196 if (refineTargetNodeCtx == null) {
197 throw new IllegalArgumentException(
198 "Refine target node not found. Path: "
199 + refineTargetNodeIdentifier);
202 addOrReplaceNodes(refineCtx, refineTargetNodeCtx);
203 refineCtx.addAsEffectOfStatement(refineTargetNodeCtx);
207 private static void addOrReplaceNodes(
208 StatementContextBase<?, ?, ?> refineCtx,
209 StatementContextBase<?, ?, ?> refineTargetNodeCtx) {
211 Collection<StatementContextBase<?, ?, ?>> declaredSubstatements = refineCtx
212 .declaredSubstatements();
213 for (StatementContextBase<?, ?, ?> refineSubstatementCtx : declaredSubstatements) {
214 if (isSupportedRefineSubstatement(refineSubstatementCtx)) {
215 addOrReplaceNode(refineSubstatementCtx, refineTargetNodeCtx);
220 private static void addOrReplaceNode(
221 StatementContextBase<?, ?, ?> refineSubstatementCtx,
222 StatementContextBase<?, ?, ?> refineTargetNodeCtx) {
224 StatementDefinition refineSubstatementDef = refineSubstatementCtx
225 .getPublicDefinition();
226 StatementDefinition refineTargetNodeDef = refineTargetNodeCtx
227 .getPublicDefinition();
229 if (!isSupportedRefineTarget(refineSubstatementCtx, refineTargetNodeCtx)) {
230 throw new SourceException("Error in module '"
231 + refineSubstatementCtx.getRoot().getStatementArgument()
232 + "' in the refine of uses '"
233 + refineSubstatementCtx.getParentContext()
234 .getStatementArgument()
235 + "': can not perform refine of '"
236 + refineSubstatementCtx.getPublicDefinition()
237 + "' for the target '"
238 + refineTargetNodeCtx.getPublicDefinition() + "'.",
239 refineSubstatementCtx.getStatementSourceReference());
242 if (isAllowedToAddByRefine(refineSubstatementDef)) {
243 refineTargetNodeCtx.addEffectiveSubstatement(refineSubstatementCtx);
245 refineTargetNodeCtx.removeStatementFromEffectiveSubstatements(refineSubstatementDef);
246 refineTargetNodeCtx.addEffectiveSubstatement(refineSubstatementCtx);
250 private static boolean isAllowedToAddByRefine(
251 StatementDefinition publicDefinition) {
252 Set<StatementDefinition> allowedToAddByRefineDefSet = new HashSet<>();
253 allowedToAddByRefineDefSet.add(Rfc6020Mapping.MUST);
255 return allowedToAddByRefineDefSet.contains(publicDefinition);
258 private static boolean isSupportedRefineSubstatement(
259 StatementContextBase<?, ?, ?> refineSubstatementCtx) {
261 Collection<?> supportedRefineSubstatements = refineSubstatementCtx
262 .getFromNamespace(ValidationBundlesNamespace.class,
263 ValidationBundleType.SUPPORTED_REFINE_SUBSTATEMENTS);
265 return supportedRefineSubstatements == null
266 || supportedRefineSubstatements.isEmpty()
267 || supportedRefineSubstatements.contains(refineSubstatementCtx
268 .getPublicDefinition())
269 || StmtContextUtils.isUnknownStatement(refineSubstatementCtx);
272 private static boolean isSupportedRefineTarget(
273 StatementContextBase<?, ?, ?> refineSubstatementCtx,
274 StatementContextBase<?, ?, ?> refineTargetNodeCtx) {
276 Collection<?> supportedRefineTargets = YangValidationBundles.SUPPORTED_REFINE_TARGETS
277 .get(refineSubstatementCtx.getPublicDefinition());
279 return supportedRefineTargets == null
280 || supportedRefineTargets.isEmpty()
281 || supportedRefineTargets.contains(refineTargetNodeCtx
282 .getPublicDefinition());