Remove AbstractEffectiveModule.name
[yangtools.git] / yang / yang-parser-rfc7950 / src / main / java / org / opendaylight / yangtools / yang / parser / rfc7950 / stmt / AbstractEffectiveModule.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.rfc7950.stmt;
9
10 import static com.google.common.base.Verify.verifyNotNull;
11 import static java.util.Objects.requireNonNull;
12
13 import com.google.common.annotations.Beta;
14 import com.google.common.base.MoreObjects;
15 import com.google.common.collect.ImmutableList;
16 import com.google.common.collect.ImmutableMap;
17 import com.google.common.collect.ImmutableMap.Builder;
18 import com.google.common.collect.ImmutableSet;
19 import java.net.URI;
20 import java.util.ArrayList;
21 import java.util.Collection;
22 import java.util.LinkedHashSet;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Optional;
26 import java.util.Set;
27 import org.eclipse.jdt.annotation.NonNull;
28 import org.opendaylight.yangtools.concepts.SemVer;
29 import org.opendaylight.yangtools.openconfig.model.api.OpenConfigVersionEffectiveStatement;
30 import org.opendaylight.yangtools.yang.common.QName;
31 import org.opendaylight.yangtools.yang.common.Revision;
32 import org.opendaylight.yangtools.yang.common.YangVersion;
33 import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
34 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
35 import org.opendaylight.yangtools.yang.model.api.Deviation;
36 import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition;
37 import org.opendaylight.yangtools.yang.model.api.FeatureDefinition;
38 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
39 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
40 import org.opendaylight.yangtools.yang.model.api.Module;
41 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
42 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
43 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
44 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
45 import org.opendaylight.yangtools.yang.model.api.UsesNode;
46 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
47 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
48 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
49 import org.opendaylight.yangtools.yang.model.api.stmt.ContactEffectiveStatement;
50 import org.opendaylight.yangtools.yang.model.api.stmt.DataTreeAwareEffectiveStatement;
51 import org.opendaylight.yangtools.yang.model.api.stmt.ImportEffectiveStatement;
52 import org.opendaylight.yangtools.yang.model.api.stmt.ModuleEffectiveStatement;
53 import org.opendaylight.yangtools.yang.model.api.stmt.OrganizationEffectiveStatement;
54 import org.opendaylight.yangtools.yang.model.api.stmt.PrefixEffectiveStatement;
55 import org.opendaylight.yangtools.yang.model.api.stmt.PrefixStatement;
56 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeAwareEffectiveStatement;
57 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
58 import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
59 import org.opendaylight.yangtools.yang.model.api.stmt.YangVersionEffectiveStatement;
60 import org.opendaylight.yangtools.yang.model.api.stmt.compat.NotificationNodeContainerCompat;
61 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
62 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
63 import org.opendaylight.yangtools.yang.parser.spi.source.ImportPrefixToModuleCtx;
64 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
65
66 @Beta
67 public abstract class AbstractEffectiveModule<D extends DeclaredStatement<String>,
68         E extends DataTreeAwareEffectiveStatement<String, D>>
69         extends AbstractEffectiveDocumentedNodeWithStatus<String, D>
70         implements Module, NotificationNodeContainerCompat<String, D, E> {
71     private final String prefix;
72     private final YangVersion yangVersion;
73     private final String organization;
74     private final String contact;
75     private final ImmutableSet<ModuleImport> imports;
76     private final ImmutableSet<FeatureDefinition> features;
77     private final @NonNull ImmutableSet<NotificationDefinition> notifications;
78     private final ImmutableSet<AugmentationSchemaNode> augmentations;
79     private final ImmutableSet<RpcDefinition> rpcs;
80     private final ImmutableSet<Deviation> deviations;
81     private final ImmutableList<ExtensionDefinition> extensionNodes;
82     private final ImmutableSet<IdentitySchemaNode> identities;
83     private final ImmutableSet<GroupingDefinition> groupings;
84     private final ImmutableSet<UsesNode> uses;
85     private final ImmutableSet<TypeDefinition<?>> typeDefinitions;
86     private final ImmutableSet<DataSchemaNode> publicChildNodes;
87     private final SemVer semanticVersion;
88     private final ImmutableMap<QName, SchemaTreeEffectiveStatement<?>> schemaTreeNamespace;
89
90     protected AbstractEffectiveModule(
91             final @NonNull StmtContext<String, D, ? extends EffectiveStatement<String, ?>> ctx,
92             final @NonNull String prefix) {
93         super(ctx);
94
95         // This check is rather weird, but comes from our desire to lower memory footprint while providing both
96         // EffectiveStatements and SchemaNode interfaces -- which do not overlap completely where child lookups are
97         // concerned. This ensures that we have SchemaTree index available for use with child lookups.
98         final Map<QName, SchemaTreeEffectiveStatement<?>> schemaTree =
99                 createSchemaTreeNamespace(ctx.getStatementSourceReference(), effectiveSubstatements());
100         schemaTreeNamespace = ImmutableMap.copyOf(schemaTree);
101
102         // Data tree check, not currently used
103         createDataTreeNamespace(ctx.getStatementSourceReference(), schemaTree.values(), schemaTreeNamespace);
104
105         this.prefix = requireNonNull(prefix);
106         this.yangVersion = findFirstEffectiveSubstatementArgument(YangVersionEffectiveStatement.class)
107                 .orElse(YangVersion.VERSION_1);
108         this.semanticVersion = findFirstEffectiveSubstatementArgument(OpenConfigVersionEffectiveStatement.class)
109                 .orElse(null);
110         this.organization = findFirstEffectiveSubstatementArgument(OrganizationEffectiveStatement.class)
111                 .orElse(null);
112         this.contact = findFirstEffectiveSubstatementArgument(ContactEffectiveStatement.class)
113                 .orElse(null);
114
115         final Set<AugmentationSchemaNode> augmentationsInit = new LinkedHashSet<>();
116         final Set<ModuleImport> importsInit = new LinkedHashSet<>();
117         final Set<NotificationDefinition> notificationsInit = new LinkedHashSet<>();
118         final Set<RpcDefinition> rpcsInit = new LinkedHashSet<>();
119         final Set<Deviation> deviationsInit = new LinkedHashSet<>();
120         final Set<IdentitySchemaNode> identitiesInit = new LinkedHashSet<>();
121         final Set<FeatureDefinition> featuresInit = new LinkedHashSet<>();
122         final List<ExtensionDefinition> extensionNodesInit = new ArrayList<>();
123
124         final Set<GroupingDefinition> mutableGroupings = new LinkedHashSet<>();
125         final Set<UsesNode> mutableUses = new LinkedHashSet<>();
126         final Set<TypeDefinition<?>> mutableTypeDefinitions = new LinkedHashSet<>();
127         final Set<DataSchemaNode> mutablePublicChildNodes = new LinkedHashSet<>();
128
129         for (final EffectiveStatement<?, ?> effectiveStatement : effectiveSubstatements()) {
130             if (effectiveStatement instanceof AugmentationSchemaNode) {
131                 augmentationsInit.add((AugmentationSchemaNode) effectiveStatement);
132             }
133             if (effectiveStatement instanceof ModuleImport) {
134                 importsInit.add((ModuleImport) effectiveStatement);
135             }
136             if (effectiveStatement instanceof NotificationDefinition) {
137                 notificationsInit.add((NotificationDefinition) effectiveStatement);
138             }
139             if (effectiveStatement instanceof RpcDefinition) {
140                 rpcsInit.add((RpcDefinition) effectiveStatement);
141             }
142             if (effectiveStatement instanceof Deviation) {
143                 deviationsInit.add((Deviation) effectiveStatement);
144             }
145             if (effectiveStatement instanceof IdentitySchemaNode) {
146                 identitiesInit.add((IdentitySchemaNode) effectiveStatement);
147             }
148             if (effectiveStatement instanceof FeatureDefinition) {
149                 featuresInit.add((FeatureDefinition) effectiveStatement);
150             }
151             if (effectiveStatement instanceof ExtensionDefinition) {
152                 extensionNodesInit.add((ExtensionDefinition) effectiveStatement);
153             }
154             if (effectiveStatement instanceof DataSchemaNode) {
155                 mutablePublicChildNodes.add((DataSchemaNode) effectiveStatement);
156             }
157             if (effectiveStatement instanceof UsesNode && !mutableUses.add((UsesNode) effectiveStatement)) {
158                 throw EffectiveStmtUtils.createNameCollisionSourceException(ctx, effectiveStatement);
159             }
160             if (effectiveStatement instanceof TypedefEffectiveStatement) {
161                 final TypeDefinition<?> type = ((TypedefEffectiveStatement) effectiveStatement).getTypeDefinition();
162                 if (!mutableTypeDefinitions.add(type)) {
163                     throw EffectiveStmtUtils.createNameCollisionSourceException(ctx, effectiveStatement);
164                 }
165             }
166             if (effectiveStatement instanceof GroupingDefinition
167                     && !mutableGroupings.add((GroupingDefinition) effectiveStatement)) {
168                 throw EffectiveStmtUtils.createNameCollisionSourceException(ctx, effectiveStatement);
169             }
170         }
171
172         this.augmentations = ImmutableSet.copyOf(augmentationsInit);
173         this.imports = ImmutableSet.copyOf(importsInit);
174         this.notifications = ImmutableSet.copyOf(notificationsInit);
175         this.rpcs = ImmutableSet.copyOf(rpcsInit);
176         this.deviations = ImmutableSet.copyOf(deviationsInit);
177         this.identities = ImmutableSet.copyOf(identitiesInit);
178         this.features = ImmutableSet.copyOf(featuresInit);
179         this.extensionNodes = ImmutableList.copyOf(extensionNodesInit);
180
181         this.groupings = ImmutableSet.copyOf(mutableGroupings);
182         this.publicChildNodes = ImmutableSet.copyOf(mutablePublicChildNodes);
183         this.typeDefinitions = ImmutableSet.copyOf(mutableTypeDefinitions);
184         this.uses = ImmutableSet.copyOf(mutableUses);
185     }
186
187     @Override
188     public URI getNamespace() {
189         return getQNameModule().getNamespace();
190     }
191
192     @Override
193     public String getName() {
194         return argument();
195     }
196
197     @Override
198     public Optional<Revision> getRevision() {
199         return getQNameModule().getRevision();
200     }
201
202     @Override
203     public String getPrefix() {
204         return prefix;
205     }
206
207     @Override
208     public YangVersion getYangVersion() {
209         return yangVersion;
210     }
211
212     @Override
213     public Optional<String> getOrganization() {
214         return Optional.ofNullable(organization);
215     }
216
217     @Override
218     public Optional<String> getContact() {
219         return Optional.ofNullable(contact);
220     }
221
222     @Override
223     public Collection<? extends ModuleImport> getImports() {
224         return imports;
225     }
226
227     @Override
228     public Collection<? extends FeatureDefinition> getFeatures() {
229         return features;
230     }
231
232     @Override
233     public Collection<? extends NotificationDefinition> getNotifications() {
234         return notifications;
235     }
236
237     @Override
238     public Collection<? extends AugmentationSchemaNode> getAugmentations() {
239         return augmentations;
240     }
241
242     @Override
243     public Collection<? extends RpcDefinition> getRpcs() {
244         return rpcs;
245     }
246
247     @Override
248     public Collection<? extends Deviation> getDeviations() {
249         return deviations;
250     }
251
252     @Override
253     public Collection<? extends ExtensionDefinition> getExtensionSchemaNodes() {
254         return extensionNodes;
255     }
256
257     @Override
258     public Collection<? extends IdentitySchemaNode> getIdentities() {
259         return identities;
260     }
261
262     @Override
263     public final Collection<? extends TypeDefinition<?>> getTypeDefinitions() {
264         return typeDefinitions;
265     }
266
267     @Override
268     public final Collection<? extends DataSchemaNode> getChildNodes() {
269         return publicChildNodes;
270     }
271
272     @Override
273     public final Collection<? extends GroupingDefinition> getGroupings() {
274         return groupings;
275     }
276
277     @Override
278     @SuppressWarnings("checkstyle:hiddenField")
279     public final Optional<DataSchemaNode> findDataChildByName(final QName name) {
280         final SchemaTreeEffectiveStatement<?> child = schemaTreeNamespace.get(requireNonNull(name));
281         return child instanceof DataSchemaNode ? Optional.of((DataSchemaNode) child) : Optional.empty();
282     }
283
284     @Override
285     public Collection<? extends UsesNode> getUses() {
286         return uses;
287     }
288
289     @Override
290     public Optional<SemVer> getSemanticVersion() {
291         return Optional.ofNullable(semanticVersion);
292     }
293
294     @Override
295     @SuppressWarnings("unchecked")
296     protected <K, V, N extends IdentifierNamespace<K, V>> Optional<? extends Map<K, V>> getNamespaceContents(
297             final Class<N> namespace) {
298         if (SchemaTreeAwareEffectiveStatement.Namespace.class.equals(namespace)) {
299             return Optional.of((Map<K, V>) schemaTreeNamespace);
300         }
301         return super.getNamespaceContents(namespace);
302     }
303
304     @Override
305     public String toString() {
306         return MoreObjects.toStringHelper(this).omitNullValues()
307                 .add("name", getName())
308                 .add("namespace", getNamespace())
309                 .add("revision", getRevision().orElse(null))
310                 .add("prefix", prefix)
311                 .add("yangVersion", yangVersion)
312                 .toString();
313     }
314
315     protected static final @NonNull String findPrefix(final @NonNull StmtContext<?, ?, ?> ctx,
316             final String type, final String name) {
317         return SourceException.throwIfNull(
318             StmtContextUtils.firstAttributeOf(ctx.declaredSubstatements(), PrefixStatement.class),
319             ctx.getStatementSourceReference(), "Unable to resolve prefix for %s %s.", type, name);
320     }
321
322     // Alright. this is quite ugly
323     protected final void appendPrefixes(final StmtContext<?, ?, ?> ctx,
324             final Builder<String, ModuleEffectiveStatement> builder) {
325         streamEffectiveSubstatements(ImportEffectiveStatement.class)
326             .map(imp -> imp.findFirstEffectiveSubstatementArgument(PrefixEffectiveStatement.class).get())
327             .forEach(pfx -> {
328                 final StmtContext<?, ?, ?> importedCtx =
329                         verifyNotNull(ctx.getFromNamespace(ImportPrefixToModuleCtx.class, pfx),
330                             "Failed to resolve prefix %s", pfx);
331                 builder.put(pfx, (ModuleEffectiveStatement) importedCtx.buildEffective());
332             });
333     }
334 }