2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.yang.parser.impl;
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;
20 import java.util.TreeMap;
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;
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;
47 final class SchemaContextImpl implements SchemaContext {
48 private static final Supplier<HashSet<Module>> URI_SET_SUPPLIER = new Supplier<HashSet<Module>>() {
50 public HashSet<Module> get() {
51 return new HashSet<>();
55 private final Map<ModuleIdentifier, String> identifiersToSources;
56 private final SetMultimap<URI, Module> namespaceToModules;
57 private final Set<Module> modules;
59 SchemaContextImpl(final Set<Module> modules, final Map<ModuleIdentifier, String> identifiersToSources) {
60 this.identifiersToSources = identifiersToSources;
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.
66 this.modules = ImmutableSet.copyOf(ModuleDependencySort.sort(modules.toArray(new Module[modules.size()])));
69 * The most common lookup is from Namespace->Module. Invest some quality time in
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);
78 namespaceToModules = ImmutableSetMultimap.copyOf(multimap);
82 public Set<DataSchemaNode> getDataDefinitions() {
83 final Set<DataSchemaNode> dataDefs = new HashSet<DataSchemaNode>();
84 for (Module m : modules) {
85 dataDefs.addAll(m.getChildNodes());
91 public Set<Module> getModules() {
96 public Set<NotificationDefinition> getNotifications() {
97 final Set<NotificationDefinition> notifications = new HashSet<NotificationDefinition>();
98 for (Module m : modules) {
99 notifications.addAll(m.getNotifications());
101 return notifications;
105 public Set<RpcDefinition> getOperations() {
106 final Set<RpcDefinition> rpcs = new HashSet<RpcDefinition>();
107 for (Module m : modules) {
108 rpcs.addAll(m.getRpcs());
114 public Set<ExtensionDefinition> getExtensions() {
115 final Set<ExtensionDefinition> extensions = new HashSet<ExtensionDefinition>();
116 for (Module m : modules) {
117 extensions.addAll(m.getExtensionSchemaNodes());
123 public Module findModuleByName(final String name, final Date revision) {
125 for (final Module module : modules) {
126 if (revision == null) {
127 if (module.getName().equals(name)) {
130 } else if (module.getName().equals(name) && module.getRevision().equals(revision)) {
139 public Set<Module> findModuleByNamespace(final URI namespace) {
140 final Set<Module> ret = namespaceToModules.get(namespace);
141 return ret == null ? Collections.<Module>emptySet() : ret;
145 public Module findModuleByNamespaceAndRevision(final URI namespace, final Date revision) {
146 if (namespace == null) {
149 final Set<Module> modules = findModuleByNamespace(namespace);
150 if (modules.isEmpty()) {
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);
163 return map.lastEntry().getValue();
165 for (Module module : modules) {
166 if (module.getRevision().equals(revision)) {
175 public boolean isAugmenting() {
180 public boolean isAddedByUses() {
185 public boolean isConfiguration() {
190 public ConstraintDefinition getConstraints() {
195 public QName getQName() {
196 return SchemaContext.NAME;
200 public SchemaPath getPath() {
205 public String getDescription() {
210 public String getReference() {
215 public Status getStatus() {
216 return Status.CURRENT;
220 public List<UnknownSchemaNode> getUnknownSchemaNodes() {
221 final List<UnknownSchemaNode> result = new ArrayList<>();
222 for (Module module : modules) {
223 result.addAll(module.getUnknownSchemaNodes());
225 return Collections.unmodifiableList(result);
229 public Set<TypeDefinition<?>> getTypeDefinitions() {
230 final Set<TypeDefinition<?>> result = new LinkedHashSet<>();
231 for (Module module : modules) {
232 result.addAll(module.getTypeDefinitions());
234 return Collections.unmodifiableSet(result);
238 public Set<DataSchemaNode> getChildNodes() {
239 final Set<DataSchemaNode> result = new LinkedHashSet<>();
240 for (Module module : modules) {
241 result.addAll(module.getChildNodes());
243 return Collections.unmodifiableSet(result);
247 public Set<GroupingDefinition> getGroupings() {
248 final Set<GroupingDefinition> result = new LinkedHashSet<>();
249 for (Module module : modules) {
250 result.addAll(module.getGroupings());
252 return Collections.unmodifiableSet(result);
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) {
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) {
280 public Set<UsesNode> getUses() {
281 return Collections.emptySet();
285 public boolean isPresenceContainer() {
290 public Set<AugmentationSchema> getAvailableAugmentations() {
291 return Collections.emptySet();
294 //FIXME: should work for submodules too
296 public Set<ModuleIdentifier> getAllModuleIdentifiers() {
297 return identifiersToSources.keySet();
301 public Optional<String> getModuleSource(final ModuleIdentifier moduleIdentifier) {
302 String maybeSource = identifiersToSources.get(moduleIdentifier);
303 return Optional.fromNullable(maybeSource);