BUG-6522: create a specialized CopyHistory object
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / reactor / RootStatementContext.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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.reactor;
9
10 import com.google.common.base.Optional;
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.Map;
14 import javax.annotation.Nullable;
15 import org.opendaylight.yangtools.yang.common.QNameModule;
16 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
17 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
18 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
19 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
20 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.NamespaceStorageNode;
21 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.Registry;
22 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.StorageNodeType;
23 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
24 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
25 import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
26 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.IncludedModuleContext;
27
28 /**
29  * root statement class for a Yang source
30  */
31 public class RootStatementContext<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>> extends
32         StatementContextBase<A, D, E> {
33
34     private final SourceSpecificContext sourceContext;
35     private final Collection<NamespaceStorageNode> includedContexts = new ArrayList<>();
36     private final A argument;
37
38     RootStatementContext(final ContextBuilder<A, D, E> builder, final SourceSpecificContext sourceContext) {
39         super(builder);
40         this.sourceContext = sourceContext;
41         this.argument = builder.getDefinition().parseArgumentValue(this, builder.getRawArgument());
42     }
43
44     RootStatementContext(final RootStatementContext<A, D, E> original, final QNameModule newQNameModule,
45         final CopyType typeOfCopy) {
46         super(original);
47
48         sourceContext = original.sourceContext;
49         this.argument = original.argument;
50
51         copyDeclaredStmts(original, newQNameModule, typeOfCopy);
52
53         copyEffectiveStmts(original, newQNameModule, typeOfCopy);
54
55     }
56
57     /**
58      * copies declared statements from original to this' substatements
59      *
60      * @param typeOfCopy
61      *            determines whether copy is used by augmentation or uses
62      * @throws org.opendaylight.yangtools.yang.parser.spi.source.SourceException
63      */
64     private void copyDeclaredStmts(final RootStatementContext<A, D, E> original, final QNameModule newQNameModule,
65             final CopyType typeOfCopy) {
66         final Collection<StatementContextBase<?, ?, ?>> originalDeclaredSubstatements = original.declaredSubstatements();
67         for (final StatementContextBase<?, ?, ?> stmtContext : originalDeclaredSubstatements) {
68             if (!StmtContextUtils.areFeaturesSupported(stmtContext)) {
69                 continue;
70             }
71             this.addEffectiveSubstatement(stmtContext.createCopy(newQNameModule, this, typeOfCopy));
72         }
73     }
74
75     /**
76      * copies effective statements from original to this' substatements
77      *
78      * @param typeOfCopy
79      *            determines whether copy is used by augmentation or uses
80      * @throws org.opendaylight.yangtools.yang.parser.spi.source.SourceException
81      */
82     private void copyEffectiveStmts(final RootStatementContext<A, D, E> original, final QNameModule newQNameModule,
83             final CopyType typeOfCopy) {
84         final Collection<? extends StmtContext<?, ?, ?>> originalEffectiveSubstatements = original.effectiveSubstatements();
85         for (final StmtContext<?, ?, ?> stmtContext : originalEffectiveSubstatements) {
86             this.addEffectiveSubstatement(stmtContext.createCopy(newQNameModule, this, typeOfCopy));
87         }
88     }
89
90     /**
91      * @return null as root cannot have parent
92      */
93     @Override
94     public StatementContextBase<?, ?, ?> getParentContext() {
95         return null;
96     }
97
98     /**
99      * @return namespace storage of source context
100      */
101     @Override
102     public NamespaceStorageNode getParentNamespaceStorage() {
103         return sourceContext;
104     }
105
106     /**
107      * @return registry of source context
108      */
109     @Override
110     public Registry getBehaviourRegistry() {
111         return sourceContext;
112     }
113
114     @Override
115     public StorageNodeType getStorageNodeType() {
116         return StorageNodeType.ROOT_STATEMENT_LOCAL;
117     }
118     /**
119      * @return this as its own root
120      */
121     @Override
122     public RootStatementContext<?, ?, ?> getRoot() {
123         return this;
124     }
125
126     SourceSpecificContext getSourceContext() {
127         return sourceContext;
128     }
129
130     @Override
131     public A getStatementArgument() {
132         return argument;
133     }
134
135     /**
136      * @return copy of this considering {@link CopyType} (augment, uses)
137      *
138      * @throws org.opendaylight.yangtools.yang.parser.spi.source.SourceException instance of SourceException
139      */
140     @Override
141     public StatementContextBase<?, ?, ?> createCopy(final StatementContextBase<?, ?, ?> newParent,
142             final CopyType typeOfCopy) {
143         return createCopy(null, newParent, typeOfCopy);
144     }
145
146     /**
147      * @return copy of this considering {@link CopyType} (augment, uses)
148      *
149      * @throws org.opendaylight.yangtools.yang.parser.spi.source.SourceException instance of SourceException
150      */
151     @Override
152     public StatementContextBase<A, D, E> createCopy(final QNameModule newQNameModule,
153             final StatementContextBase<?, ?, ?> newParent, final CopyType typeOfCopy) {
154         final RootStatementContext<A, D, E> copy = new RootStatementContext<>(this, newQNameModule, typeOfCopy);
155
156         copy.appendCopyHistory(typeOfCopy, this.getCopyHistory());
157
158         if (this.getOriginalCtx() != null) {
159             copy.setOriginalCtx(this.getOriginalCtx());
160         } else {
161             copy.setOriginalCtx(this);
162         }
163         definition().onStatementAdded(copy);
164         return copy;
165     }
166
167     @Override
168     public Optional<SchemaPath> getSchemaPath() {
169         return Optional.of(SchemaPath.ROOT);
170     }
171
172     /**
173      * @return true
174      */
175     @Override
176     public boolean isRootContext() {
177         return true;
178     }
179
180     @Override
181     public boolean isConfiguration() {
182         return true;
183     }
184
185     @Override
186     public boolean isEnabledSemanticVersioning() {
187         return sourceContext.isEnabledSemanticVersioning();
188     }
189
190     @Override
191     public <K, V, N extends IdentifierNamespace<K, V>> void addToLocalStorage(final Class<N> type, final K key,
192             final V value) {
193         if (IncludedModuleContext.class.isAssignableFrom(type)) {
194             includedContexts.add((NamespaceStorageNode) value);
195         }
196         super.addToLocalStorage(type, key, value);
197     }
198
199     @Override
200     public <K, V, N extends IdentifierNamespace<K, V>> V getFromLocalStorage(final Class<N> type, final K key) {
201         final V potentialLocal = super.getFromLocalStorage(type, key);
202         if (potentialLocal != null) {
203             return potentialLocal;
204         }
205         for (final NamespaceStorageNode includedSource : includedContexts) {
206             final V potential = includedSource.getFromLocalStorage(type, key);
207             if (potential != null) {
208                 return potential;
209             }
210         }
211         return null;
212     }
213
214     @Nullable
215     @Override
216     public <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromLocalStorage(final Class<N> type) {
217         final Map<K, V> potentialLocal = super.getAllFromLocalStorage(type);
218         if (potentialLocal != null) {
219             return potentialLocal;
220         }
221         for (final NamespaceStorageNode includedSource : includedContexts) {
222             final Map<K, V> potential = includedSource.getAllFromLocalStorage(type);
223             if (potential != null) {
224                 return potential;
225             }
226         }
227         return null;
228     }
229 }