Added support for Modules to ModuleDependencySort (beside ModuleBuilders). 57/357/3
authorMaros Marsalek <mmarsale@cisco.com>
Thu, 16 May 2013 09:34:08 +0000 (11:34 +0200)
committerMaros Marsalek <mmarsale@cisco.com>
Thu, 16 May 2013 13:44:26 +0000 (15:44 +0200)
ModuleDependencySort now provides only static methods.

Change-Id: Ia407c30f3a99ffd2b5bd7b726590132a71c4fc49
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/impl/YangParserImpl.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/ModuleDependencySort.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/TopologicalSort.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/util/ModuleDependencySortTest.java

index 7c2aa66..569036a 100644 (file)
@@ -77,7 +77,6 @@ import org.opendaylight.controller.yang.parser.builder.impl.TypedefBuilder;
 import org.opendaylight.controller.yang.parser.builder.impl.UnionTypeBuilder;
 import org.opendaylight.controller.yang.parser.builder.impl.UnknownSchemaNodeBuilder;
 import org.opendaylight.controller.yang.parser.util.ModuleDependencySort;
-import org.opendaylight.controller.yang.parser.util.ModuleDependencySort.ModuleSimple;
 import org.opendaylight.controller.yang.parser.util.ParserUtils;
 import org.opendaylight.controller.yang.parser.util.RefineHolder;
 import org.opendaylight.controller.yang.parser.util.TypeConstraints;
@@ -140,24 +139,9 @@ public class YangParserImpl implements YangModelParser {
         }
 
         // module dependency graph sorted
-        List<ModuleSimple> sorted = new ModuleDependencySort(builders).sort();
-
-        // TODO FIX THIS ASAP!
-        // FIXME this is just temp workaround the ModuleDependencySort MUST
-        // RETURN ordered List
-        // of SORTED and DEPENDECNY RESOLVED MODULE BUILDERS!!!!!!
-        final List<ModuleBuilder> orderedBuilders = new ArrayList<ModuleBuilder>();
-        for (final ModuleSimple ms : sorted) {
-            for (int i = 0; i < builders.length; ++i) {
-                if (ms.getName().equals(builders[i].getName())
-                        && ms.getRevision().equals(builders[i].getRevision())) {
-                    orderedBuilders.add(builders[i]);
-                }
-            }
-        }
-        // FIXME END OF WORKAROUND
+        List<ModuleBuilder> sorted = ModuleDependencySort.sort(builders);
 
