X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;ds=sidebyside;f=yang%2Fyang-parser-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fparser%2Futil%2FModuleDependencySort.java;h=ebf6fe278d96e66d70aaf2c0eec7f97b326dd1ee;hb=2d529417d7214a4e0222f7dff84fe24ea245673e;hp=8f22718eb865f3dd5acbebdd7bb07a727fcb0524;hpb=477333e9a7b39a5f3ac51cd81aa42cc4ed3d6581;p=yangtools.git diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/util/ModuleDependencySort.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/util/ModuleDependencySort.java index 8f22718eb8..ebf6fe278d 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/util/ModuleDependencySort.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/util/ModuleDependencySort.java @@ -7,40 +7,45 @@ */ package org.opendaylight.yangtools.yang.parser.util; -import java.text.SimpleDateFormat; -import java.util.ArrayList; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import java.net.URI; import java.util.Arrays; -import java.util.Collections; +import java.util.Collection; import java.util.Date; +import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; - +import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil; +import org.opendaylight.yangtools.yang.common.YangVersion; import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.ModuleImport; -import org.opendaylight.yangtools.yang.model.api.SchemaContext; -import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleBuilder; import org.opendaylight.yangtools.yang.parser.util.TopologicalSort.Node; import org.opendaylight.yangtools.yang.parser.util.TopologicalSort.NodeImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Function; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; - /** - * Creates a module dependency graph from provided {@link ModuleBuilder}s and - * provides a {@link #sort(ModuleBuilder...)} method. It is topological sort and + * Creates a module dependency graph from provided {@link Module}s and + * provides a {@link #sort(Module...)} method. It is topological sort and * returns modules in order in which they should be processed (e.g. if A imports * B, sort returns {B, A}). */ public final class ModuleDependencySort { - private static final Date DEFAULT_REVISION = new Date(0); + private static final Date DEFAULT_REVISION = SimpleDateFormatUtil.DEFAULT_DATE_REV; private static final Logger LOGGER = LoggerFactory.getLogger(ModuleDependencySort.class); + private static final Function TOPOLOGY_FUNCTION = input -> { + if (input == null) { + return null; + } + return ((ModuleNodeImpl) input).getReference(); + }; /** * It is not desirable to instance this class @@ -49,67 +54,35 @@ public final class ModuleDependencySort { } /** - * Topological sort of module builder dependency graph. + * Topological sort of module dependency graph. * - * @return Sorted list of Module builders. Modules can be further processed - * in returned order. + * @param modules YANG modules + * @return Sorted list of Modules. Modules can be further processed in + * returned order. */ - 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(); - } - }); - } - - public static List sortWithContext(SchemaContext context, ModuleBuilder... builders) { - List modules = new ArrayList(); - Collections.addAll(modules, builders); - modules.addAll(context.getModules()); - - List sorted = sortInternal(modules); - // Cast to ModuleBuilder from Node if possible and return - return Lists.transform(sorted, new Function() { - - @Override - public ModuleBuilder apply(Node input) { - if (((ModuleNodeImpl) input).getReference() instanceof ModuleBuilder) { - return (ModuleBuilder) ((ModuleNodeImpl) input).getReference(); - } else { - return null; - } - } - }); + public static List sort(final Module... modules) { + return sort(Arrays.asList(modules)); } /** * Topological sort of module dependency graph. * + * @param modules YANG modules * @return Sorted list of Modules. Modules can be further processed in * returned order. */ - public static List sort(Module... modules) { - List sorted = sortInternal(Arrays.asList(modules)); + public static List sort(final Iterable modules) { + final List sorted = sortInternal(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(); - } - }); + return Lists.transform(sorted, TOPOLOGY_FUNCTION); } - private static List sortInternal(List modules) { - Map> moduleGraph = createModuleGraph(modules); + private static List sortInternal(final Iterable modules) { + final Map> moduleGraph = createModuleGraph(modules); - Set nodes = Sets.newHashSet(); - for (Map map : moduleGraph.values()) { - for (ModuleNodeImpl node : map.values()) { + final Set nodes = Sets.newHashSet(); + for (final Map map : moduleGraph.values()) { + for (final ModuleNodeImpl node : map.values()) { nodes.add(node); } } @@ -118,8 +91,8 @@ public final class ModuleDependencySort { } @VisibleForTesting - static Map> createModuleGraph(List builders) { - Map> moduleGraph = Maps.newHashMap(); + static Map> createModuleGraph(final Iterable builders) { + final Map> moduleGraph = Maps.newHashMap(); processModules(moduleGraph, builders); processDependencies(moduleGraph, builders); @@ -130,26 +103,38 @@ public final class ModuleDependencySort { /** * Extract module:revision from module builders */ - private static void processDependencies(Map> moduleGraph, List builders) { - + private static void processDependencies(final Map> moduleGraph, + final Iterable mmbs) { + final Map allNS = new HashMap<>(); // Create edges in graph - for (Object mb : builders) { - Map imported = Maps.newHashMap(); - - 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(); + for (final Module module : mmbs) { + final Map imported = Maps.newHashMap(); + + String fromName; + Date fromRevision; + Collection imports; + URI ns; + + fromName = module.getName(); + fromRevision = module.getRevision(); + imports = module.getImports(); + ns = module.getNamespace(); + + // check for existence of module with same namespace + if (allNS.containsKey(ns)) { + final Module mod = allNS.get(ns); + final String name = mod.getName(); + final Date revision = mod.getRevision(); + if (!fromName.equals(name)) { + LOGGER.warn( + "Error while sorting module [{}, {}]: module with same namespace ({}) already loaded: [{}, {}]", + fromName, fromRevision, ns, name, revision); + } + } else { + allNS.put(ns, module); } + // no need to check if other Type of object, check is performed in // process modules @@ -157,20 +142,21 @@ public final class ModuleDependencySort { fromRevision = DEFAULT_REVISION; } - for (ModuleImport imprt : imports) { - String toName = imprt.getModuleName(); - Date toRevision = imprt.getRevision() == null ? DEFAULT_REVISION : imprt.getRevision(); + for (final ModuleImport imprt : imports) { + final String toName = imprt.getModuleName(); + final Date toRevision = imprt.getRevision() == null ? DEFAULT_REVISION : imprt.getRevision(); - ModuleNodeImpl from = moduleGraph.get(fromName).get(fromRevision); + final ModuleNodeImpl from = moduleGraph.get(fromName).get(fromRevision); - ModuleNodeImpl to = getModuleByNameAndRevision(moduleGraph, fromName, fromRevision, toName, toRevision); + final ModuleNodeImpl to = getModuleByNameAndRevision(moduleGraph, fromName, fromRevision, toName, toRevision); /* - * Check imports: If module is imported twice with different + * If it is an yang 1 module, check imports: If module is imported twice with different * revisions then throw exception */ - if (imported.get(toName) != null && !imported.get(toName).equals(toRevision) - && !imported.get(toName).equals(DEFAULT_REVISION) && !toRevision.equals(DEFAULT_REVISION)) { + if (YangVersion.VERSION_1.toString().equals(module.getYangVersion()) && imported.get(toName) != null + && !imported.get(toName).equals(toRevision) && !imported.get(toName).equals(DEFAULT_REVISION) + && !toRevision.equals(DEFAULT_REVISION)) { ex(String.format("Module:%s imported twice with different revisions:%s, %s", toName, formatRevDate(imported.get(toName)), formatRevDate(toRevision))); } @@ -185,8 +171,8 @@ public final class ModuleDependencySort { /** * Get imported module by its name and revision from moduleGraph */ - private static ModuleNodeImpl getModuleByNameAndRevision(Map> moduleGraph, - String fromName, Date fromRevision, String toName, Date toRevision) { + private static ModuleNodeImpl getModuleByNameAndRevision(final Map> moduleGraph, + final String fromName, final Date fromRevision, final String toName, final Date toRevision) { ModuleNodeImpl to = null; if (moduleGraph.get(toName) == null || !moduleGraph.get(toName).containsKey(toRevision)) { @@ -195,7 +181,7 @@ public final class ModuleDependencySort { if (moduleGraph.get(toName) != null && !moduleGraph.get(toName).isEmpty() && toRevision.equals(DEFAULT_REVISION)) { to = moduleGraph.get(toName).values().iterator().next(); - LOGGER.debug(String + LOGGER.trace(String .format("Import:%s:%s by module:%s:%s does not specify revision, using:%s:%s for module dependency sort", toName, formatRevDate(toRevision), fromName, formatRevDate(fromRevision), to.getName(), formatRevDate(to.getRevision()))); @@ -212,7 +198,7 @@ public final class ModuleDependencySort { return to; } - private static void ex(String message) { + private static void ex(final String message) { throw new YangValidationException(message); } @@ -220,56 +206,44 @@ public final class ModuleDependencySort { * Extract dependencies from module builders or modules to fill dependency * graph */ - private static void processModules(Map> moduleGraph, List builders) { + private static void processModules(final Map> moduleGraph, + final Iterable modules) { // Process nodes - 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())); - } + for (final Module momb : modules) { + final String name = momb.getName(); + Date rev = momb.getRevision(); if (rev == null) { rev = DEFAULT_REVISION; } if (moduleGraph.get(name) == null) { - moduleGraph.put(name, Maps. newHashMap()); + moduleGraph.put(name, Maps.newHashMap()); } if (moduleGraph.get(name).get(rev) != null) { ex(String.format("Module:%s with revision:%s declared twice", name, formatRevDate(rev))); } - moduleGraph.get(name).put(rev, new ModuleNodeImpl(name, rev, mb)); + moduleGraph.get(name).put(rev, new ModuleNodeImpl(name, rev, momb)); } } - private static String formatRevDate(Date rev) { - return rev.equals(DEFAULT_REVISION) ? "default" : new SimpleDateFormat("yyyy-MM-dd").format(rev); + private static String formatRevDate(final Date rev) { + return rev.equals(DEFAULT_REVISION) ? "default" : SimpleDateFormatUtil.getRevisionFormat().format(rev); } @VisibleForTesting static class ModuleNodeImpl extends NodeImpl { private final String name; private final Date revision; - private final Object originalObject; + private final Module originalObject; - public ModuleNodeImpl(String name, Date revision, Object builder) { + public ModuleNodeImpl(final String name, final Date revision, final Module module) { this.name = name; this.revision = revision; - this.originalObject = builder; + this.originalObject = module; } public String getName() { @@ -284,13 +258,13 @@ public final class ModuleDependencySort { public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((name == null) ? 0 : name.hashCode()); - result = prime * result + ((revision == null) ? 0 : revision.hashCode()); + result = prime * result + Objects.hashCode(name); + result = prime * result + Objects.hashCode(revision); return result; } @Override - public boolean equals(Object obj) { + public boolean equals(final Object obj) { if (this == obj) { return true; } @@ -300,7 +274,7 @@ public final class ModuleDependencySort { if (getClass() != obj.getClass()) { return false; } - ModuleNodeImpl other = (ModuleNodeImpl) obj; + final ModuleNodeImpl other = (ModuleNodeImpl) obj; if (name == null) { if (other.name != null) { return false; @@ -323,7 +297,7 @@ public final class ModuleDependencySort { return "Module [name=" + name + ", revision=" + formatRevDate(revision) + "]"; } - public Object getReference() { + public Module getReference() { return originalObject; }