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