Propagate @NonNull collection annotations
[yangtools.git] / yang / yang-model-util / src / main / java / org / opendaylight / yangtools / yang / model / util / FilteringSchemaContextProxy.java
index feaa194c29409315dc57e9e25766db1f0a0239b1..d858276c901dd803a94a8f887b44fe63dbec9850 100644 (file)
@@ -5,46 +5,52 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-
 package org.opendaylight.yangtools.yang.model.util;
 
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSet.Builder;
 import com.google.common.collect.ImmutableSetMultimap;
-import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Multimap;
 import com.google.common.collect.Multimaps;
 import com.google.common.collect.SetMultimap;
 import com.google.common.collect.TreeMultimap;
 import java.net.URI;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Date;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import java.util.TreeMap;
 import java.util.function.Function;
-import javax.annotation.concurrent.Immutable;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.common.Revision;
 import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
+import org.opendaylight.yangtools.yang.model.api.ModuleLike;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.Submodule;
 
-@Immutable
 public final class FilteringSchemaContextProxy extends AbstractSchemaContext {
+    private final ImmutableMap<QNameModule, Module> moduleMap;
 
     //collection to be filled with filtered modules
-    private final Set<Module> filteredModules;
+    private final ImmutableSet<Module> filteredModules;
 
     //collections to be filled in with filtered data
-    private final SetMultimap<URI, Module> namespaceToModules;
-    private final SetMultimap<String, Module> nameToModules;
+    private final ImmutableSetMultimap<URI, Module> namespaceToModules;
+    private final ImmutableSetMultimap<String, Module> nameToModules;
 
     /**
      * Filters SchemaContext for yang modules.
@@ -56,27 +62,22 @@ public final class FilteringSchemaContextProxy extends AbstractSchemaContext {
      */
     public FilteringSchemaContextProxy(final SchemaContext delegate, final Collection<ModuleId> rootModules,
             final Set<ModuleId> additionalModuleIds) {
-        Preconditions.checkNotNull(rootModules, "Base modules cannot be null.");
-        Preconditions.checkNotNull(additionalModuleIds, "Additional modules cannot be null.");
+        requireNonNull(rootModules, "Base modules cannot be null.");
+        requireNonNull(additionalModuleIds, "Additional modules cannot be null.");
 
         final Builder<Module> filteredModulesBuilder = new Builder<>();
-        final SetMultimap<URI, Module> nsMap = Multimaps.newSetMultimap(new TreeMap<>(),
-            AbstractSchemaContext::createModuleSet);
-        final SetMultimap<String, Module> nameMap = Multimaps.newSetMultimap(new TreeMap<>(),
-            AbstractSchemaContext::createModuleSet);
 
-        ImmutableMap.Builder<ModuleIdentifier, String> identifiersToSourcesBuilder = ImmutableMap.builder();
-
-        //preparing map to get all modules with one name but difference in revision
-        final TreeMultimap<String, Module> nameToModulesAll = getStringModuleTreeMultimap();
+        // preparing map to get all modules with one name but difference in revision
+        final TreeMultimap<String, Module> nameToModulesAll = TreeMultimap.create(String::compareTo,
+            REVISION_COMPARATOR);
 
         nameToModulesAll.putAll(getStringModuleMap(delegate));
 
-        //in case there is a particular dependancy to view filteredModules/yang models
-        //dependancy is checked for module name and imports
+        // in case there is a particular dependency to view filteredModules/YANG models dependency is checked
+        // for module name and imports
         processForRootModules(delegate, rootModules, filteredModulesBuilder);
 
-        //adding additional modules
+        // adding additional modules
         processForAdditionalModules(delegate, additionalModuleIds, filteredModulesBuilder);
 
         filteredModulesBuilder.addAll(getImportedModules(
@@ -84,22 +85,26 @@ public final class FilteringSchemaContextProxy extends AbstractSchemaContext {
                 filteredModulesBuilder.build(), nameToModulesAll));
 
         /**
-         * Instead of doing this on each invocation of getModules(), pre-compute
-         * it once and keep it around -- better than the set we got in.
+         * Instead of doing this on each invocation of getModules(), pre-compute it once and keep it around.
          */
-        this.filteredModules = filteredModulesBuilder.build();
+        final List<Module> sortedModules = new ArrayList<>(filteredModulesBuilder.build());
+        sortedModules.sort(NAME_REVISION_COMPARATOR);
+        this.filteredModules = ImmutableSet.copyOf(sortedModules);
 
+        final SetMultimap<URI, Module> nsMap = Multimaps.newSetMultimap(new TreeMap<>(),
+            AbstractSchemaContext::createModuleSet);
+        final SetMultimap<String, Module> nameMap = Multimaps.newSetMultimap(new TreeMap<>(),
+            AbstractSchemaContext::createModuleSet);
+        final ImmutableMap.Builder<QNameModule, Module> moduleMapBuilder = ImmutableMap.builder();
         for (final Module module : filteredModules) {
             nameMap.put(module.getName(), module);
             nsMap.put(module.getNamespace(), module);
+            moduleMapBuilder.put(module.getQNameModule(), module);
         }
 
         namespaceToModules = ImmutableSetMultimap.copyOf(nsMap);
         nameToModules = ImmutableSetMultimap.copyOf(nameMap);
-    }
-
-    private static TreeMultimap<String, Module> getStringModuleTreeMultimap() {
-        return TreeMultimap.create(String::compareTo, REVISION_COMPARATOR);
+        moduleMap = moduleMapBuilder.build();
     }
 
     private static void processForAdditionalModules(final SchemaContext delegate,
@@ -114,21 +119,22 @@ public final class FilteringSchemaContextProxy extends AbstractSchemaContext {
             module -> checkModuleDependency(module, rootModules)));
     }
 
-    private static Multimap<String, Module> getStringModuleMap(final SchemaContext delegate) {
+    private static Multimap<String, ? extends Module> getStringModuleMap(final SchemaContext delegate) {
         return Multimaps.index(delegate.getModules(), Module::getName);
     }
 
     //dealing with imported module other than root and directly importing root
-    private static Collection<Module> getImportedModules(final Map<ModuleId, Module> allModules,
-            final Set<Module> baseModules, final TreeMultimap<String, Module> nameToModulesAll) {
+    private static Collection<Module> getImportedModules(final Map<ModuleId, ? extends @NonNull Module> allModules,
+            final Collection<? extends @NonNull Module> baseModules,
+            final TreeMultimap<String, Module> nameToModulesAll) {
 
-        List<Module> relatedModules = Lists.newLinkedList();
+        List<Module> relatedModules = new LinkedList<>();
 
         for (Module module : baseModules) {
             for (ModuleImport moduleImport : module.getImports()) {
-                Optional<Date> revisionDate = moduleImport.getRevision();
-                if (!revisionDate.isPresent()) {
-                    revisionDate = nameToModulesAll.get(moduleImport.getModuleName()).last().getRevision();
+                Optional<Revision> revisionDate = moduleImport.getRevision();
+                if (revisionDate.isEmpty()) {
+                    revisionDate = nameToModulesAll.get(moduleImport.getModuleName()).first().getRevision();
                 }
 
                 ModuleId key = new ModuleId(moduleImport.getModuleName(), revisionDate);
@@ -153,6 +159,11 @@ public final class FilteringSchemaContextProxy extends AbstractSchemaContext {
         return filteredModules;
     }
 
+    @Override
+    protected Map<QNameModule, Module> getModuleMap() {
+        return moduleMap;
+    }
+
     @Override
     protected SetMultimap<URI, Module> getNamespaceToModules() {
         return namespaceToModules;
@@ -168,30 +179,22 @@ public final class FilteringSchemaContextProxy extends AbstractSchemaContext {
     }
 
     //check for any dependency regarding given string
-    private boolean checkModuleDependency(final Module module, final Collection<ModuleId> rootModules) {
-
+    private boolean checkModuleDependency(final ModuleLike module, final Collection<ModuleId> rootModules) {
         for (ModuleId rootModule : rootModules) {
-
             if (rootModule.equals(new ModuleId(module.getName(), module.getRevision()))) {
                 return true;
             }
 
             //handling/checking imports regarding root modules
             for (ModuleImport moduleImport : module.getImports()) {
-
                 if (moduleImport.getModuleName().equals(rootModule.getName())) {
-
-                    if (moduleImport.getRevision().isPresent()
-                            && !moduleImport.getRevision().equals(rootModule.getRev())) {
-                        return false;
-                    }
-
-                    return true;
+                    return moduleImport.getRevision().isEmpty()
+                            || moduleImport.getRevision().equals(rootModule.getRev());
                 }
             }
 
             //submodules handling
-            for (Module moduleSub : module.getSubmodules()) {
+            for (Submodule moduleSub : module.getSubmodules()) {
                 return checkModuleDependency(moduleSub, rootModules);
             }
         }
@@ -206,13 +209,12 @@ public final class FilteringSchemaContextProxy extends AbstractSchemaContext {
 
     public static final class ModuleId {
         private final String name;
-        private final Date rev;
+        private final Revision rev;
 
-        public ModuleId(final String name, final Optional<Date> rev) {
-            Preconditions.checkArgument(!Strings.isNullOrEmpty(name),
-                    "No module dependency name given. Nothing to do.");
+        public ModuleId(final String name, final Optional<Revision> rev) {
+            checkArgument(!Strings.isNullOrEmpty(name), "No module dependency name given. Nothing to do.");
             this.name = name;
-            Preconditions.checkArgument(rev.isPresent(), "No revision date given. Nothing to do.");
+            checkArgument(rev.isPresent(), "No revision date given. Nothing to do.");
             this.rev = rev.get();
         }
 
@@ -220,7 +222,7 @@ public final class FilteringSchemaContextProxy extends AbstractSchemaContext {
             return name;
         }
 
-        public Optional<Date> getRev() {
+        public Optional<Revision> getRev() {
             return Optional.ofNullable(rev);
         }