/** * Obtain the {@link Module#getAdditionalModules()} of this module and all its * {@link Module.Util#transitiveDependenciesOf(Module) transitive dependencies}. * * <p> * No guarantees are made as to the order of these additional module classes. * </p> */ static List<Class<?>> transitiveAdditionalModulesOf(Module module) { final Set<Class<?>> modules = Sets.newHashSet(); final List<Module> transitiveDependencies = transitiveDependenciesOf(module); for (Module transitiveDependency : transitiveDependencies) { final Set<Class<?>> additionalModules = transitiveDependency.getAdditionalModules(); if(additionalModules != null && !additionalModules.isEmpty()) { for (Class<?> clazz : additionalModules) { if(Module.class.isAssignableFrom(clazz)) { throw new IllegalArgumentException("Module " + transitiveDependency + " has returned " + clazz + " from getAdditionalModules(). This class implements 'Module' interface so should instead be returned from getDependencies()"); } } modules.addAll(additionalModules); } } return Lists.newArrayList(modules); }
private static void appendDependenciesTo( final List<Module> ordered, final Module module, final List<Module> visited) { if(visited.contains(module)) { throw new IllegalStateException(String.format( "Cyclic dependency detected; visited: %s", visited)); } else { visited.add(module); } final Set<Module> dependencies = module.getDependencies(); if(dependencies.isEmpty() || ordered.containsAll(dependencies)) { ordered.add(module); visited.clear(); // reset } else { for (Module dependency : dependencies) { appendDependenciesTo(ordered, dependency, visited); } } if(!ordered.contains(module)) { ordered.add(module); } }
/** * Obtain the {@link #getAdditionalServices()} of this module and all its * {@link Module.Util#transitiveDependenciesOf(Module) transitive dependencies}. * * <p> * No guarantees are made as to the order of these additional service classes. * </p> */ static List<Class<?>> transitiveAdditionalServicesOf(Module module) { final Set<Class<?>> services = Sets.newHashSet(); final List<Module> transitiveDependencies = Util.transitiveDependenciesOf(module); for (Module transitiveDependency : transitiveDependencies) { final Set<Class<?>> additionalServices = transitiveDependency.getAdditionalServices(); if(additionalServices != null && !additionalServices.isEmpty()) { services.addAll(additionalServices); } } return Lists.newArrayList(services); }
/** * Recursively obtain the transitive dependencies. * * <p> * The dependencies are returned in order, with this (the top-most) module last. * </p> */ static List<Module> transitiveDependenciesOf(Module module) { final List<Module> ordered = Lists.newArrayList(); final List<Module> visited = Lists.newArrayList(); appendDependenciesTo(ordered, module, visited); final LinkedHashSet<Module> sequencedSet = Sets.newLinkedHashSet(ordered); return Lists.newArrayList(sequencedSet); }
static Map<String, String> transitiveIndividualConfigPropsOf(final Module module) { final Map<String,String> transitiveIndividualConfigProps = Maps.newLinkedHashMap(); final List<Module> transitiveDependencies = transitiveDependenciesOf(module); for (Module transitiveDependency : transitiveDependencies) { transitiveIndividualConfigProps.putAll(transitiveDependency.getIndividualConfigProps()); } return transitiveIndividualConfigProps; }
void assertTransitiveDependencies( final Module module, final List<Module> expected) { final List<Module> dependencies = Module.Util.transitiveDependenciesOf(module); assertTrue(dependencies.containsAll(expected)); assertTrue(expected.containsAll(dependencies)); }
static List<PropertyResource> transitivePropertyResourcesOf(final Module module) { final List<PropertyResource> transitivePropertyResources = Lists.newArrayList(); final List<Module> transitiveDependencies = transitiveDependenciesOf(module); for (Module transitiveDependency : transitiveDependencies) { transitivePropertyResources.addAll(transitiveDependency.getPropertyResources()); } return transitivePropertyResources; } }
void assertTransitiveDependenciesAsClass( final Module module, final List<Class<?>> expected) { final List<Class<?>> dependenciesAsClass = Module.Util.transitiveAdditionalModulesOf(module); assertTrue(dependenciesAsClass.containsAll(expected)); assertTrue(expected.containsAll(dependenciesAsClass)); }
@Test public void with_cyclic_dependencies() throws Exception { expectedException.expect(IllegalStateException.class); Module.Util.transitiveDependenciesOf(moduleG); }
void assertTransitiveServices( final Module module, final List<Class<?>> expected) { final List<Class<?>> services = Module.Util.transitiveAdditionalServicesOf(module); assertTrue(services.containsAll(expected)); assertTrue(expected.containsAll(services)); }
void withTransitiveFrom(final Module module) { withAdditionalModules(asClasses(Module.Util.transitiveDependenciesOf(module))); withAdditionalModules(Module.Util.transitiveAdditionalModulesOf(module)); withAdditionalServices(Module.Util.transitiveAdditionalServicesOf(module)); withConfigurationPropertyResources(Module.Util.transitivePropertyResourcesOf(module)); withConfigurationProperties(Module.Util.transitiveIndividualConfigPropsOf(module)); }