if(title == null)
title = "";
if(cancel == null)
cancel = new NullIndicator();
RootGraph g = new RootGraph(title, "RootGraph", "root");
// Create Graph vertexes, one per existing module
// and one for the root/non-modular
for(ModuleNodeData mnd : moduleNodeData.values()) {
cancel.assertContinue();
if(renderAll || mnd.marked)
if(mnd.isNode())
g.addVertex(createVertexForPPNodeNode(mnd));
else
g.addVertex(createVertexForModuleNode(mnd));
}
// only draw the root node if it has been marked (incoming dependency), or has outgoing
// when not rendering all, the non modular must have incoming dependencies to show.
if(renderAll && nonModularNode.outgoing.size() > 0 || nonModularNode.marked) {
Vertex v = createVertexForRootNode(nonModularNode);
g.addVertex(v);
}
// Create Vertexes for all Edges that have data
// (very large labels on edges does not work that well as they often overlap)
// Skip edges that are from non marked module nodes unless everything is rendered
for(ModuleEdge me : moduleEdges) {
// filter out self references
if(me.from == me.to)
continue;
if(renderAll || me.from.marked) {
cancel.assertContinue();
Vertex v = createVertexForEdge(me);
if(v != null) {
g.addVertex(v);
}
}
}
// Create Edges
// If an edge has a vertex, it needs to be drawn as two separate graph edges
for(ModuleNodeData a : Iterables.concat(moduleNodeData.values(), Collections.singleton(nonModularNode))) {
if(!(renderAll || a.marked))
continue; // skip non marked unless all is rendered
for(ModuleNodeData b : a.outgoing.keySet()) {
cancel.assertContinue();
int resolved = 0;
int unresolved = 0;
int implied = 0;
int count = 0;
List<ModuleEdge> edges = new ArrayList<ModuleEdge>();
Collection<ModuleEdge> outgoing = a.outgoing.get(b);
for(ModuleEdge e : outgoing) {
edges.add(e);
switch(e.edgeType) {
case IMPLIED:
implied++;
break;
case UNRESOLVED:
unresolved++;
break;
case RESOLVED:
resolved++;
break;
default:
throw new IllegalStateException("Illegal edge type found");
}
++count;
}
String tooltipString = makeTooltip(a, b);
List<String> styleClasses = classesFor(a, b);
// CASE 1
// A --> [...] --> B
// A imports from resolved B
if(count == 2 && resolved == 1 && implied == 1) {
Edge e1 = new Edge("", STYLE_EDGE__IMPORT, a.getVertex(), edges.get(1).getVertex());
Edge e2 = new Edge(getVersionLabel(edges.get(0)), STYLE_EDGE__RESOLVED_DEP, //
edges.get(1).getVertex(), b.getVertex());
g.addEdge(e1, e2);
addTooltip(tooltipString, e1, e2);
addStyleClasses(styleClasses, e1, e2);
addEdgeHref(a, b, e1, e2);
}
else if(count == 1 && implied == 1) {
// CASE 5
// A --> [...]
if(edges.get(0).to == null) {
Edge e1 = new Edge("unresolved", STYLE_EDGE__UIMPORT, a.getVertex(), edges.get(0).getVertex());
g.addEdge(e1);
addTooltip(tooltipString, e1);
addStyleClasses(styleClasses, e1);
addEdgeHref(a, b, e1);
}
// CASE 8 (reference to pptp - do not draw imports -> pptp part)
// A -->[...]
else if(edges.get(0).to == pptpNode) {
Edge e1 = new Edge("puppet", STYLE_EDGE__IMPORT, a.getVertex(), edges.get(0).getVertex());
g.addEdge(e1);
// default tooltip == label
addStyleClasses(styleClasses, e1);
addEdgeHref(a, b, e1);
}
// CASE 2 (and CASE 0 - self reference)
// A -->[...] ~~> B
else {
if(edges.get(0).from != edges.get(0).to) { // skip self references
Edge e1 = new Edge("", STYLE_EDGE__IMPORT, a.getVertex(), edges.get(0).getVertex());
Edge e2 = new Edge(
"implicit", STYLE_EDGE__IMPLIED_DEP, edges.get(0).getVertex(),
edges.get(0).to.getVertex());
g.addEdge(e1, e2);
addTooltip(tooltipString, e1, e2);
addStyleClasses(styleClasses, e1, e2);
addEdgeHref(a, b, e1, e2);
}
}
}
// CASE 3
// A --> [...] ~~>(not in range) B
else if(count == 2 && implied == 1 && unresolved == 1) {
Edge e1 = new Edge("", STYLE_EDGE__IMPORT, a.getVertex(), edges.get(1).getVertex());
String label = "implicit\\nunresolved\\n" + getVersionLabel(edges.get(0));
Edge e2 = new Edge(label, STYLE_EDGE__UNRESOLVED_IMPLIED_DEP, //
edges.get(1).getVertex(), edges.get(1).to.getVertex());
g.addEdge(e1, e2);
addTooltip(tooltipString, e1, e2);
addStyleClasses(styleClasses, e1, e2);
addEdgeHref(a, b, e1, e2);
}
else if(count == 1 && unresolved == 1) {
// CASE 7
// A ~~> B where B is not in range
if(edges.get(0).to.exists()) {
String label = "unresolved\\n" + getVersionLabel(edges.get(0));
Edge e1 = new Edge(label, STYLE_EDGE__UNRESOLVED_IMPLIED_DEP, //
a.getVertex(), b.getVertex());
g.addEdge(e1);
addTooltip(tooltipString, e1);
addStyleClasses(styleClasses, e1);
addEdgeHref(a, b, e1);
}
// CASE 4
// A --> B where B does not exist
else {
String label = "unresolved\\n" + getVersionLabel(edges.get(0));
Edge e1 = new Edge(label, STYLE_EDGE__UNRESOLVED_DEP, //
a.getVertex(), b.getVertex());
g.addEdge(e1);
addTooltip(tooltipString, e1);
addStyleClasses(styleClasses, e1);
addEdgeHref(a, b, e1);
}
}
// CASE 6
// A --> B
// (nothing is imported from B)
else if(count == 1 && resolved == 1) {
Edge e1 = new Edge(getVersionLabel(edges.get(0)), STYLE_EDGE__RESOLVED_DEP, //
a.getVertex(), b.getVertex());
g.addEdge(e1);
addTooltip(tooltipString, e1);
addStyleClasses(styleClasses, e1);
addEdgeHref(a, b, e1);
}
else if(count == implied) {