ModuleDependencySort now provides only static methods.
Change-Id: Ia407c30f3a99ffd2b5bd7b726590132a71c4fc49
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
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;
}
// 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) {
*/
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;
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()) {
}
}
- // 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);
/**
* 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();
/**
* 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;
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;
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));
}
}
: 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;
}
+ formatRevDate(revision) + "]";
}
+ public Object getReference() {
+ return originalObject;
+ }
+
}
}
/**
* Utility class that provides topological sort
*/
-public class TopologicalSort {
+public final class TopologicalSort {
/**
* Topological sort of dependent nodes in acyclic graphs.
*/
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;
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 {
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()));
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;
}
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;
}
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)));
@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)
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();
}
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;
+ }
}