Merge "BUG-1276: fixed generated union constructor"
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / impl / SchemaContextImpl.java
1 /*
2  * Copyright (c) 2013 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.impl;
9
10 import java.net.URI;
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.Collections;
14 import java.util.Date;
15 import java.util.HashSet;
16 import java.util.LinkedHashSet;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Set;
20 import java.util.TreeMap;
21
22 import javax.annotation.concurrent.Immutable;
23
24 import org.opendaylight.yangtools.yang.common.QName;
25 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
26 import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition;
27 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
28 import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition;
29 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
30 import org.opendaylight.yangtools.yang.model.api.Module;
31 import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
32 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
33 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
34 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
35 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
36 import org.opendaylight.yangtools.yang.model.api.Status;
37 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
38 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
39 import org.opendaylight.yangtools.yang.model.api.UsesNode;
40 import org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort;
41
42 import com.google.common.base.Optional;
43 import com.google.common.base.Supplier;
44 import com.google.common.collect.ImmutableMap;
45 import com.google.common.collect.ImmutableSet;
46 import com.google.common.collect.ImmutableSetMultimap;
47 import com.google.common.collect.Multimaps;
48 import com.google.common.collect.SetMultimap;
49
50 @Immutable
51 final class SchemaContextImpl implements SchemaContext {
52     private static final Supplier<HashSet<Module>> URI_SET_SUPPLIER = new Supplier<HashSet<Module>>() {
53         @Override
54         public HashSet<Module> get() {
55             return new HashSet<>();
56         }
57     };
58
59     private final ImmutableMap<ModuleIdentifier, String> identifiersToSources;
60     private final ImmutableSetMultimap<URI, Module> namespaceToModules;
61     private final ImmutableSet<Module> modules;
62
63     SchemaContextImpl(final Set<Module> modules, final Map<ModuleIdentifier, String> identifiersToSources) {
64         this.identifiersToSources = ImmutableMap.copyOf(identifiersToSources);
65
66         /*
67          * Instead of doing this on each invocation of getModules(), pre-compute
68          * it once and keep it around -- better than the set we got in.
69          */
70         this.modules = ImmutableSet.copyOf(ModuleDependencySort.sort(modules.toArray(new Module[modules.size()])));
71
72         /*
73          * The most common lookup is from Namespace->Module. Invest some quality time in
74          * building that up.
75          */
76         final SetMultimap<URI, Module> multimap = Multimaps.newSetMultimap(
77                 new TreeMap<URI, Collection<Module>>(), URI_SET_SUPPLIER);
78         for (Module m : modules) {
79             multimap.put(m.getNamespace(), m);
80         }
81
82         namespaceToModules = ImmutableSetMultimap.copyOf(multimap);
83     }
84
85     @Override
86     public Set<DataSchemaNode> getDataDefinitions() {
87         final Set<DataSchemaNode> dataDefs = new HashSet<>();
88         for (Module m : modules) {
89             dataDefs.addAll(m.getChildNodes());
90         }
91         return dataDefs;
92     }
93
94     @Override
95     public Set<Module> getModules() {
96         return modules;
97     }
98
99     @Override
100     public Set<NotificationDefinition> getNotifications() {
101         final Set<NotificationDefinition> notifications = new HashSet<>();
102         for (Module m : modules) {
103             notifications.addAll(m.getNotifications());
104         }
105         return notifications;
106     }
107
108     @Override
109     public Set<RpcDefinition> getOperations() {
110         final Set<RpcDefinition> rpcs = new HashSet<>();
111         for (Module m : modules) {
112             rpcs.addAll(m.getRpcs());
113         }
114         return rpcs;
115     }
116
117     @Override
118     public Set<ExtensionDefinition> getExtensions() {
119         final Set<ExtensionDefinition> extensions = new HashSet<>();
120         for (Module m : modules) {
121             extensions.addAll(m.getExtensionSchemaNodes());
122         }
123         return extensions;
124     }
125
126     @Override
127     public Module findModuleByName(final String name, final Date revision) {
128         if (name != null) {
129             for (final Module module : modules) {
130                 if (revision == null) {
131                     if (module.getName().equals(name)) {
132                         return module;
133                     }
134                 } else if (module.getName().equals(name) && module.getRevision().equals(revision)) {
135                     return module;
136                 }
137             }
138         }
139         return null;
140     }
141
142     @Override
143     public Set<Module> findModuleByNamespace(final URI namespace) {
144         final Set<Module> ret = namespaceToModules.get(namespace);
145         return ret == null ? Collections.<Module>emptySet() : ret;
146     }
147
148     @Override
149     public Module findModuleByNamespaceAndRevision(final URI namespace, final Date revision) {
150         if (namespace == null) {
151             return null;
152         }
153         final Set<Module> modules = findModuleByNamespace(namespace);
154         if (modules.isEmpty()) {
155             return null;
156         }
157
158         if (revision == null) {
159             // FIXME: The ordering of modules in Multimap could just guarantee this...
160             TreeMap<Date, Module> map = new TreeMap<>();
161             for (Module module : modules) {
162                 map.put(module.getRevision(), module);
163             }
164             if (map.isEmpty()) {
165                 return null;
166             }
167             return map.lastEntry().getValue();
168         } else {
169             for (Module module : modules) {
170                 if (module.getRevision().equals(revision)) {
171                     return(module);
172                 }
173             }
174         }
175         return null;
176     }
177
178     @Override
179     public boolean isAugmenting() {
180         return false;
181     }
182
183     @Override
184     public boolean isAddedByUses() {
185         return false;
186     }
187
188     @Override
189     public boolean isConfiguration() {
190         return false;
191     }
192
193     @Override
194     public ConstraintDefinition getConstraints() {
195         return null;
196     }
197
198     @Override
199     public QName getQName() {
200         return SchemaContext.NAME;
201     }
202
203     @Override
204     public SchemaPath getPath() {
205         return null;
206     }
207
208     @Override
209     public String getDescription() {
210         return null;
211     }
212
213     @Override
214     public String getReference() {
215         return null;
216     }
217
218     @Override
219     public Status getStatus() {
220         return Status.CURRENT;
221     }
222
223     @Override
224     public List<UnknownSchemaNode> getUnknownSchemaNodes() {
225         final List<UnknownSchemaNode> result = new ArrayList<>();
226         for (Module module : modules) {
227             result.addAll(module.getUnknownSchemaNodes());
228         }
229         return Collections.unmodifiableList(result);
230     }
231
232     @Override
233     public Set<TypeDefinition<?>> getTypeDefinitions() {
234         final Set<TypeDefinition<?>> result = new LinkedHashSet<>();
235         for (Module module : modules) {
236             result.addAll(module.getTypeDefinitions());
237         }
238         return Collections.unmodifiableSet(result);
239     }
240
241     @Override
242     public Set<DataSchemaNode> getChildNodes() {
243         final Set<DataSchemaNode> result = new LinkedHashSet<>();
244         for (Module module : modules) {
245             result.addAll(module.getChildNodes());
246         }
247         return Collections.unmodifiableSet(result);
248     }
249
250     @Override
251     public Set<GroupingDefinition> getGroupings() {
252         final Set<GroupingDefinition> result = new LinkedHashSet<>();
253         for (Module module : modules) {
254             result.addAll(module.getGroupings());
255         }
256         return Collections.unmodifiableSet(result);
257     }
258
259     @Override
260     public DataSchemaNode getDataChildByName(final QName name) {
261         DataSchemaNode result = null;
262         for (Module module : modules) {
263             result = module.getDataChildByName(name);
264             if (result != null) {
265                 break;
266             }
267         }
268         return result;
269     }
270
271     @Override
272     public DataSchemaNode getDataChildByName(final String name) {
273         DataSchemaNode result = null;
274         for (Module module : modules) {
275             result = module.getDataChildByName(name);
276             if (result != null) {
277                 break;
278             }
279         }
280         return result;
281     }
282
283     @Override
284     public Set<UsesNode> getUses() {
285         return Collections.emptySet();
286     }
287
288     @Override
289     public boolean isPresenceContainer() {
290         return false;
291     }
292
293     @Override
294     public Set<AugmentationSchema> getAvailableAugmentations() {
295         return Collections.emptySet();
296     }
297
298     //FIXME: should work for submodules too
299     @Override
300     public Set<ModuleIdentifier> getAllModuleIdentifiers() {
301         return identifiersToSources.keySet();
302     }
303
304     @Override
305     public Optional<String> getModuleSource(final ModuleIdentifier moduleIdentifier) {
306         String maybeSource = identifiersToSources.get(moduleIdentifier);
307         return Optional.fromNullable(maybeSource);
308     }
309
310     @Override
311     public String toString() {
312         return "SchemaContextImpl{" +
313                 "modules=" + modules +
314                 '}';
315     }
316 }