11package graph
22
3+ import groovy.transform.PackageScope
4+
35/**
46 * Implementation of a Graph. Vertices are represented as key/value pairs in a map. The edges connect the keys in
57 * the map to form a graph. The values in the map are the contents of the vertices. This makes it easy to represent
@@ -26,7 +28,7 @@ class Graph {
2628 /**
2729 * Defines the color for a vertex when traversing.
2830 */
29- def enum TraversalColor {
31+ enum TraversalColor {
3032 /**
3133 * an undiscovered vertex
3234 */
@@ -93,6 +95,16 @@ class Graph {
9395 plugin. apply(this )
9496 }
9597
98+ /**
99+ * Adds a vertex object directly.
100+ * @param vertex
101+ * @return true if add was successful.
102+ */
103+ @PackageScope
104+ boolean addVertex (Vertex vertex ) {
105+ vertices[vertex. name] = vertex
106+ }
107+
96108 /**
97109 * Creates a map with the name key set to the name param. The map
98110 * and closure are passed to vertex(Map, Clousre)
@@ -139,6 +151,16 @@ class Graph {
139151 vertex
140152 }
141153
154+ /**
155+ * Adds an edge object directly.
156+ * @param edge
157+ * @return true if add was successful.
158+ */
159+ @PackageScope
160+ boolean addEdge (Edge edge ) {
161+ edges << edge
162+ }
163+
142164 /**
143165 * Creates a map with the entries one and two set to the params one and two.
144166 * This map is then passed to edge(map, closure = null).
@@ -360,6 +382,12 @@ class Graph {
360382 for (int index = 0 ; index < adjacentEdges. size(); index++ ) { // cannot stop and each() call on adjacentEdges
361383 Edge edge = adjacentEdges[index]
362384 String connectedName = root == edge. one ? edge. two : edge. one
385+ // if white tree edge
386+ // if grey back edge
387+ // if black forward or cross edge. must keep track of trees to say cross edge.
388+ if (spec. classifyEdge && spec. classifyEdge(edge, root, connectedName, spec. colors[connectedName]) == Traversal . STOP ) {
389+ return Traversal . STOP
390+ }
363391 if (spec. colors[connectedName] == TraversalColor . WHITE ) {
364392 if (Traversal . STOP == depthFirstTraversalConnected(connectedName, spec)) {
365393 return Traversal . STOP
@@ -408,6 +436,7 @@ class Graph {
408436 }
409437 def traversal = spec. visit(vertices[root])
410438 if (traversal == Traversal . STOP ) {
439+ spec. colors[root] = TraversalColor . GREY
411440 return traversal
412441 }
413442 spec. colors[root] = TraversalColor . GREY
@@ -422,6 +451,7 @@ class Graph {
422451 if (spec. colors[connected] == TraversalColor . WHITE ) {
423452 traversal = spec. visit(vertices[connected])
424453 if (traversal == Traversal . STOP ) {
454+ spec. colors[connected] = TraversalColor . GREY
425455 return traversal
426456 }
427457 spec. colors[connected] = TraversalColor . GREY
@@ -432,4 +462,19 @@ class Graph {
432462 }
433463 null
434464 }
465+
466+ /**
467+ * Classifies edges in a depthFirstTraversal returning the results.
468+ * @param action passed into EdgeClassification.addEdge
469+ * @return the resulting EdgeClassification
470+ */
471+ EdgeClassification classifyEdges (Closure action ) {
472+ EdgeClassification ec = new EdgeClassification ()
473+ depthFirstTraversal {
474+ classifyEdge { Edge edge , String from , String to , TraversalColor toColor ->
475+ ec. addEdge(this , edge, from, to, toColor, action)
476+ }
477+ }
478+ ec
479+ }
435480}
0 commit comments