List of usage examples for com.google.common.graph EndpointPair ordered
public static <N> EndpointPair<N> ordered(N source, N target)
From source file:com.techshroom.wood.module.ModuleDependencySolver.java
ImmutableList<Module> computeDependencyOrder() {
// Fast-track no module case
if (this.moduleMap.isEmpty()) {
return ImmutableList.of();
}/*from w ww . j a va 2s . com*/
// If a node goes from A->B, A must be loaded AFTER B
MutableGraph<ModuleMetadata> depGraph = GraphBuilder.directed().allowsSelfLoops(false)
.expectedNodeCount(this.moduleMap.size()).build();
// Insert all nodes before connecting
this.moduleMap.values().stream().map(Module::getMetadata).forEach(depGraph::addNode);
for (Module factory : this.moduleMap.values()) {
ModuleMetadata data = factory.getMetadata();
data.getLoadAfterModules().forEach(dep -> {
Range<SemVer> acceptable = dep.getVersionRange();
// Here, we must load data after meta, put data->meta
depGraph.nodes().stream().filter(meta -> acceptable.contains(meta.getVersion())).findAny()
.ifPresent(meta -> {
// Do a check for existing edges going the other
// way
if (depGraph.edges().contains(EndpointPair.ordered(meta, data))) {
throw new IllegalStateException("Cannot have a two-way dependency. Found between "
+ Modules.getBasicRepresentation(data) + " and "
+ Modules.getBasicRepresentation(meta));
}
depGraph.putEdge(data, meta);
});
});
data.getLoadBeforeModules().forEach(dep -> {
Range<SemVer> acceptable = dep.getVersionRange();
// Here, we must load data before meta, put meta->data
depGraph.nodes().stream().filter(meta -> acceptable.contains(meta.getVersion())).findAny()
.ifPresent(meta -> {
// Do a check for existing edges going the other
// way
if (depGraph.edges().contains(EndpointPair.ordered(data, meta))) {
throw new IllegalStateException("Cannot have a two-way dependency. Found between "
+ Modules.getBasicRepresentation(data) + " and "
+ Modules.getBasicRepresentation(meta));
}
depGraph.putEdge(meta, data);
});
});
data.getRequiredModules().forEach(dep -> {
Range<SemVer> acceptable = dep.getVersionRange();
// Here, we must load data after meta, put data->meta
ModuleMetadata result = depGraph.nodes().stream()
.filter(meta -> acceptable.contains(meta.getVersion())).findAny().orElseThrow(() -> {
return new IllegalStateException("Missing required dependency " + dep);
});
// Do a check for existing edges going the other
// way
if (depGraph.edges().contains(EndpointPair.ordered(result, data))) {
throw new IllegalStateException("Cannot have a two-way dependency. Found between "
+ Modules.getBasicRepresentation(data) + " and "
+ Modules.getBasicRepresentation(result));
}
depGraph.putEdge(data, result);
});
}
// Modules in dependency-loading order
List<ModuleMetadata> dependencyOrder = new LinkedList<>();
// The outDegree is the number of dependencies
Set<ModuleMetadata> noDeps = depGraph.nodes().stream().filter(m -> depGraph.outDegree(m) == 0)
.collect(Collectors.toSet());
checkState(!noDeps.isEmpty(), "There must be at least one module with no dependencies.");
// this set tracks encountered modules (i.e. child nodes)
// that have not been known as satisfied by things in depedencyOrder
Set<ModuleMetadata> encounteredNotSatisfied = new HashSet<>();
// this set tracks satisfied modules
// (but not yet added to dependencyOrder)
// that have not been processed to find other modules
Set<ModuleMetadata> satisfiedNotProcessed = new HashSet<>(noDeps);
// Snapshots the last round hashcode for checks
int lastDepOrderSize = 0;
while (!satisfiedNotProcessed.isEmpty() || lastDepOrderSize != Objects.hash(dependencyOrder,
encounteredNotSatisfied, satisfiedNotProcessed)) {
lastDepOrderSize = Objects.hash(dependencyOrder, encounteredNotSatisfied, satisfiedNotProcessed);
// Process satisfied modules
for (ModuleMetadata node : satisfiedNotProcessed) {
dependencyOrder.add(node);
// Load modules that depend on `node`
// insert them into encountered
depGraph.predecessors(node).forEach(dependent -> {
encounteredNotSatisfied.add(dependent);
});
}
// Clear satisfiedNotProcessed, after processing
satisfiedNotProcessed.clear();
// Process encountered nodes
for (ModuleMetadata node : encounteredNotSatisfied) {
// Calculate the load-after deps that might be satisfiable
// Basically does a ID check against the available
// dependencies.
Set<ModuleDependency> satisfiableLoadAfters = getSatisfiableLoadAfters(depGraph.nodes(),
node.getLoadAfterModules());
Set<ModuleDependency> deps = Sets.union(satisfiableLoadAfters, node.getRequiredModules());
if (allDependenciesSatisified(dependencyOrder, deps)) {
satisfiedNotProcessed.add(node);
}
}
// Remove all satisfied
encounteredNotSatisfied.removeAll(satisfiedNotProcessed);
}
if (encounteredNotSatisfied.size() > 0) {
throw new IllegalStateException("Unsatisfied dependencies: " + encounteredNotSatisfied);
}
return FluentIterable.from(dependencyOrder).transform(ModuleMetadata::getId).transform(this.moduleMap::get)
.toList();
}
From source file:org.jgrapht.graph.guava.BaseGraphAdapter.java
/** * Create an edge.//from www . j a va 2 s . c o m * * @param s the source vertex * @param t the target vertex * @return the edge */ final EndpointPair<V> createEdge(V s, V t) { return graph.isDirected() ? EndpointPair.ordered(s, t) : EndpointPair.unordered(s, t); }
From source file:org.jgrapht.graph.guava.BaseValueGraphAdapter.java
/** * Create an edge/*www .j a va2 s . c o m*/ * * @param s the source vertex * @param t the target vertex * @return the edge */ final EndpointPair<V> createEdge(V s, V t) { return valueGraph.isDirected() ? EndpointPair.ordered(s, t) : EndpointPair.unordered(s, t); }