Fix checkListKey not checking actual/expected values
[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.Comparator;
22 import java.util.Date;
23 import java.util.HashSet;
24 import java.util.LinkedHashSet;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Set;
28 import java.util.TreeMap;
29 import java.util.TreeSet;
30 import javax.annotation.concurrent.Immutable;
31 import org.opendaylight.yangtools.yang.common.QName;
32 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
33 import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition;
34 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
35 import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition;
36 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
37 import org.opendaylight.yangtools.yang.model.api.Module;
38 import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
39 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
40 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
41 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
42 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
43 import org.opendaylight.yangtools.yang.model.api.Status;
44 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
45 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
46 import org.opendaylight.yangtools.yang.model.api.UsesNode;
47 import org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort;
48
49 @Immutable
50 final class SchemaContextImpl implements SchemaContext {
51     private static final Comparator<Module> REVISION_COMPARATOR = new Comparator<Module>() {
52         @Override
53         public int compare(final Module o1, final Module o2) {
54             if (o2.getRevision() == null) {
55                 return -1;
56             }
57
58             return o2.getRevision().compareTo(o1.getRevision());
59         }
60     };
61
62     private static final Supplier<TreeSet<Module>> MODULE_SET_SUPPLIER = new Supplier<TreeSet<Module>>() {
63         @Override
64         public TreeSet<Module> get() {
65             return new TreeSet<>(REVISION_COMPARATOR);
66         }
67     };
68
69     private final Map<ModuleIdentifier, String> identifiersToSources;
70     private final SetMultimap<URI, Module> namespaceToModules;
71     private final SetMultimap<String, Module> nameToModules;
72     private final Set<Module> modules;
73
74     SchemaContextImpl(final Set<Module> modules, final Map<ModuleIdentifier, String> identifiersToSources) {
75         this.identifiersToSources = ImmutableMap.copyOf(identifiersToSources);
76
77         /*
78          * Instead of doing this on each invocation of getModules(), pre-compute
79          * it once and keep it around -- better than the set we got in.
80          */
81         this.modules = ImmutableSet.copyOf(ModuleDependencySort.sort(modules.toArray(new Module[modules.size()])));
82
83         /*
84          * The most common lookup is from Namespace->Module.
85          *
86          * RESTCONF performs lookups based on module name only, where it wants
87          * to receive the latest revision
88          *
89          * Invest some quality time in building up lookup tables for both.
90          */
91         final SetMultimap<URI, Module> nsMap = Multimaps.newSetMultimap(
92                 new TreeMap<URI, Collection<Module>>(), MODULE_SET_SUPPLIER);
93         final SetMultimap<String, Module> nameMap = Multimaps.newSetMultimap(
94                 new TreeMap<String, Collection<Module>>(), MODULE_SET_SUPPLIER);
95         for (Module m : modules) {
96             nameMap.put(m.getName(), m);
97             nsMap.put(m.getNamespace(), m);
98         }
99
100         namespaceToModules = ImmutableSetMultimap.copyOf(nsMap);
101         nameToModules = ImmutableSetMultimap.copyOf(nameMap);
102     }
103
104     @Override
105     public Set<DataSchemaNode> getDataDefinitions() {
106         final Set<DataSchemaNode> dataDefs = new HashSet<>();
107         for (Module m : modules) {
108             dataDefs.addAll(m.getChildNodes());
109         }
110         return dataDefs;
111     }
112
113     @Override
114     public Set<Module> getModules() {
115         return modules;
116     }
117
118     @Override
119     public Set<NotificationDefinition> getNotifications() {
120         final Set<NotificationDefinition> notifications = new HashSet<>();
121         for (Module m : modules) {
122             notifications.addAll(m.getNotifications());
123         }
124         return notifications;
125     }
126
127     @Override
128     public Set<RpcDefinition> getOperations() {
129         final Set<RpcDefinition> rpcs = new HashSet<>();
130         for (Module m : modules) {
131             rpcs.addAll(m.getRpcs());
132         }
133         return rpcs;
134     }
135
136     @Override
137     public Set<ExtensionDefinition> getExtensions() {
138         final Set<ExtensionDefinition> extensions = new HashSet<>();
139         for (Module m : modules) {
140             extensions.addAll(m.getExtensionSchemaNodes());
141         }
142         return extensions;
143     }
144
145     @Override
146     public Module findModuleByName(final String name, final Date revision) {
147         for (final Module module : nameToModules.get(name)) {
148             if (revision == null || revision.equals(module.getRevision())) {
149                 return module;
150             }
151         }
152
153         return null;
154     }
155
156     @Override
157     public Set<Module> findModuleByNamespace(final URI namespace) {
158         final Set<Module> ret = namespaceToModules.get(namespace);
159         return ret == null ? Collections.<Module>emptySet() : ret;
160     }
161
162     @Override
163     public Module findModuleByNamespaceAndRevision(final URI namespace, final Date revision) {
164         if (namespace == null) {
165             return null;
166         }
167         for (Module module : findModuleByNamespace(namespace)) {
168             if (revision == null || revision.equals(module.getRevision())) {
169                 return module;
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 SchemaPath.ROOT;
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         for (Module module : modules) {
259             final DataSchemaNode result = module.getDataChildByName(name);
260             if (result != null) {
261                 return result;
262             }
263         }
264         return null;
265     }
266
267     @Override
268     public DataSchemaNode getDataChildByName(final String name) {
269         for (Module module : modules) {
270             final DataSchemaNode result = module.getDataChildByName(name);
271             if (result != null) {
272                 return result;
273             }
274         }
275         return null;
276     }
277
278     @Override
279     public Set<UsesNode> getUses() {
280         return Collections.emptySet();
281     }
282
283     @Override
284     public boolean isPresenceContainer() {
285         return false;
286     }
287
288     @Override
289     public Set<AugmentationSchema> getAvailableAugmentations() {
290         return Collections.emptySet();
291     }
292
293     //FIXME: should work for submodules too
294     @Override
295     public Set<ModuleIdentifier> getAllModuleIdentifiers() {
296         return identifiersToSources.keySet();
297     }
298
299     @Override
300     public Optional<String> getModuleSource(final ModuleIdentifier moduleIdentifier) {
301         String maybeSource = identifiersToSources.get(moduleIdentifier);
302         return Optional.fromNullable(maybeSource);
303     }
304
305     @Override
306     public String toString() {
307         return "SchemaContextImpl{" +
308                 "modules=" + modules +
309                 '}';
310     }
311 }