66cfd1d51ed332f91a9446f4c67e415195d55bfa
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / rfc6020 / AugmentUtils.java
1 /**
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  * <p/>
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
7  */
8 package org.opendaylight.yangtools.yang.parser.stmt.rfc6020;
9
10 import java.util.Collection;
11 import java.util.HashSet;
12
13 import org.opendaylight.yangtools.yang.common.QName;
14 import org.opendaylight.yangtools.yang.common.QNameModule;
15 import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
16 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
17 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
18 import org.opendaylight.yangtools.yang.model.api.stmt.AugmentStatement;
19 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
20 import org.opendaylight.yangtools.yang.parser.spi.NamespaceToModule;
21 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
22 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
23 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleNameToModuleQName;
24 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
25 import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase;
26
27 public class AugmentUtils {
28
29     private static final String REGEX_PATH_REL1 = "\\.\\.?\\s*/(.+)";
30     private static final String REGEX_PATH_REL2 = "//.*";
31
32     public static Iterable<QName> parseAugmentPath(StmtContext<?, ?, ?> ctx, String path) {
33
34         if (path.matches(REGEX_PATH_REL1) || path.matches(REGEX_PATH_REL2)) {
35             throw new IllegalArgumentException(
36                     "An argument for augment can be only absolute path; or descendant if used in uses");
37         }
38
39         return Utils.parseXPath(ctx, path);
40     }
41
42     public static void copyFromSourceToTarget(StatementContextBase<?, ?, ?> sourceCtx,
43             StatementContextBase<?, ?, ?> targetCtx) throws SourceException {
44
45         QNameModule newQNameModule = getNewQNameModule(targetCtx, sourceCtx);
46         copyDeclaredStmts(sourceCtx, targetCtx, newQNameModule);
47         copyEffectiveStmts(sourceCtx, targetCtx, newQNameModule);
48
49     }
50
51     public static void copyDeclaredStmts(StatementContextBase<?, ?, ?> sourceCtx,
52             StatementContextBase<?, ?, ?> targetCtx, QNameModule newQNameModule) throws SourceException {
53         Collection<? extends StatementContextBase<?, ?, ?>> declaredSubstatements = sourceCtx.declaredSubstatements();
54         for (StatementContextBase<?, ?, ?> originalStmtCtx : declaredSubstatements) {
55             if (needToCopyByAugment(originalStmtCtx)) {
56                 StatementContextBase<?, ?, ?> copy = originalStmtCtx.createCopy(newQNameModule, targetCtx);
57                 targetCtx.addEffectiveSubstatement(copy);
58             } else if (isReusedByAugment(originalStmtCtx)) {
59                 targetCtx.addEffectiveSubstatement(originalStmtCtx);
60             }
61         }
62     }
63
64     public static void copyEffectiveStmts(StatementContextBase<?, ?, ?> sourceCtx,
65             StatementContextBase<?, ?, ?> targetCtx, QNameModule newQNameModule) throws SourceException {
66         Collection<? extends StatementContextBase<?, ?, ?>> effectiveSubstatements = sourceCtx.effectiveSubstatements();
67         for (StatementContextBase<?, ?, ?> originalStmtCtx : effectiveSubstatements) {
68             if (needToCopyByAugment(originalStmtCtx)) {
69                 StatementContextBase<?, ?, ?> copy = originalStmtCtx.createCopy(newQNameModule, targetCtx);
70                 targetCtx.addEffectiveSubstatement(copy);
71             } else if (isReusedByAugment(originalStmtCtx)) {
72                 targetCtx.addEffectiveSubstatement(originalStmtCtx);
73             }
74         }
75     }
76
77     public static QNameModule getNewQNameModule(StatementContextBase<?, ?, ?> targetCtx,
78             StatementContextBase<?, ?, ?> sourceCtx) {
79         Object targetStmtArgument = targetCtx.getStatementArgument();
80
81         final StatementContextBase<?, ?, ?> root = sourceCtx.getRoot();
82         final String moduleName = (String) root.getStatementArgument();
83         final QNameModule sourceQNameModule = root.getFromNamespace(ModuleNameToModuleQName.class, moduleName);
84
85         if (targetStmtArgument instanceof QName) {
86             QName targetQName = (QName) targetStmtArgument;
87             QNameModule targetQNameModule = targetQName.getModule();
88
89             if (targetQNameModule.equals(sourceQNameModule))
90                 return null;
91             else
92                 return targetQNameModule;
93         } else
94             return null;
95     }
96
97     public static boolean needToCopyByAugment(StmtContext<?, ?, ?> stmtContext) {
98
99         HashSet<StatementDefinition> noCopyDefSet = new HashSet<>();
100         noCopyDefSet.add(Rfc6020Mapping.USES);
101
102         StatementDefinition def = stmtContext.getPublicDefinition();
103         if (noCopyDefSet.contains(def))
104             return false;
105         else
106             return true;
107     }
108
109     public static boolean isReusedByAugment(StmtContext<?, ?, ?> stmtContext) {
110
111         HashSet<StatementDefinition> reusedDefSet = new HashSet<>();
112         reusedDefSet.add(Rfc6020Mapping.TYPEDEF);
113
114         StatementDefinition def = stmtContext.getPublicDefinition();
115         if (reusedDefSet.contains(def))
116             return true;
117         else
118             return false;
119     }
120
121     public static StatementContextBase<?, ?, ?> getAugmentTargetCtx(
122             final Mutable<SchemaNodeIdentifier, AugmentStatement, EffectiveStatement<SchemaNodeIdentifier, AugmentStatement>> augmentNode) {
123
124         final SchemaNodeIdentifier augmentTargetPath = augmentNode.getStatementArgument();
125
126         QNameModule module;
127         if (augmentTargetPath != null) {
128             module = augmentTargetPath.getPathFromRoot().iterator().next().getModule();
129         } else {
130             throw new IllegalArgumentException(
131                     "Augment argument null, something bad happened in some of previous parsing phases");
132         }
133
134         StatementContextBase<?, ?, ?> rootStatementCtx = (StatementContextBase<?, ?, ?>) augmentNode.getFromNamespace(
135                 NamespaceToModule.class, module);
136
137         final StatementContextBase<?, ?, ?> augmentTargetCtx = Utils.findCtxOfNodeInRoot(rootStatementCtx,
138                 augmentTargetPath);
139
140         if (augmentTargetCtx == null) {
141
142             throw new NullPointerException(String.format(
143                     "Augment path %s not found in target model so its resulting context is null",
144                     augmentNode.rawStatementArgument()));
145
146         }
147
148         return augmentTargetCtx;
149     }
150 }