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