Bug 6877: [Yang 1.1] Allow multiple base identities
[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 com.google.common.base.Preconditions;
12 import com.google.common.base.Verify;
13 import com.google.common.collect.ImmutableList;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.Map;
17 import javax.annotation.Nonnull;
18 import javax.annotation.Nullable;
19 import org.opendaylight.yangtools.yang.common.QNameModule;
20 import org.opendaylight.yangtools.yang.common.YangVersion;
21 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
22 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
23 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
24 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
25 import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
26 import org.opendaylight.yangtools.yang.parser.spi.meta.MutableStatement;
27 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.NamespaceStorageNode;
28 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.Registry;
29 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.StorageNodeType;
30 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
31 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
32 import org.opendaylight.yangtools.yang.parser.spi.source.IncludedModuleContext;
33 import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
34
35 /**
36  * Root statement class for a YANG source. All statements defined in that YANG source are mapped underneath an instance
37  * of this class, hence recursive lookups from them cross this class.
38  */
39 public class RootStatementContext<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>> extends
40         StatementContextBase<A, D, E> {
41
42     public static final YangVersion DEFAULT_VERSION = YangVersion.VERSION_1;
43
44     private final SourceSpecificContext sourceContext;
45     private final A argument;
46
47     private YangVersion version;
48
49     /**
50      * References to RootStatementContext of submodules which are included in this source.
51      */
52     private Collection<RootStatementContext<?, ?, ?>> includedContexts = ImmutableList.of();
53
54     RootStatementContext(final SourceSpecificContext sourceContext, final StatementDefinitionContext<A, D, E> def,
55         final StatementSourceReference ref, final String rawArgument) {
56         super(def, ref, rawArgument);
57         this.sourceContext = Preconditions.checkNotNull(sourceContext);
58         this.argument = def.parseArgumentValue(this, rawArgument);
59     }
60
61     RootStatementContext(final SourceSpecificContext sourceContext, final StatementDefinitionContext<A, D, E> def,
62         final StatementSourceReference ref, final String rawArgument, final YangVersion version) {
63         this(sourceContext, def, ref, rawArgument);
64         this.setRootVersion(version);
65     }
66
67     RootStatementContext(final RootStatementContext<A, D, E> original, final QNameModule newQNameModule,
68         final CopyType typeOfCopy) {
69         super(original);
70
71         sourceContext = Preconditions.checkNotNull(original.sourceContext);
72         this.argument = original.argument;
73
74         final Collection<StatementContextBase<?, ?, ?>> declared = original.declaredSubstatements();
75         final Collection<StatementContextBase<?, ?, ?>> effective = original.effectiveSubstatements();
76         final Collection<StatementContextBase<?, ?, ?>> buffer = new ArrayList<>(declared.size() + effective.size());
77
78         for (final StatementContextBase<?, ?, ?> stmtContext : declared) {
79             if (StmtContextUtils.areFeaturesSupported(stmtContext)) {
80                 buffer.add(stmtContext.createCopy(newQNameModule, this, typeOfCopy));
81             }
82         }
83         for (final StmtContext<?, ?, ?> stmtContext : effective) {
84             buffer.add(stmtContext.createCopy(newQNameModule, this, typeOfCopy));
85         }
86
87         addEffectiveSubstatements(buffer);
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     @Override
107     public Registry getBehaviourRegistry() {
108         return sourceContext;
109     }
110
111     @Override
112     public StorageNodeType getStorageNodeType() {
113         return StorageNodeType.ROOT_STATEMENT_LOCAL;
114     }
115     /**
116      * @return this as its own root
117      */
118     @Nonnull
119     @Override
120     public RootStatementContext<?, ?, ?> getRoot() {
121         return this;
122     }
123
124     SourceSpecificContext getSourceContext() {
125         return sourceContext;
126     }
127
128     @Override
129     public A getStatementArgument() {
130         return argument;
131     }
132
133     /**
134      * @return copy of this considering {@link CopyType} (augment, uses)
135      *
136      * @throws org.opendaylight.yangtools.yang.parser.spi.source.SourceException instance of SourceException
137      */
138     @Override
139     public StatementContextBase<?, ?, ?> createCopy(final StatementContextBase<?, ?, ?> newParent,
140             final CopyType typeOfCopy) {
141         return createCopy(null, newParent, typeOfCopy);
142     }
143
144     /**
145      * @return copy of this considering {@link CopyType} (augment, uses)
146      *
147      * @throws org.opendaylight.yangtools.yang.parser.spi.source.SourceException instance of SourceException
148      */
149     @Override
150     public StatementContextBase<A, D, E> createCopy(final QNameModule newQNameModule,
151             final StatementContextBase<?, ?, ?> newParent, final CopyType typeOfCopy) {
152         final RootStatementContext<A, D, E> copy = new RootStatementContext<>(this, newQNameModule, typeOfCopy);
153
154         copy.appendCopyHistory(typeOfCopy, this.getCopyHistory());
155
156         if (this.getOriginalCtx() != null) {
157             copy.setOriginalCtx(this.getOriginalCtx());
158         } else {
159             copy.setOriginalCtx(this);
160         }
161         definition().onStatementAdded(copy);
162         return copy;
163     }
164
165     @Nonnull
166     @Override
167     public Optional<SchemaPath> getSchemaPath() {
168         return Optional.of(SchemaPath.ROOT);
169     }
170
171     /**
172      * @return true
173      */
174     @Override
175     public boolean isRootContext() {
176         return true;
177     }
178
179     @Override
180     public boolean isConfiguration() {
181         return true;
182     }
183
184     @Override
185     public boolean isEnabledSemanticVersioning() {
186         return sourceContext.isEnabledSemanticVersioning();
187     }
188
189     @Override
190     public <K, V, N extends IdentifierNamespace<K, V>> void addToLocalStorage(final Class<N> type, final K key,
191             final V value) {
192         if (IncludedModuleContext.class.isAssignableFrom(type)) {
193             if (includedContexts.isEmpty()) {
194                 includedContexts = new ArrayList<>(1);
195             }
196             Verify.verify(value instanceof RootStatementContext);
197             includedContexts.add((RootStatementContext<?, ?, ?>) value);
198         }
199         super.addToLocalStorage(type, key, value);
200     }
201
202     @Override
203     public <K, V, N extends IdentifierNamespace<K, V>> V getFromLocalStorage(final Class<N> type, final K key) {
204         final V potentialLocal = super.getFromLocalStorage(type, key);
205         if (potentialLocal != null) {
206             return potentialLocal;
207         }
208         for (final NamespaceStorageNode includedSource : includedContexts) {
209             final V potential = includedSource.getFromLocalStorage(type, key);
210             if (potential != null) {
211                 return potential;
212             }
213         }
214         return null;
215     }
216
217     @Nullable
218     @Override
219     public <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromLocalStorage(final Class<N> type) {
220         final Map<K, V> potentialLocal = super.getAllFromLocalStorage(type);
221         if (potentialLocal != null) {
222             return potentialLocal;
223         }
224         for (final NamespaceStorageNode includedSource : includedContexts) {
225             final Map<K, V> potential = includedSource.getAllFromLocalStorage(type);
226             if (potential != null) {
227                 return potential;
228             }
229         }
230         return null;
231     }
232
233     @Override
234     public YangVersion getRootVersion() {
235         return version == null ? DEFAULT_VERSION : version;
236     }
237
238     @Override
239     public void setRootVersion(final YangVersion version) {
240         Preconditions.checkArgument(sourceContext.getSupportedVersions().contains(version),
241                 "Unsupported yang version %s in %s", version, getStatementSourceReference());
242         Preconditions.checkState(this.version == null, "Version of root %s has been already set to %s", argument,
243                 this.version);
244         this.version = Preconditions.checkNotNull(version);
245     }
246
247     @Override
248     public void addMutableStmtToSeal(final MutableStatement mutableStatement) {
249         sourceContext.addMutableStmtToSeal(mutableStatement);
250     }
251 }