Clarify SchemaContext getModules() API contract 23/65823/5
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 22 Nov 2017 00:20:31 +0000 (01:20 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Wed, 22 Nov 2017 14:56:02 +0000 (15:56 +0100)
This clarifies the API contract with regards to iteration ordering
and shuffles the methods around a bit. Also creates additional index
for looking up Module by its QNameModule, which is common when
dealing with NormalizedNode encoding.

Change-Id: I76a8f2f24f4a70e0cf4fab544de6d79e1b476103
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/SchemaContext.java
yang/yang-model-immutable/src/main/java/org/opendaylight/yangtools/yang/model/immutable/AbstractSchemaContext.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/AbstractSchemaContext.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/FilteringSchemaContextProxy.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/SimpleSchemaContext.java

index 9faf3fc76b07e7861bcabbdf06f4616d9736d1c4..50311a1c5e163fea1a93f52112b4d3533adf242f 100644 (file)
@@ -44,7 +44,9 @@ public interface SchemaContext extends ContainerSchemaNode {
     Set<DataSchemaNode> getDataDefinitions();
 
     /**
-     * Returns modules which are part of the schema context.
+     * Returns modules which are part of the schema context. Returned set is required to have its iteration ordered
+     * by module revision, so that if modules are filtered by {@link Module#getName()} or {@link Module#getNamespace()},
+     * modules having the same attribute are encountered newest revision first.
      *
      * @return set of the modules which belong to the schema context
      */
@@ -60,7 +62,7 @@ public interface SchemaContext extends ContainerSchemaNode {
     Set<RpcDefinition> getOperations();
 
     /**
-     * Returns extencion definition instances which are defined as the direct
+     * Returns extension definition instances which are defined as the direct
      * subelements in all YANG modules in the context.
      *
      * @return set of <code>ExtensionDefinition</code> instances which
@@ -69,31 +71,70 @@ public interface SchemaContext extends ContainerSchemaNode {
     Set<ExtensionDefinition> getExtensions();
 
     /**
-     * Returns module instance (from the context) with concrete name and revision date.
+     * Returns the module matching specified {@link QNameModule}, if present.
      *
-     * @param name
-     *            string with the module name
+     * @param qnameModule requested QNameModule
+     * @return Module, if present.
+     * @throws NullPointerException if qnameModule is null
+     */
+    Optional<Module> findModule(QNameModule qnameModule);
+
+    /**
+     * Returns module instance (from the context) with specified namespace and no revision.
+     *
+     * @param namespace
+     *            module namespace
+     * @return module instance which has name and revision the same as are the values specified in parameters
+     *         <code>namespace</code> and no revision.
+     */
+    default Optional<Module> findModule(final URI namespace) {
+        return findModule(QNameModule.create(namespace));
+    }
+
+    /**
+     * Returns module instance (from the context) with specified namespace and revision.
+     *
+     * @param namespace
+     *            module namespace
      * @param revision
-     *            date of the module revision
+     *            module revision, may be null
      * @return module instance which has name and revision the same as are the values specified in parameters
-     *         <code>name</code> and <code>revision</code>.
+     *         <code>namespace</code> and <code>revision</code>.
      */
-    Optional<Module> findModule(String name, Optional<Revision> revision);
+    default Optional<Module> findModule(final URI namespace, @Nullable final Revision revision) {
+        return findModule(QNameModule.create(namespace, revision));
+    }
 
     /**
-     * Returns module instance (from the context) with concrete name and revision date.
+     * Returns module instance (from the context) with specified namespace and revision.
+     *
+     * @param namespace
+     *            module namespace
+     * @param revision
+     *            module revision, may be null
+     * @return module instance which has name and revision the same as are the values specified in parameters
+     *         <code>namespace</code> and <code>revision</code>.
+     */
+    default Optional<Module> findModule(final URI namespace, final Optional<Revision> revision) {
+        return findModule(QNameModule.create(namespace, revision));
+    }
+
+    /**
+     * Returns module instance (from the context) with specified name and an optional revision.
      *
      * @param name
      *            string with the module name
+     * @param revision
+     *            date of the module revision
      * @return module instance which has name and revision the same as are the values specified in parameters
-     *         <code>name</code> and <code>revision</code>.
+     *                <code>name</code> and <code>revision</code>.
      */
-    default Optional<Module> findModule(final String name) {
-        return findModule(name, Optional.empty());
+    default Optional<Module> findModule(final String name, final Optional<Revision> revision) {
+        return findModules(name).stream().filter(module -> revision.equals(module.getRevision())).findAny();
     }
 
     /**
-     * Returns module instance (from the context) with concrete name and revision date.
+     * Returns module instance (from the context) with specified name and revision.
      *
      * @param name
      *            string with the module name
@@ -106,24 +147,21 @@ public interface SchemaContext extends ContainerSchemaNode {
         return findModule(name, Optional.ofNullable(revision));
     }
 
-    default Optional<Module> findModule(final URI namespace) {
-        return findModule(QNameModule.create(namespace));
-    }
-
-    default Optional<Module> findModule(final URI namespace, @Nullable final Revision revision) {
-        return findModule(QNameModule.create(namespace, revision));
-    }
-
-    default Optional<Module> findModule(final URI namespace, final Optional<Revision> revision) {
-        return findModule(QNameModule.create(namespace, revision));
-    }
-
-    default Optional<Module> findModule(final QNameModule qnameModule) {
-        return getModules().stream().filter(m -> qnameModule.equals(m.getQNameModule())).findAny();
+    /**
+     * Returns module instance (from the context) with specified name and no revision.
+     *
+     * @param name string with the module name
+     * @return module instance which has name and revision the same as are the values specified in <code>name</code>
+     *                and no revision.
+     * @throws NullPointerException if name is null
+     */
+    default Optional<Module> findModule(final String name) {
+        return findModule(name, Optional.empty());
     }
 
     /**
-     * Returns module instances (from the context) with a concrete name.
+     * Returns module instances (from the context) with a concrete name. Returned Set is required to have its iteration
+     * order guarantee that the latest revision is encountered first.
      *
      * @param name
      *            string with the module name
@@ -134,7 +172,8 @@ public interface SchemaContext extends ContainerSchemaNode {
     }
 
     /**
-     * Returns module instance (from the context) with concrete namespace.
+     * Returns module instance (from the context) with concrete namespace. Returned Set is required to have its
+     * iteration order guarantee that the latest revision is encountered first.
      *
      * @param namespace
      *            URI instance with specified namespace
index 70761e479697d611a0699885ecc55ebf4dac9c7f..c6603472c2efb64ebef49acb2489a3cbe50fd6cb 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.yangtools.yang.model.immutable;
 
 import java.util.Optional;
 import org.immutables.value.Value;
+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.SchemaContext;
@@ -16,6 +17,11 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 @Value.Immutable
 abstract class AbstractSchemaContext extends CommonContainerSchemaNode implements SchemaContext {
 
+    @Override
+    public Optional<Module> findModule(final QNameModule qnameModule) {
+        throw new UnsupportedOperationException("Not implemented");
+    }
+
     @Override
     public Optional<Module> findModule(final String name, final Optional<Revision> revision) {
         throw new UnsupportedOperationException("Not implemented");
index 3427bd5b2a5b44eb59eed4d7af67074ca27009ba..be3e24d5834523b807b4b4a17f0913043ae161fb 100644 (file)
@@ -18,11 +18,13 @@ import java.util.Comparator;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import java.util.TreeSet;
 import javax.annotation.Nonnull;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.common.Revision;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
@@ -60,6 +62,13 @@ public abstract class AbstractSchemaContext implements SchemaContext {
      */
     protected abstract SetMultimap<String, Module> getNameToModules();
 
+    /**
+     * Returns the namespace+revision-to-module mapping.
+     *
+     * @return Map of modules where key is Module's QNameModule.
+     */
+    protected abstract Map<QNameModule, Module> getModuleMap();
+
     @Override
     public Set<DataSchemaNode> getDataDefinitions() {
         final Set<DataSchemaNode> dataDefs = new HashSet<>();
@@ -96,7 +105,6 @@ public abstract class AbstractSchemaContext implements SchemaContext {
         return extensions;
     }
 
-
     @Override
     public Optional<Module> findModule(final String name, final Optional<Revision> revision) {
         for (final Module module : getNameToModules().get(name)) {
@@ -108,10 +116,19 @@ public abstract class AbstractSchemaContext implements SchemaContext {
         return Optional.empty();
     }
 
+    @Override
+    public Optional<Module> findModule(final QNameModule qnameModule) {
+        return Optional.ofNullable(getModuleMap().get(qnameModule));
+    }
+
     @Override
     public Set<Module> findModules(final URI namespace) {
-        final Set<Module> ret = getNamespaceToModules().get(namespace);
-        return ret == null ? Collections.emptySet() : ret;
+        return getNamespaceToModules().get(namespace);
+    }
+
+    @Override
+    public Set<Module> findModules(final String name) {
+        return getNameToModules().get(name);
     }
 
     @Override
index 3e3a0f22c57eb2655d41077bc31073da0ca7b4d6..b7a599fa092496deb201143caedefa6aff6ac00d 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.yangtools.yang.model.util;
 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.Builder;
 import com.google.common.collect.ImmutableSetMultimap;
 import com.google.common.collect.Lists;
@@ -29,6 +30,7 @@ import java.util.Set;
 import java.util.TreeMap;
 import java.util.function.Function;
 import javax.annotation.concurrent.Immutable;
+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.ModuleImport;
@@ -36,6 +38,7 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
 @Immutable
 public final class FilteringSchemaContextProxy extends AbstractSchemaContext {
+    private final Map<QNameModule, Module> moduleMap;
 
     //collection to be filled with filtered modules
     private final Set<Module> filteredModules;
@@ -58,10 +61,6 @@ public final class FilteringSchemaContextProxy extends AbstractSchemaContext {
         Preconditions.checkNotNull(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);
 
         // preparing map to get all modules with one name but difference in revision
         final TreeMultimap<String, Module> nameToModulesAll = getStringModuleTreeMultimap();
@@ -85,13 +84,20 @@ public final class FilteringSchemaContextProxy extends AbstractSchemaContext {
          */
         this.filteredModules = filteredModulesBuilder.build();
 
+        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);
+        moduleMap = moduleMapBuilder.build();
     }
 
     private static TreeMultimap<String, Module> getStringModuleTreeMultimap() {
@@ -149,6 +155,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;
index 878d9016ed3bdb046a9db601bf0310a991234c69..3e860502ac67e71440d3ebd23306a8c10b6d5f34 100644 (file)
@@ -10,13 +10,17 @@ package org.opendaylight.yangtools.yang.model.util;
 import com.google.common.annotations.Beta;
 import com.google.common.base.MoreObjects;
 import com.google.common.base.MoreObjects.ToStringHelper;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
 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.Map;
 import java.util.Set;
 import java.util.TreeMap;
+import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.model.api.Module;
 
 /**
@@ -28,6 +32,7 @@ import org.opendaylight.yangtools.yang.model.api.Module;
 public class SimpleSchemaContext extends AbstractSchemaContext {
     private final SetMultimap<URI, Module> namespaceToModules;
     private final SetMultimap<String, Module> nameToModules;
+    private final Map<QNameModule, Module> moduleMap;
     private final Set<Module> modules;
 
     protected SimpleSchemaContext(final Set<Module> modules) {
@@ -49,13 +54,16 @@ public class SimpleSchemaContext extends AbstractSchemaContext {
             AbstractSchemaContext::createModuleSet);
         final SetMultimap<String, Module> nameMap = Multimaps.newSetMultimap(new TreeMap<>(),
             AbstractSchemaContext::createModuleSet);
+        final Builder<QNameModule, Module> moduleMapBuilder = ImmutableMap.builder();
         for (Module m : modules) {
             nameMap.put(m.getName(), m);
             nsMap.put(m.getNamespace(), m);
+            moduleMapBuilder.put(m.getQNameModule(), m);
         }
 
         namespaceToModules = ImmutableSetMultimap.copyOf(nsMap);
         nameToModules = ImmutableSetMultimap.copyOf(nameMap);
+        moduleMap = moduleMapBuilder.build();
     }
 
     /**
@@ -71,6 +79,11 @@ public class SimpleSchemaContext extends AbstractSchemaContext {
         return modules;
     }
 
+    @Override
+    protected Map<QNameModule, Module> getModuleMap() {
+        return moduleMap;
+    }
+
     @Override
     protected final SetMultimap<URI, Module> getNamespaceToModules() {
         return namespaceToModules;