Use Objects.equals() in effective statements
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / rfc6020 / effective / ModuleEffectiveStatementImpl.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.rfc6020.effective;
9
10 import com.google.common.collect.ImmutableList;
11 import com.google.common.collect.ImmutableMap;
12 import com.google.common.collect.ImmutableSet;
13 import java.net.URI;
14 import java.util.Collection;
15 import java.util.Date;
16 import java.util.HashSet;
17 import java.util.LinkedHashMap;
18 import java.util.LinkedHashSet;
19 import java.util.LinkedList;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Objects;
23 import java.util.Set;
24 import org.opendaylight.yangtools.concepts.Immutable;
25 import org.opendaylight.yangtools.yang.common.QName;
26 import org.opendaylight.yangtools.yang.common.QNameModule;
27 import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
28 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
29 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
30 import org.opendaylight.yangtools.yang.model.api.Deviation;
31 import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition;
32 import org.opendaylight.yangtools.yang.model.api.FeatureDefinition;
33 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
34 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
35 import org.opendaylight.yangtools.yang.model.api.Module;
36 import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
37 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
38 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
39 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
40 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
41 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
42 import org.opendaylight.yangtools.yang.model.api.UsesNode;
43 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
44 import org.opendaylight.yangtools.yang.model.api.stmt.ModuleStatement;
45 import org.opendaylight.yangtools.yang.model.api.stmt.SubmoduleStatement;
46 import org.opendaylight.yangtools.yang.model.util.ExtendedType;
47 import org.opendaylight.yangtools.yang.model.util.ModuleImportImpl;
48 import org.opendaylight.yangtools.yang.parser.spi.SubmoduleNamespace;
49 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
50 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
51 import org.opendaylight.yangtools.yang.parser.spi.source.DeclarationInTextSource;
52 import org.opendaylight.yangtools.yang.parser.spi.source.IncludedSubmoduleNameToIdentifier;
53 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleCtxToModuleQName;
54 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.Utils;
55
56 public class ModuleEffectiveStatementImpl extends AbstractEffectiveDocumentedNode<String, ModuleStatement> implements
57         Module, Immutable {
58
59     private final QNameModule qNameModule;
60     private final String name;
61     private final String sourcePath;
62     private String prefix;
63     private String yangVersion;
64     private String organization;
65     private String contact;
66     private ImmutableSet<ModuleImport> imports;
67     private ImmutableSet<Module> submodules;
68     private ImmutableSet<FeatureDefinition> features;
69     private ImmutableSet<NotificationDefinition> notifications;
70     private ImmutableSet<AugmentationSchema> augmentations;
71     private ImmutableSet<RpcDefinition> rpcs;
72     private ImmutableSet<Deviation> deviations;
73     private ImmutableList<ExtensionDefinition> extensionNodes;
74     private ImmutableSet<IdentitySchemaNode> identities;
75     private ImmutableList<UnknownSchemaNode> unknownNodes;
76     private final String source;
77     private ImmutableList<EffectiveStatement<?, ?>> substatementsOfSubmodules;
78
79     private ImmutableMap<QName, DataSchemaNode> childNodes;
80     private ImmutableSet<GroupingDefinition> groupings;
81     private ImmutableSet<UsesNode> uses;
82     private ImmutableSet<TypeDefinition<?>> typeDefinitions;
83     private ImmutableSet<DataSchemaNode> publicChildNodes;
84
85     public ModuleEffectiveStatementImpl(
86             final StmtContext<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> ctx) {
87         super(ctx);
88
89         name = argument();
90         QNameModule qNameModuleInit = ctx.getFromNamespace( ModuleCtxToModuleQName.class, ctx);
91         qNameModule = qNameModuleInit.getRevision() == null
92                 ? QNameModule.create(qNameModuleInit.getNamespace(), SimpleDateFormatUtil.DEFAULT_DATE_REV)
93                 : qNameModuleInit;
94
95         for (EffectiveStatement<?, ?> effectiveStatement : effectiveSubstatements()) {
96             if (effectiveStatement instanceof PrefixEffectiveStatementImpl) {
97                 prefix = ((PrefixEffectiveStatementImpl) effectiveStatement).argument();
98             }
99             if (effectiveStatement instanceof YangVersionEffectiveStatementImpl) {
100                 yangVersion = ((YangVersionEffectiveStatementImpl) effectiveStatement).argument();
101             }
102             if (effectiveStatement instanceof OrganizationEffectiveStatementImpl) {
103                 organization = ((OrganizationEffectiveStatementImpl) effectiveStatement).argument();
104             }
105             if (effectiveStatement instanceof ContactEffectiveStatementImpl) {
106                 contact = ((ContactEffectiveStatementImpl) effectiveStatement).argument();
107             }
108         }
109
110         if (yangVersion == null) {
111             yangVersion = "1";
112         }
113
114         DeclarationInTextSource sourceReference = (DeclarationInTextSource) ctx.getStatementSourceReference();
115         sourcePath = sourceReference.getSourceName();
116         source = sourceReference.getSourceText();
117
118         initSubmodules(ctx);
119         initSubstatementCollections(ctx);
120     }
121
122     private void initSubmodules(
123             final StmtContext<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> ctx) {
124         Map<String, ModuleIdentifier> includedSubmodulesMap = ctx
125                 .getAllFromCurrentStmtCtxNamespace(IncludedSubmoduleNameToIdentifier.class);
126
127         if (includedSubmodulesMap == null || includedSubmodulesMap.isEmpty()) {
128             this.submodules = ImmutableSet.of();
129             this.substatementsOfSubmodules = ImmutableList.of();
130             return;
131         }
132
133         Collection<ModuleIdentifier> includedSubmodules = includedSubmodulesMap.values();
134
135         Set<Module> submodulesInit = new HashSet<>();
136         List<EffectiveStatement<?, ?>> substatementsOfSubmodulesInit = new LinkedList<>();
137         for (ModuleIdentifier submoduleIdentifier : includedSubmodules) {
138             @SuppressWarnings("unchecked")
139             Mutable<String, SubmoduleStatement, EffectiveStatement<String, SubmoduleStatement>> submoduleCtx =
140                     (Mutable<String, SubmoduleStatement, EffectiveStatement<String, SubmoduleStatement>>)
141                     ctx.getFromNamespace(SubmoduleNamespace.class, submoduleIdentifier);
142             SubmoduleEffectiveStatementImpl submodule = (SubmoduleEffectiveStatementImpl) submoduleCtx
143                     .buildEffective();
144             submodulesInit.add(submodule);
145             substatementsOfSubmodulesInit.addAll(submodule.effectiveSubstatements());
146         }
147
148         this.submodules = ImmutableSet.copyOf(submodulesInit);
149         this.substatementsOfSubmodules = ImmutableList
150                 .copyOf(substatementsOfSubmodulesInit);
151     }
152
153     private void initSubstatementCollections(
154             final StmtContext<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> ctx) {
155         List<EffectiveStatement<?, ?>> effectiveSubstatements = new LinkedList<>();
156
157         effectiveSubstatements.addAll(effectiveSubstatements());
158         effectiveSubstatements.addAll(substatementsOfSubmodules);
159
160         List<UnknownSchemaNode> unknownNodesInit = new LinkedList<>();
161         Set<AugmentationSchema> augmentationsInit = new HashSet<>();
162         Set<ModuleImport> importsInit = new HashSet<>();
163         Set<NotificationDefinition> notificationsInit = new HashSet<>();
164         Set<RpcDefinition> rpcsInit = new HashSet<>();
165         Set<Deviation> deviationsInit = new HashSet<>();
166         Set<IdentitySchemaNode> identitiesInit = new HashSet<>();
167         Set<FeatureDefinition> featuresInit = new HashSet<>();
168         List<ExtensionDefinition> extensionNodesInit = new LinkedList<>();
169
170         Map<QName, DataSchemaNode> mutableChildNodes = new LinkedHashMap<>();
171         Set<GroupingDefinition> mutableGroupings = new HashSet<>();
172         Set<UsesNode> mutableUses = new HashSet<>();
173         Set<TypeDefinition<?>> mutableTypeDefinitions = new LinkedHashSet<>();
174         Set<DataSchemaNode> mutablePublicChildNodes = new LinkedHashSet<>();
175
176         for (EffectiveStatement<?, ?> effectiveStatement : effectiveSubstatements) {
177             if (effectiveStatement instanceof UnknownSchemaNode) {
178                 unknownNodesInit.add((UnknownSchemaNode) effectiveStatement);
179             }
180             if (effectiveStatement instanceof AugmentationSchema) {
181                 augmentationsInit.add((AugmentationSchema) effectiveStatement);
182             }
183             if (effectiveStatement instanceof ModuleImport) {
184                 importsInit.add((ModuleImport) effectiveStatement);
185             }
186             if (effectiveStatement instanceof NotificationDefinition) {
187                 notificationsInit.add((NotificationDefinition) effectiveStatement);
188             }
189             if (effectiveStatement instanceof RpcDefinition) {
190                 rpcsInit.add((RpcDefinition) effectiveStatement);
191             }
192             if (effectiveStatement instanceof Deviation) {
193                 deviationsInit.add((Deviation) effectiveStatement);
194             }
195             if (effectiveStatement instanceof IdentitySchemaNode) {
196                 identitiesInit.add((IdentitySchemaNode) effectiveStatement);
197             }
198             if (effectiveStatement instanceof FeatureDefinition) {
199                 featuresInit.add((FeatureDefinition) effectiveStatement);
200             }
201             if (effectiveStatement instanceof ExtensionDefinition) {
202                 extensionNodesInit.add((ExtensionDefinition) effectiveStatement);
203             }
204             if (effectiveStatement instanceof DataSchemaNode) {
205                 DataSchemaNode dataSchemaNode = (DataSchemaNode) effectiveStatement;
206                 if (!mutableChildNodes.containsKey(dataSchemaNode.getQName())) {
207                     mutableChildNodes.put(dataSchemaNode.getQName(), dataSchemaNode);
208                     mutablePublicChildNodes.add(dataSchemaNode);
209                 } else {
210                     throw EffectiveStmtUtils.createNameCollisionSourceException(ctx, effectiveStatement);
211                 }
212             }
213             if (effectiveStatement instanceof UsesNode) {
214                 UsesNode usesNode = (UsesNode) effectiveStatement;
215                 if (!mutableUses.contains(usesNode)) {
216                     mutableUses.add(usesNode);
217                 } else {
218                     throw EffectiveStmtUtils.createNameCollisionSourceException(ctx, effectiveStatement);
219                 }
220             }
221             if (effectiveStatement instanceof TypeDefEffectiveStatementImpl) {
222                 TypeDefEffectiveStatementImpl typeDef = (TypeDefEffectiveStatementImpl) effectiveStatement;
223                 ExtendedType extendedType = typeDef.buildType();
224                 if (!mutableTypeDefinitions.contains(extendedType)) {
225                     mutableTypeDefinitions.add(extendedType);
226                 } else {
227                     throw EffectiveStmtUtils.createNameCollisionSourceException(ctx, effectiveStatement);
228                 }
229             }
230             if (effectiveStatement instanceof GroupingDefinition) {
231                 GroupingDefinition grp = (GroupingDefinition) effectiveStatement;
232                 if (!mutableGroupings.contains(grp)) {
233                     mutableGroupings.add(grp);
234                 } else {
235                     throw EffectiveStmtUtils.createNameCollisionSourceException(ctx, effectiveStatement);
236                 }
237             }
238         }
239
240         this.unknownNodes = ImmutableList.copyOf(unknownNodesInit);
241         this.augmentations = ImmutableSet.copyOf(augmentationsInit);
242         this.imports = ImmutableSet.copyOf(resolveModuleImports(importsInit, ctx));
243         this.notifications = ImmutableSet.copyOf(notificationsInit);
244         this.rpcs = ImmutableSet.copyOf(rpcsInit);
245         this.deviations = ImmutableSet.copyOf(deviationsInit);
246         this.identities = ImmutableSet.copyOf(identitiesInit);
247         this.features = ImmutableSet.copyOf(featuresInit);
248         this.extensionNodes = ImmutableList.copyOf(extensionNodesInit);
249
250         this.childNodes = ImmutableMap.copyOf(mutableChildNodes);
251         this.groupings = ImmutableSet.copyOf(mutableGroupings);
252         this.publicChildNodes = ImmutableSet.copyOf(mutablePublicChildNodes);
253         this.typeDefinitions = ImmutableSet.copyOf(mutableTypeDefinitions);
254         this.uses = ImmutableSet.copyOf(mutableUses);
255     }
256
257     private static Set<ModuleImport> resolveModuleImports(final Set<ModuleImport> importsInit,
258             final StmtContext<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> ctx) {
259         Set<ModuleImport> resolvedModuleImports = new LinkedHashSet<>();
260         for (ModuleImport moduleImport : importsInit) {
261             if (moduleImport.getRevision().equals(
262                     SimpleDateFormatUtil.DEFAULT_DATE_IMP)) {
263                 QNameModule impModuleQName = Utils.getModuleQNameByPrefix(ctx,
264                         moduleImport.getPrefix());
265                 if (!impModuleQName.getRevision().equals(
266                         SimpleDateFormatUtil.DEFAULT_DATE_REV)) {
267                     ModuleImport resolvedModuleImport = new ModuleImportImpl(
268                             moduleImport.getModuleName(),
269                             impModuleQName.getRevision(),
270                             moduleImport.getPrefix());
271                     resolvedModuleImports.add(resolvedModuleImport);
272                 }
273             } else {
274                 resolvedModuleImports.add(moduleImport);
275             }
276         }
277         return resolvedModuleImports;
278     }
279
280     @Override
281     public String getModuleSourcePath() {
282         return sourcePath;
283     }
284
285     @Override
286     public URI getNamespace() {
287         return qNameModule.getNamespace();
288     }
289
290     @Override
291     public String getName() {
292         return name;
293     }
294
295     @Override
296     public Date getRevision() {
297         return qNameModule.getRevision();
298     }
299
300     @Override
301     public String getPrefix() {
302         return prefix;
303     }
304
305     @Override
306     public String getYangVersion() {
307         return yangVersion;
308     }
309
310     @Override
311     public String getOrganization() {
312         return organization;
313     }
314
315     @Override
316     public String getContact() {
317         return contact;
318     }
319
320     @Override
321     public Set<ModuleImport> getImports() {
322         return imports;
323     }
324
325     @Override
326     public Set<Module> getSubmodules() {
327         return submodules;
328     }
329
330     @Override
331     public Set<FeatureDefinition> getFeatures() {
332         return features;
333     }
334
335     @Override
336     public Set<NotificationDefinition> getNotifications() {
337         return notifications;
338     }
339
340     @Override
341     public Set<AugmentationSchema> getAugmentations() {
342         return augmentations;
343     }
344
345     @Override
346     public Set<RpcDefinition> getRpcs() {
347         return rpcs;
348     }
349
350     @Override
351     public Set<Deviation> getDeviations() {
352         return deviations;
353     }
354
355     @Override
356     public List<ExtensionDefinition> getExtensionSchemaNodes() {
357         return extensionNodes;
358     }
359
360     @Override
361     public Set<IdentitySchemaNode> getIdentities() {
362         return identities;
363     }
364
365     @Override
366     public List<UnknownSchemaNode> getUnknownSchemaNodes() {
367         return unknownNodes;
368     }
369
370     @Override
371     public final Set<TypeDefinition<?>> getTypeDefinitions() {
372         return typeDefinitions;
373     }
374
375     @Override
376     public final Set<DataSchemaNode> getChildNodes() {
377         return publicChildNodes;
378     }
379
380     @Override
381     public final Set<GroupingDefinition> getGroupings() {
382         return groupings;
383     }
384
385     @Override
386     public final DataSchemaNode getDataChildByName(final QName name) {
387         // Child nodes are keyed by their container name, so we can do a direct
388         // lookup
389         return childNodes.get(name);
390     }
391
392     @Override
393     public final DataSchemaNode getDataChildByName(final String name) {
394         for (DataSchemaNode node : childNodes.values()) {
395             if (node.getQName().getLocalName().equals(name)) {
396                 return node;
397             }
398         }
399         return null;
400     }
401
402     @Override
403     public Set<UsesNode> getUses() {
404         return uses;
405     }
406
407     @Override
408     public String getSource() {
409         return source;
410     }
411
412     @Override
413     public int hashCode() {
414         final int prime = 31;
415         int result = 1;
416         result = prime * result + Objects.hashCode(name);
417         result = prime * result + Objects.hashCode(yangVersion);
418         result = prime * result + qNameModule.hashCode();
419         return result;
420     }
421
422     @Override
423     public boolean equals(final Object obj) {
424         if (this == obj) {
425             return true;
426         }
427         if (obj == null) {
428             return false;
429         }
430         if (getClass() != obj.getClass()) {
431             return false;
432         }
433         ModuleEffectiveStatementImpl other = (ModuleEffectiveStatementImpl) obj;
434         if (!Objects.equals(name, other.name)) {
435             return false;
436         }
437         if (!qNameModule.equals(other.qNameModule)) {
438             return false;
439         }
440         if (!Objects.equals(yangVersion, other.yangVersion)) {
441             return false;
442         }
443         return true;
444     }
445
446     @Override
447     public String toString() {
448         StringBuilder sb = new StringBuilder(ModuleEffectiveStatementImpl.class.getSimpleName());
449         sb.append("[");
450         sb.append("name=").append(name);
451         sb.append(", namespace=").append(getNamespace());
452         sb.append(", revision=").append(getRevision());
453         sb.append(", prefix=").append(prefix);
454         sb.append(", yangVersion=").append(yangVersion);
455         sb.append("]");
456         return sb.toString();
457     }
458
459     @Override
460     public QNameModule getQNameModule() {
461         return qNameModule;
462     }
463
464 }