-        for (ModuleBuilder builder : orderedBuilders) {
+        for (ModuleBuilder builder : sorted) {
             final String builderName = builder.getName();
             Date builderRevision = builder.getRevision();
             if (builderRevision == null) {
index 75b6009..8cf9cea 100644 (file)
@@ -7,11 +7,13 @@
  */
 package org.opendaylight.controller.yang.parser.util;
 
+import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.opendaylight.controller.yang.model.api.Module;
 import org.opendaylight.controller.yang.model.api.ModuleImport;
 import org.opendaylight.controller.yang.parser.builder.impl.ModuleBuilder;
 import org.opendaylight.controller.yang.parser.impl.YangParserListenerImpl;
@@ -38,32 +40,45 @@ public final class ModuleDependencySort {
     private static final Logger logger = LoggerFactory
             .getLogger(ModuleDependencySort.class);
 
-    private final Map<String, Map<Date, ModuleNodeImpl>> moduleGraph;
-
     /**
+     * Topological sort of module builder dependency graph.
      *
-     * @param builders
-     *            Source for module dependency graph.
-     * @throws YangValidationException
-     *             if 1. there are module:revision duplicates 2. there is
-     *             imported not existing module 3. module is imported twice
+     * @return Sorted list of Module builders. Modules can be further processed
+     *         in returned order.
      */
-    public ModuleDependencySort(ModuleBuilder... builders) {
-        this.moduleGraph = createModuleGraph(builders);
-    }
-
-    @VisibleForTesting
-    Map<String, Map<Date, ModuleNodeImpl>> getModuleGraph() {
-        return moduleGraph;
+    public static List<ModuleBuilder> sort(ModuleBuilder... builders) {
+        List<Node> sorted = sortInternal(Arrays.asList(builders));
+        // Cast to ModuleBuilder from Node and return
+        return Lists.transform(sorted, new Function<Node, ModuleBuilder>() {
+
+            @Override
+            public ModuleBuilder apply(Node input) {
+                return (ModuleBuilder) ((ModuleNodeImpl) input).getReference();
+            }
+        });
     }
 
     /**
      * Topological sort of module dependency graph.
      *
-     * @return Sorted list of modules. Modules can be further processed in
+     * @return Sorted list of Modules. Modules can be further processed in
      *         returned order.
      */
-    public List<ModuleSimple> sort() {
+    public static List<Module> sort(Module... modules) {
+        List<Node> sorted = sortInternal(Arrays.asList(modules));
+        // Cast to Module from Node and return
+        return Lists.transform(sorted, new Function<Node, Module>() {
+
+            @Override
+            public Module apply(Node input) {
+                return (Module) ((ModuleNodeImpl) input).getReference();
+            }
+        });
+    }
+
+    private static List<Node> sortInternal(List<?> modules) {
+        Map<String, Map<Date, ModuleNodeImpl>> moduleGraph = createModuleGraph(modules);
+
         Set<Node> nodes = Sets.newHashSet();
         for (Map<Date, ModuleNodeImpl> map : moduleGraph.values()) {
             for (ModuleNodeImpl node : map.values()) {
@@ -71,19 +86,12 @@ public final class ModuleDependencySort {
             }
         }
 
-        // Cast to ModuleNode from Node
-        return Lists.transform(TopologicalSort.sort(nodes),
-                new Function<Node, ModuleSimple>() {
-
-                    @Override
-                    public ModuleSimple apply(Node input) {
-                        return (ModuleSimple) input;
-                    }
-                });
+        return TopologicalSort.sort(nodes);
     }
 
-    private Map<String, Map<Date, ModuleNodeImpl>> createModuleGraph(
-            ModuleBuilder... builders) {
+    @VisibleForTesting
+    static Map<String, Map<Date, ModuleNodeImpl>> createModuleGraph(
+            List<?> builders) {
         Map<String, Map<Date, ModuleNodeImpl>> moduleGraph = Maps.newHashMap();
 
         processModules(moduleGraph, builders);
@@ -95,17 +103,33 @@ public final class ModuleDependencySort {
     /**
      * Extract module:revision from module builders
      */
-    private void processDependencies(
-            Map<String, Map<Date, ModuleNodeImpl>> moduleGraph,
-            ModuleBuilder... builders) {
+    private static void processDependencies(
+            Map<String, Map<Date, ModuleNodeImpl>> moduleGraph, List<?> builders) {
         Map<String, Date> imported = Maps.newHashMap();
 
         // Create edges in graph
-        for (ModuleBuilder mb : builders) {
-            String fromName = mb.getName();
-            Date fromRevision = mb.getRevision() == null ? DEFAULT_REVISION
-                    : mb.getRevision();
-            for (ModuleImport imprt : mb.getModuleImports()) {
+        for (Object mb : builders) {
+
+            String fromName = null;
+            Date fromRevision = null;
+            Set<ModuleImport> imports = null;
+
+            if (mb instanceof Module) {
+                fromName = ((Module) mb).getName();
+                fromRevision = ((Module) mb).getRevision();
+                imports = ((Module) mb).getImports();
+            } else if (mb instanceof ModuleBuilder) {
+                fromName = ((ModuleBuilder) mb).getName();
+                fromRevision = ((ModuleBuilder) mb).getRevision();
+                imports = ((ModuleBuilder) mb).getModuleImports();
+            }
+            // no need to check if other Type of object, check is performed in
+            // process modules
+
+            if (fromRevision == null)
+                fromRevision = DEFAULT_REVISION;
+
+            for (ModuleImport imprt : imports) {
                 String toName = imprt.getModuleName();
                 Date toRevision = imprt.getRevision() == null ? DEFAULT_REVISION
                         : imprt.getRevision();
@@ -137,7 +161,7 @@ public final class ModuleDependencySort {
     /**
      * Get imported module by its name and revision from moduleGraph
      */
-    private ModuleNodeImpl getModuleByNameAndRevision(
+    private static ModuleNodeImpl getModuleByNameAndRevision(
             Map<String, Map<Date, ModuleNodeImpl>> moduleGraph,
             String fromName, Date fromRevision, String toName, Date toRevision) {
         ModuleNodeImpl to = null;
@@ -165,22 +189,37 @@ public final class ModuleDependencySort {
         return to;
     }
 
-    private void ex(String message) {
+    private static void ex(String message) {
         throw new YangValidationException(message);
     }
 
     /**
-     * Extract dependencies from module builders to fill dependency graph
+     * Extract dependencies from module builders or modules to fill dependency
+     * graph
      */
-    private void processModules(
-            Map<String, Map<Date, ModuleNodeImpl>> moduleGraph,
-            ModuleBuilder... builders) {
+    private static void processModules(
+            Map<String, Map<Date, ModuleNodeImpl>> moduleGraph, List<?> builders) {
 
         // Process nodes
-        for (ModuleBuilder mb : builders) {
-            String name = mb.getName();
+        for (Object mb : builders) {
+
+            String name = null;
+            Date rev = null;
+
+            if (mb instanceof Module) {
+                name = ((Module) mb).getName();
+                rev = ((Module) mb).getRevision();
+            } else if (mb instanceof ModuleBuilder) {
+                name = ((ModuleBuilder) mb).getName();
+                rev = ((ModuleBuilder) mb).getRevision();
+            } else {
+                throw new IllegalStateException(
+                        String.format(
+                                "Unexpected type of node for sort, expected only:%s, %s, got:%s",
+                                Module.class, ModuleBuilder.class,
+                                mb.getClass()));
+            }
 
-            Date rev = mb.getRevision();
             if (rev == null)
                 rev = DEFAULT_REVISION;
 
@@ -191,7 +230,7 @@ public final class ModuleDependencySort {
                 ex(String.format("Module:%s with revision:%s declared twice",
                         name, formatRevDate(rev)));
 
-            moduleGraph.get(name).put(rev, new ModuleNodeImpl(name, rev));
+            moduleGraph.get(name).put(rev, new ModuleNodeImpl(name, rev, mb));
         }
     }
 
@@ -200,30 +239,22 @@ public final class ModuleDependencySort {
                 : YangParserListenerImpl.simpleDateFormat.format(rev);
     }
 
-    /**
-     * Simple representation of module. Contains name and revision.
-     */
-    public interface ModuleSimple {
-        String getName();
-
-        Date getRevision();
-    }
-
-    static class ModuleNodeImpl extends NodeImpl implements ModuleSimple {
+    @VisibleForTesting
+    static class ModuleNodeImpl extends NodeImpl {
         private final String name;
         private final Date revision;
+        private final Object originalObject;
 
-        public ModuleNodeImpl(String name, Date revision) {
+        public ModuleNodeImpl(String name, Date revision, Object builder) {
             this.name = name;
             this.revision = revision;
+            this.originalObject = builder;
         }
 
-        @Override
         public String getName() {
             return name;
         }
 
-        @Override
         public Date getRevision() {
             return revision;
         }
@@ -266,6 +297,10 @@ public final class ModuleDependencySort {
                     + formatRevDate(revision) + "]";
         }
 
+        public Object getReference() {
+            return originalObject;
+        }
+
     }
 
 }
index 195347a..484e34d 100644 (file)
@@ -7,12 +7,13 @@
  */
 package org.opendaylight.controller.yang.parser.util;
 
-import static org.hamcrest.core.AnyOf.anyOf;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import static org.junit.matchers.JUnitMatchers.containsString;
+import static org.hamcrest.core.AnyOf.*;
+import static org.hamcrest.core.Is.*;
+import static org.junit.Assert.*;
+import static org.junit.matchers.JUnitMatchers.*;
 import static org.mockito.Mockito.*;
 
+import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
@@ -21,21 +22,21 @@ import java.util.Set;
 
 import org.hamcrest.Matcher;
 import org.junit.Test;
+import org.opendaylight.controller.yang.model.api.Module;
 import org.opendaylight.controller.yang.model.api.ModuleImport;
 import org.opendaylight.controller.yang.parser.builder.impl.ModuleBuilder;
 import org.opendaylight.controller.yang.parser.impl.YangParserListenerImpl;
 import org.opendaylight.controller.yang.parser.util.ModuleDependencySort.ModuleNodeImpl;
-import org.opendaylight.controller.yang.parser.util.ModuleDependencySort.ModuleSimple;
 import org.opendaylight.controller.yang.parser.util.TopologicalSort.Edge;
 
 import com.google.common.collect.Sets;
 
 public class ModuleDependencySortTest {
 
-    private ModuleBuilder a = mockModule("a", null);
-    private ModuleBuilder b = mockModule("b", null);
-    private ModuleBuilder c = mockModule("c", null);
-    private ModuleBuilder d = mockModule("d", null);
+    private ModuleBuilder a = mockModuleBuilder("a", null);
+    private ModuleBuilder b = mockModuleBuilder("b", null);
+    private ModuleBuilder c = mockModuleBuilder("c", null);
+    private ModuleBuilder d = mockModuleBuilder("d", null);
 
     @Test
     public void testValid() throws Exception {
@@ -45,11 +46,11 @@ public class ModuleDependencySortTest {
         mockDependency(b, d);
 
         ModuleBuilder[] builders = new ModuleBuilder[] { d, b, c, a };
-        ModuleDependencySort sort = new ModuleDependencySort(builders);
 
-        assertDependencyGraph(sort.getModuleGraph());
+        List<ModuleBuilder> l = ModuleDependencySort.sort(builders);
 
-        List<ModuleSimple> l = sort.sort();
+        assertDependencyGraph(ModuleDependencySort.createModuleGraph(Arrays
+                .asList(builders)));
 
         @SuppressWarnings("unchecked")
         Matcher<String> cOrD = anyOf(is(c.getName()), is(d.getName()));
@@ -60,15 +61,37 @@ public class ModuleDependencySortTest {
         assertThat(l.get(3).getName(), is(a.getName()));
     }
 
+    @Test
+    public void testValidModule() throws Exception {
+
+        Date rev = new Date();
+        Module a = mockModule("a", rev);
+        Module b = mockModule("b", rev);
+        Module c = mockModule("c", rev);
+
+        mockDependency(a, b);
+        mockDependency(b, c);
+        mockDependency(a, c);
+
+        Module[] builders = new Module[] { a, b, c };
+
+        List<Module> l = ModuleDependencySort.sort(builders);
+
+        assertThat(l.get(0).getName(), is(c.getName()));
+        assertThat(l.get(1).getName(), is(b.getName()));
+        assertThat(l.get(2).getName(), is(a.getName()));
+    }
+
     @Test(expected = YangValidationException.class)
     public void testModuleTwice() throws Exception {
-        ModuleBuilder a2 = mockModule("a", null);
+        ModuleBuilder a2 = mockModuleBuilder("a", null);
 
         ModuleBuilder[] builders = new ModuleBuilder[] { a, a2 };
         try {
-            new ModuleDependencySort(builders);
+            ModuleDependencySort.sort(builders);
         } catch (YangValidationException e) {
-            assertThat(e.getMessage(),
+            assertThat(
+                    e.getMessage(),
                     containsString("Module:a with revision:default declared twice"));
             throw e;
         }
@@ -80,9 +103,10 @@ public class ModuleDependencySortTest {
 
         ModuleBuilder[] builders = new ModuleBuilder[] { a };
         try {
-            new ModuleDependencySort(builders);
+            ModuleDependencySort.sort(builders);
         } catch (YangValidationException e) {
-            assertThat(e.getMessage(),
+            assertThat(
+                    e.getMessage(),
                     containsString("Not existing module imported:b:default by:a:default"));
             throw e;
         }
@@ -94,23 +118,23 @@ public class ModuleDependencySortTest {
         mockDependency(c, b);
 
         ModuleBuilder[] builders = new ModuleBuilder[] { a, b, c };
-        new ModuleDependencySort(builders);
+        ModuleDependencySort.sort(builders);
     }
 
     @Test(expected = YangValidationException.class)
     public void testImportTwiceDifferentRevision() throws Exception {
         Date date = new Date();
-        ModuleBuilder b2 = mockModule("b", date);
+        ModuleBuilder b2 = mockModuleBuilder("b", date);
 
         mockDependency(a, b);
         mockDependency(c, b2);
 
         ModuleBuilder[] builders = new ModuleBuilder[] { a, c, b, b2 };
         try {
-            ModuleDependencySort aaa = new ModuleDependencySort(builders);
-            System.out.println(aaa.getModuleGraph());
+            ModuleDependencySort.sort(builders);
         } catch (YangValidationException e) {
-            assertThat(e.getMessage(),
+            assertThat(
+                    e.getMessage(),
                     containsString("Module:b imported twice with different revisions:default, "
                             + YangParserListenerImpl.simpleDateFormat
                                     .format(date)));
@@ -120,21 +144,21 @@ public class ModuleDependencySortTest {
 
     @Test
     public void testModuleTwiceWithDifferentRevs() throws Exception {
-        ModuleBuilder a2 = mockModule("a", new Date());
+        ModuleBuilder a2 = mockModuleBuilder("a", new Date());
 
         ModuleBuilder[] builders = new ModuleBuilder[] { a, a2 };
-        new ModuleDependencySort(builders);
+        ModuleDependencySort.sort(builders);
     }
 
     @Test(expected = YangValidationException.class)
     public void testModuleTwice2() throws Exception {
         Date rev = new Date();
-        ModuleBuilder a2 = mockModule("a", rev);
-        ModuleBuilder a3 = mockModule("a", rev);
+        ModuleBuilder a2 = mockModuleBuilder("a", rev);
+        ModuleBuilder a3 = mockModuleBuilder("a", rev);
 
         ModuleBuilder[] builders = new ModuleBuilder[] { a, a2, a3 };
         try {
-            new ModuleDependencySort(builders);
+            ModuleDependencySort.sort(builders);
         } catch (YangValidationException e) {
             assertThat(e.getMessage(), containsString("Module:a with revision:"
                     + YangParserListenerImpl.simpleDateFormat.format(rev)
@@ -179,7 +203,14 @@ public class ModuleDependencySortTest {
         a.getModuleImports().add(imprt);
     }
 
-    private ModuleBuilder mockModule(String name, Date rev) {
+    private void mockDependency(Module a, Module b) {
+        ModuleImport imprt = mock(ModuleImport.class);
+        doReturn(b.getName()).when(imprt).getModuleName();
+        doReturn(b.getRevision()).when(imprt).getRevision();
+        a.getImports().add(imprt);
+    }
+
+    private ModuleBuilder mockModuleBuilder(String name, Date rev) {
         ModuleBuilder a = mock(ModuleBuilder.class);
         doReturn(name).when(a).getName();
         Set<ModuleImport> set = Sets.newHashSet();
@@ -189,4 +220,15 @@ public class ModuleDependencySortTest {
         }
         return a;
     }
+
+    private Module mockModule(String name, Date rev) {
+        Module a = mock(Module.class);
+        doReturn(name).when(a).getName();
+        Set<ModuleImport> set = Sets.newHashSet();
+        doReturn(set).when(a).getImports();
+        if (rev != null) {
+            doReturn(rev).when(a).getRevision();
+        }
+        return a;
+    }
 }