BUG-576: modified parser to handle augmentation of extension instances.
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / impl / SchemaContextImpl.java
index ee59c847a9936fb829bd00d34ae5065bd60c7f3f..319f189043f4743daedc326834caeea4c2e12d1d 100644 (file)
@@ -7,11 +7,19 @@
  */
 package org.opendaylight.yangtools.yang.parser.impl;
 
+import com.google.common.base.Optional;
+import com.google.common.base.Supplier;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.Multimaps;
+import com.google.common.collect.SetMultimap;
+
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.Date;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
@@ -19,8 +27,10 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
+import java.util.TreeSet;
 
 import javax.annotation.concurrent.Immutable;
+
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
 import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition;
@@ -39,25 +49,30 @@ import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.UsesNode;
 import org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Supplier;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSetMultimap;
-import com.google.common.collect.Multimaps;
-import com.google.common.collect.SetMultimap;
-
 @Immutable
 final class SchemaContextImpl implements SchemaContext {
-    private static final Supplier<HashSet<Module>> URI_SET_SUPPLIER = new Supplier<HashSet<Module>>() {
+    private static final Comparator<Module> REVISION_COMPARATOR = new Comparator<Module>() {
+        @Override
+        public int compare(final Module o1, final Module o2) {
+            if (o2.getRevision() == null) {
+                return -1;
+            }
+
+            return o2.getRevision().compareTo(o1.getRevision());
+        }
+    };
+
+    private static final Supplier<TreeSet<Module>> MODULE_SET_SUPPLIER = new Supplier<TreeSet<Module>>() {
         @Override
-        public HashSet<Module> get() {
-            return new HashSet<>();
+        public TreeSet<Module> get() {
+            return new TreeSet<>(REVISION_COMPARATOR);
         }
     };
 
-    private final ImmutableMap<ModuleIdentifier, String> identifiersToSources;
-    private final ImmutableSetMultimap<URI, Module> namespaceToModules;
-    private final ImmutableSet<Module> modules;
+    private final Map<ModuleIdentifier, String> identifiersToSources;
+    private final SetMultimap<URI, Module> namespaceToModules;
+    private final SetMultimap<String, Module> nameToModules;
+    private final Set<Module> modules;
 
     SchemaContextImpl(final Set<Module> modules, final Map<ModuleIdentifier, String> identifiersToSources) {
         this.identifiersToSources = ImmutableMap.copyOf(identifiersToSources);
@@ -69,21 +84,29 @@ final class SchemaContextImpl implements SchemaContext {
         this.modules = ImmutableSet.copyOf(ModuleDependencySort.sort(modules.toArray(new Module[modules.size()])));
 
         /*
-         * The most common lookup is from Namespace->Module. Invest some quality time in
-         * building that up.
+         * The most common lookup is from Namespace->Module.
+         *
+         * RESTCONF performs lookups based on module name only, where it wants
+         * to receive the latest revision
+         *
+         * Invest some quality time in building up lookup tables for both.
          */
-        final SetMultimap<URI, Module> multimap = Multimaps.newSetMultimap(
-                new TreeMap<URI, Collection<Module>>(), URI_SET_SUPPLIER);
+        final SetMultimap<URI, Module> nsMap = Multimaps.newSetMultimap(
+                new TreeMap<URI, Collection<Module>>(), MODULE_SET_SUPPLIER);
+        final SetMultimap<String, Module> nameMap = Multimaps.newSetMultimap(
+                new TreeMap<String, Collection<Module>>(), MODULE_SET_SUPPLIER);
         for (Module m : modules) {
-            multimap.put(m.getNamespace(), m);
+            nameMap.put(m.getName(), m);
+            nsMap.put(m.getNamespace(), m);
         }
 
-        namespaceToModules = ImmutableSetMultimap.copyOf(multimap);
+        namespaceToModules = ImmutableSetMultimap.copyOf(nsMap);
+        nameToModules = ImmutableSetMultimap.copyOf(nameMap);
     }
 
     @Override
     public Set<DataSchemaNode> getDataDefinitions() {
-        final Set<DataSchemaNode> dataDefs = new HashSet<DataSchemaNode>();
+        final Set<DataSchemaNode> dataDefs = new HashSet<>();
         for (Module m : modules) {
             dataDefs.addAll(m.getChildNodes());
         }
@@ -97,7 +120,7 @@ final class SchemaContextImpl implements SchemaContext {
 
     @Override
     public Set<NotificationDefinition> getNotifications() {
-        final Set<NotificationDefinition> notifications = new HashSet<NotificationDefinition>();
+        final Set<NotificationDefinition> notifications = new HashSet<>();
         for (Module m : modules) {
             notifications.addAll(m.getNotifications());
         }
@@ -106,7 +129,7 @@ final class SchemaContextImpl implements SchemaContext {
 
     @Override
     public Set<RpcDefinition> getOperations() {
-        final Set<RpcDefinition> rpcs = new HashSet<RpcDefinition>();
+        final Set<RpcDefinition> rpcs = new HashSet<>();
         for (Module m : modules) {
             rpcs.addAll(m.getRpcs());
         }
@@ -115,7 +138,7 @@ final class SchemaContextImpl implements SchemaContext {
 
     @Override
     public Set<ExtensionDefinition> getExtensions() {
-        final Set<ExtensionDefinition> extensions = new HashSet<ExtensionDefinition>();
+        final Set<ExtensionDefinition> extensions = new HashSet<>();
         for (Module m : modules) {
             extensions.addAll(m.getExtensionSchemaNodes());
         }
@@ -124,17 +147,12 @@ final class SchemaContextImpl implements SchemaContext {
 
     @Override
     public Module findModuleByName(final String name, final Date revision) {
-        if (name != null) {
-            for (final Module module : modules) {
-                if (revision == null) {
-                    if (module.getName().equals(name)) {
-                        return module;
-                    }
-                } else if (module.getName().equals(name) && module.getRevision().equals(revision)) {
-                    return module;
-                }
+        for (final Module module : nameToModules.get(name)) {
+            if (revision == null || revision.equals(module.getRevision())) {
+                return module;
             }
         }
+
         return null;
     }
 
@@ -149,26 +167,9 @@ final class SchemaContextImpl implements SchemaContext {
         if (namespace == null) {
             return null;
         }
-        final Set<Module> modules = findModuleByNamespace(namespace);
-        if (modules.isEmpty()) {
-            return null;
-        }
-
-        if (revision == null) {
-            // FIXME: The ordering of modules in Multimap could just guarantee this...
-            TreeMap<Date, Module> map = new TreeMap<Date, Module>();
-            for (Module module : modules) {
-                map.put(module.getRevision(), module);
-            }
-            if (map.isEmpty()) {
-                return null;
-            }
-            return map.lastEntry().getValue();
-        } else {
-            for (Module module : modules) {
-                if (module.getRevision().equals(revision)) {
-                    return(module);
-                }
+        for (Module module : findModuleByNamespace(namespace)) {
+            if (revision == null || revision.equals(module.getRevision())) {
+                return module;
             }
         }
         return null;
@@ -257,26 +258,24 @@ final class SchemaContextImpl implements SchemaContext {
 
     @Override
     public DataSchemaNode getDataChildByName(final QName name) {
-        DataSchemaNode result = null;
         for (Module module : modules) {
-            result = module.getDataChildByName(name);
+            final DataSchemaNode result = module.getDataChildByName(name);
             if (result != null) {
-                break;
+                return result;
             }
         }
-        return result;
+        return null;
     }
 
     @Override
     public DataSchemaNode getDataChildByName(final String name) {
-        DataSchemaNode result = null;
         for (Module module : modules) {
-            result = module.getDataChildByName(name);
+            final DataSchemaNode result = module.getDataChildByName(name);
             if (result != null) {
-                break;
+                return result;
             }
         }
-        return result;
+        return null;
     }
 
     @Override
@@ -305,4 +304,11 @@ final class SchemaContextImpl implements SchemaContext {
         String maybeSource = identifiersToSources.get(moduleIdentifier);
         return Optional.fromNullable(maybeSource);
     }
+
+    @Override
+    public String toString() {
+        return "SchemaContextImpl{" +
+                "modules=" + modules +
+                '}';
+    }
 }