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;
14 import org.opendaylight.yangtools.yang.common.QName;
15 import org.opendaylight.yangtools.yang.common.QNameModule;
16 import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
17 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
18 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
19 import org.opendaylight.yangtools.yang.model.api.stmt.AugmentStatement;
20 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
21 import org.opendaylight.yangtools.yang.parser.spi.NamespaceToModule;
22 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
23 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
24 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleNameToModuleQName;
25 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
26 import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase;
28 public final class AugmentUtils {
30 private AugmentUtils() {
33 private static final String REGEX_PATH_REL1 = "\\.\\.?\\s*/(.+)";
34 private static final String REGEX_PATH_REL2 = "//.*";
36 public static Iterable<QName> parseAugmentPath(StmtContext<?, ?, ?> ctx, String path) {
38 if (path.matches(REGEX_PATH_REL1) || path.matches(REGEX_PATH_REL2)) {
39 throw new IllegalArgumentException(
40 "An argument for augment can be only absolute path; or descendant if used in uses");
43 return Utils.parseXPath(ctx, path);
46 public static void copyFromSourceToTarget(StatementContextBase<?, ?, ?> sourceCtx,
47 StatementContextBase<?, ?, ?> targetCtx) throws SourceException {
49 QNameModule newQNameModule = getNewQNameModule(targetCtx, sourceCtx);
50 copyDeclaredStmts(sourceCtx, targetCtx, newQNameModule);
51 copyEffectiveStmts(sourceCtx, targetCtx, newQNameModule);
55 public static void copyDeclaredStmts(StatementContextBase<?, ?, ?> sourceCtx,
56 StatementContextBase<?, ?, ?> targetCtx, QNameModule newQNameModule) throws SourceException {
57 Collection<? extends StatementContextBase<?, ?, ?>> declaredSubstatements = sourceCtx.declaredSubstatements();
58 for (StatementContextBase<?, ?, ?> originalStmtCtx : declaredSubstatements) {
59 if (needToCopyByAugment(originalStmtCtx)) {
60 StatementContextBase<?, ?, ?> copy = originalStmtCtx.createCopy(newQNameModule, targetCtx);
61 targetCtx.addEffectiveSubstatement(copy);
62 } else if (isReusedByAugment(originalStmtCtx)) {
63 targetCtx.addEffectiveSubstatement(originalStmtCtx);
68 public static void copyEffectiveStmts(StatementContextBase<?, ?, ?> sourceCtx,
69 StatementContextBase<?, ?, ?> targetCtx, QNameModule newQNameModule) throws SourceException {
70 Collection<? extends StatementContextBase<?, ?, ?>> effectiveSubstatements = sourceCtx.effectiveSubstatements();
71 for (StatementContextBase<?, ?, ?> originalStmtCtx : effectiveSubstatements) {
72 if (needToCopyByAugment(originalStmtCtx)) {
73 StatementContextBase<?, ?, ?> copy = originalStmtCtx.createCopy(newQNameModule, targetCtx);
74 targetCtx.addEffectiveSubstatement(copy);
75 } else if (isReusedByAugment(originalStmtCtx)) {
76 targetCtx.addEffectiveSubstatement(originalStmtCtx);
81 public static QNameModule getNewQNameModule(StatementContextBase<?, ?, ?> targetCtx,
82 StatementContextBase<?, ?, ?> sourceCtx) {
83 Object targetStmtArgument = targetCtx.getStatementArgument();
85 final StatementContextBase<?, ?, ?> root = sourceCtx.getRoot();
86 final String moduleName = (String) root.getStatementArgument();
87 final QNameModule sourceQNameModule = root.getFromNamespace(ModuleNameToModuleQName.class, moduleName);
89 if (targetStmtArgument instanceof QName) {
90 QName targetQName = (QName) targetStmtArgument;
91 QNameModule targetQNameModule = targetQName.getModule();
93 if (targetQNameModule.equals(sourceQNameModule)) {
96 return targetQNameModule;
103 public static boolean needToCopyByAugment(StmtContext<?, ?, ?> stmtContext) {
105 Set<StatementDefinition> noCopyDefSet = new HashSet<>();
106 noCopyDefSet.add(Rfc6020Mapping.USES);
108 StatementDefinition def = stmtContext.getPublicDefinition();
109 return (!noCopyDefSet.contains(def));
112 public static boolean isReusedByAugment(StmtContext<?, ?, ?> stmtContext) {
114 HashSet<StatementDefinition> reusedDefSet = new HashSet<>();
115 reusedDefSet.add(Rfc6020Mapping.TYPEDEF);
117 StatementDefinition def = stmtContext.getPublicDefinition();
118 if (reusedDefSet.contains(def))
124 public static StatementContextBase<?, ?, ?> getAugmentTargetCtx(
125 final Mutable<SchemaNodeIdentifier, AugmentStatement, EffectiveStatement<SchemaNodeIdentifier, AugmentStatement>> augmentNode) {
127 final SchemaNodeIdentifier augmentTargetPath = augmentNode.getStatementArgument();
130 if (augmentTargetPath != null) {
131 module = augmentTargetPath.getPathFromRoot().iterator().next().getModule();
133 throw new IllegalArgumentException(
134 "Augment argument null, something bad happened in some of previous parsing phases");
137 StatementContextBase<?, ?, ?> rootStatementCtx = (StatementContextBase<?, ?, ?>) augmentNode.getFromNamespace(
138 NamespaceToModule.class, module);
140 final StatementContextBase<?, ?, ?> augmentTargetCtx = Utils.findCtxOfNodeInRoot(rootStatementCtx,
143 if (augmentTargetCtx == null) {
145 throw new NullPointerException(String.format(
146 "Augment path %s not found in target model so its resulting context is null",
147 augmentNode.rawStatementArgument()));
151 return augmentTargetCtx;