From 8d0760923824b72f8279ea26b97377ae26a49bee Mon Sep 17 00:00:00 2001 From: Maros Marsalek Date: Thu, 16 May 2013 11:34:08 +0200 Subject: [PATCH] Added support for Modules to ModuleDependencySort (beside ModuleBuilders). ModuleDependencySort now provides only static methods. Change-Id: Ia407c30f3a99ffd2b5bd7b726590132a71c4fc49 Signed-off-by: Maros Marsalek --- .../yang/parser/impl/YangParserImpl.java | 20 +-- .../parser/util/ModuleDependencySort.java | 151 +++++++++++------- .../yang/parser/util/TopologicalSort.java | 2 +- .../parser/util/ModuleDependencySortTest.java | 98 ++++++++---- 4 files changed, 166 insertions(+), 105 deletions(-) diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/impl/YangParserImpl.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/impl/YangParserImpl.java index 7c2aa6692b..569036a1de 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/impl/YangParserImpl.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/impl/YangParserImpl.java @@ -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 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 orderedBuilders = new ArrayList(); - 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 sorted = ModuleDependencySort.sort(builders); - for (ModuleBuilder builder : orderedBuilders) { + for (ModuleBuilder builder : sorted) { final String builderName = builder.getName(); Date builderRevision = builder.getRevision(); if (builderRevision == null) { diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/ModuleDependencySort.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/ModuleDependencySort.java index 75b600902d..8cf9cea0cf 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/ModuleDependencySort.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/ModuleDependencySort.java @@ -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> 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> getModuleGraph() { - return moduleGraph; + public static List sort(ModuleBuilder... builders) { + List sorted = sortInternal(Arrays.asList(builders)); + // Cast to ModuleBuilder from Node and return + return Lists.transform(sorted, new Function() { + + @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 sort() { + public static List sort(Module... modules) { + List sorted = sortInternal(Arrays.asList(modules)); + // Cast to Module from Node and return + return Lists.transform(sorted, new Function() { + + @Override + public Module apply(Node input) { + return (Module) ((ModuleNodeImpl) input).getReference(); + } + }); + } + + private static List sortInternal(List modules) { + Map> moduleGraph = createModuleGraph(modules); + Set nodes = Sets.newHashSet(); for (Map 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() { - - @Override - public ModuleSimple apply(Node input) { - return (ModuleSimple) input; - } - }); + return TopologicalSort.sort(nodes); } - private Map> createModuleGraph( - ModuleBuilder... builders) { + @VisibleForTesting + static Map> createModuleGraph( + List builders) { Map> moduleGraph = Maps.newHashMap(); processModules(moduleGraph, builders); @@ -95,17 +103,33 @@ public final class ModuleDependencySort { /** * Extract module:revision from module builders */ - private void processDependencies( - Map> moduleGraph, - ModuleBuilder... builders) { + private static void processDependencies( + Map> moduleGraph, List builders) { Map 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 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> 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> moduleGraph, - ModuleBuilder... builders) { + private static void processModules( + Map> 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; + } + } } diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/TopologicalSort.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/TopologicalSort.java index 46c092ec66..2ea289a0f7 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/TopologicalSort.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/TopologicalSort.java @@ -17,7 +17,7 @@ import com.google.common.collect.Sets; /** * Utility class that provides topological sort */ -public class TopologicalSort { +public final class TopologicalSort { /** * Topological sort of dependent nodes in acyclic graphs. diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/util/ModuleDependencySortTest.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/util/ModuleDependencySortTest.java index 195347aac0..484e34d410 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/util/ModuleDependencySortTest.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/util/ModuleDependencySortTest.java @@ -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 l = ModuleDependencySort.sort(builders); - List l = sort.sort(); + assertDependencyGraph(ModuleDependencySort.createModuleGraph(Arrays + .asList(builders))); @SuppressWarnings("unchecked") Matcher 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 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 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 set = Sets.newHashSet(); + doReturn(set).when(a).getImports(); + if (rev != null) { + doReturn(rev).when(a).getRevision(); + } + return a; + } } -- 2.36.6