Skip to content

Instantly share code, notes, and snippets.

@satyagraha
Created May 1, 2014 07:26
Show Gist options
  • Save satyagraha/5df49024b475af7928ff to your computer and use it in GitHub Desktop.
Save satyagraha/5df49024b475af7928ff to your computer and use it in GitHub Desktop.
Gradle-Graphml 2
package org.mine
import groovy.xml.StreamingMarkupBuilder
import groovy.xml.XmlUtil
import java.io.File;
import java.io.IOException;
import java.util.Set;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.component.ComponentIdentifier
import org.gradle.api.artifacts.result.DependencyResult
import org.gradle.api.artifacts.result.ResolutionResult
import org.gradle.api.artifacts.result.ResolvedComponentResult;
import org.gradle.api.artifacts.result.ResolvedDependencyResult;
import org.gradle.api.artifacts.result.UnresolvedDependencyResult;
import org.gradle.api.tasks.diagnostics.AbstractReportTask;
import org.gradle.api.tasks.diagnostics.DependencyReportTask;
import org.gradle.api.tasks.diagnostics.internal.DependencyReportRenderer
import org.gradle.api.tasks.diagnostics.internal.ReportRenderer;
import org.gradle.api.tasks.diagnostics.internal.graph.nodes.RenderableDependency;
import org.gradle.api.tasks.diagnostics.internal.graph.nodes.RenderableModuleResult
import org.gradle.logging.StyledTextOutput;
/**
* Usage:
* task makeDependenciesGml(type: org.mine.MakeGmlDeps) {
* // outputDir null
* // outputDir "./graph"
* outputDir file("./graph")
* }
*
*/
public class MakeGmlDeps extends DependencyReportTask {
private static class GmlDependencyReportRenderer implements DependencyReportRenderer {
private File outputDir
GmlDependencyReportRenderer(File outputDir) {
this.outputDir = outputDir
}
@Override
public void setOutput(StyledTextOutput paramStyledTextOutput) {
// noop
}
@Override
public void setOutputFile(File outputFile) throws IOException {
// noop
}
@Override
public void startProject(Project paramProject) {
// noop
}
@Override
public void completeProject(Project paramProject) {
// noop
}
@Override
public void complete() throws IOException {
// noop
}
@Override
public void startConfiguration(Configuration configuration) {
// TODO Auto-generated method stub
println()
println("startConfiguration: $configuration")
println("outputDir: $outputDir")
}
@Override
public void render(Configuration configuration) throws IOException {
// TODO Auto-generated method stub
println("render: $configuration")
def resolutionResult = configuration.incoming.resolutionResult
println("resolutionResult: $resolutionResult")
// def rootRenderableDependency = new RenderableModuleResult(resolutionResult.root)
// println("rootRenderableDependency: $rootRenderableDependency")
// renderTree(rootRenderableDependency)
// renderGraph(resolutionResult.root)
def filename = configuration.name.replaceAll('[^a-zA-Z0-9_]', '_')
new File(outputDir, "dep.${filename}.graphml").withWriter { out ->
def builder = new StreamingMarkupBuilder()
builder.encoding = 'UTF-8'
def xml = builder.bind {
renderGraph(delegate, resolutionResult.root)
}
def xmlTidy = XmlUtil.serialize(xml)
out.println(xmlTidy)
}
}
def stuff(d) {
d.node(id: "N") {
// <data key="d1">
// <y:ShapeNode>
// <y:Shape type="rectangle"/> <!-- node shape -->
// <y:Geometry height="30.0" width="30.0" x="0.0" y="0.0"/> <!-- position and size -->
// <y:Fill color="#FFCC00" transparent="false"/> <!-- fill color -->
// <y:BorderStyle color="#000000" type="line" width="1.0"/> <!-- border -->
// <y:NodeLabel>Label Text</y:NodeLabel> <!-- label text -->
// </y:ShapeNode>
// </data>
d.data(key: "d1") {
d.y.ShapeNode { d.y.NodeLabel("name") }
}
}
d.edge(source: "A", target: "B")
}
@Override
public void completeConfiguration(Configuration configuration) {
// TODO Auto-generated method stub
println("completeConfiguration: $configuration")
}
private void renderGraph(d, ResolvedComponentResult root) {
def visited = new HashSet<ComponentIdentifier>()
d.mkp.xmlDeclaration()
d.mkp.declareNamespace('': 'http://graphml.graphdrawing.org/xmlns')
d.mkp.declareNamespace('y': 'http://www.yworks.com/xml/graphml')
d.graphml(edgedefault: 'directed') {
key('for': 'node', id: 'd1', 'yfiles.type': 'nodegraphics')
key('for': 'edge', id: 'd2', 'yfiles.type': 'edgegraphics')
renderChildren(d, root, visited)
println("visited: $visited")
}
}
private void renderChildren(d, ResolvedComponentResult parent, Set<ComponentIdentifier> visited) {
if (visited.add(parent.id)) {
addNode(d, parent.id.displayName, true)
parent.dependencies.each { child ->
renderChild(d, parent, child, visited)
}
}
}
private void renderChild(d, ResolvedComponentResult parent, DependencyResult child, Set<ComponentIdentifier> visited) {
if (child instanceof ResolvedDependencyResult) {
ResolvedDependencyResult childRDR = child
println("childRDR: $childRDR")
println("$parent.id --> $childRDR.requested.displayName")
d.edge(source: "$parent.id", target: "$childRDR.requested.displayName")
if (!childRDR.requested.matchesStrictly(childRDR.selected.id)) {
println("version mismatch: $childRDR.requested.displayName => $childRDR.selected.id")
addNode(d, childRDR.requested.displayName, true)
d.edge(source: "$childRDR.requested.displayName", target: "$childRDR.selected.id") {
d.data(key: "d2") {
d.y.PolyLineEdge {
d.y.LineStyle("type": "dotted")
d.y.Arrows(source: "none", target: "standard")
}
}
}
}
renderChildren(d, childRDR.selected, visited)
} else if (child instanceof UnresolvedDependencyResult) {
UnresolvedDependencyResult childUDR = child
println("childUDR: $childUDR")
addNode(d, childUDR.requested.displayName, false)
d.edge(source: "$parent.id", target: "$childUDR.requested.displayName")
} else {
}
}
private void addNode(d, String name, boolean resolved) {
d.node(id: name) {
// <data key="d1">
// <y:ShapeNode>
// <y:Shape type="rectangle"/> <!-- node shape -->
// <y:Geometry height="30.0" width="30.0" x="0.0" y="0.0"/> <!-- position and size -->
// <y:Fill color="#FFCC00" transparent="false"/> <!-- fill color -->
// <y:BorderStyle color="#000000" type="line" width="1.0"/> <!-- border -->
// <y:NodeLabel>Label Text</y:NodeLabel> <!-- label text -->
// </y:ShapeNode>
// </data>
d.data(key: "d1") {
d.y.ShapeNode {
d.y.NodeLabel(name)
if (!resolved) {
d.y.Fill(color: "#FF6633")
}
}
}
}
}
// private void renderTree(RenderableDependency root) {
// def visited = new HashSet<ComponentIdentifier>()
// visited.add(root.id)
// renderChildren(root, visited)
// println("visited: $visited")
// }
//
// private void renderChildren(RenderableDependency parent, Set<ComponentIdentifier> visited) {
// startChildren()
// parent.children.each {
// child -> renderChild(parent, child, visited)
// }
// completeChildren()
// }
//
// private void startChildren() {
// }
//
// private void renderChild(RenderableDependency parent, RenderableDependency child, Set<ComponentIdentifier> visited) {
// def alreadyRendered = !visited.add(child.id)
// if (alreadyRendered) {
//// hasCyclicDependencies = true
// }
//
// println("$parent.name --> $child.name")
//// if (!node.isResolvable()) {
//// println(" FAILED");
//// } else if (alreadyRendered && !node.getChildren().isEmpty()) {
//// println(" (*)");
//// }
//
// if (!alreadyRendered) {
// renderChildren(child, visited)
// }
// }
//
// private void completeChildren() {
// }
}
public MakeGmlDeps() {
super()
}
public void setOutputDir(File outputDir) {
println("outputDir: $outputDir")
setRenderer(new GmlDependencyReportRenderer(outputDir))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment