This is an automated email from the ASF dual-hosted git repository.

martin_s pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/archiva-components.git


The following commit(s) were added to refs/heads/master by this push:
     new ba45f3c  Better naming and improving traversal
ba45f3c is described below

commit ba45f3c5d2deda3de8399b1853e7fdd07ab8b7ad
Author: Martin Stockhammer <[email protected]>
AuthorDate: Fri Nov 15 17:25:26 2019 +0100

    Better naming and improving traversal
---
 .../graph/api/{VisitError.java => Category.java}   |  20 +-
 .../apache/archiva/components/graph/api/Edge.java  |  10 +-
 .../apache/archiva/components/graph/api/Graph.java | 119 +++-
 .../graph/api/{Vertex.java => Node.java}           |  21 +-
 .../api/{VisitError.java => RelationType.java}     |  27 +-
 .../{VisitError.java => StandardRelationType.java} |  21 +-
 .../components/graph/api/TraversalStatus.java      |  18 +-
 .../archiva/components/graph/api/VisitError.java   |  12 +-
 .../archiva/components/graph/base/BaseEdge.java    |  37 +-
 .../components/graph/base/DirectedGraph.java       | 121 +++-
 .../archiva/components/graph/base/SimpleGraph.java |  41 +-
 .../base/{SimpleVertex.java => SimpleNode.java}    |  51 +-
 .../archiva/components/graph/util/Traversal.java   | 192 ++++--
 .../components/graph/util/TraversalFlags.java      |  67 ++
 .../components/graph/base/BaseEdgeTest.java        |  38 +-
 .../components/graph/base/SimpleGraphTest.java     |  92 ++-
 .../{SimpleVertexTest.java => SimpleNodeTest.java} |  22 +-
 .../components/graph/util/TraversalTest.java       | 717 ++++++++++++---------
 18 files changed, 1091 insertions(+), 535 deletions(-)

diff --git 
a/graph/src/main/java/org/apache/archiva/components/graph/api/VisitError.java 
b/graph/src/main/java/org/apache/archiva/components/graph/api/Category.java
similarity index 70%
copy from 
graph/src/main/java/org/apache/archiva/components/graph/api/VisitError.java
copy to 
graph/src/main/java/org/apache/archiva/components/graph/api/Category.java
index 41f1c09..16fb9cb 100644
--- 
a/graph/src/main/java/org/apache/archiva/components/graph/api/VisitError.java
+++ b/graph/src/main/java/org/apache/archiva/components/graph/api/Category.java
@@ -18,21 +18,11 @@ package org.apache.archiva.components.graph.api;
  * under the License.
  */
 
-public class VisitError<V extends Vertex<V>> {
-
-    private final Throwable exception;
-    private final V vertex;
-
-    public VisitError(V vertex, Throwable exception) {
-        this.exception = exception;
-        this.vertex = vertex;
-    }
+/**
+ * The category is used to shape the domain by grouping nodes.
+ */
+public interface Category {
 
-    public Throwable getException() {
-        return exception;
-    }
+    String name();
 
-    public V getVertex() {
-        return vertex;
-    }
 }
diff --git 
a/graph/src/main/java/org/apache/archiva/components/graph/api/Edge.java 
b/graph/src/main/java/org/apache/archiva/components/graph/api/Edge.java
index 5254ec8..032da50 100644
--- a/graph/src/main/java/org/apache/archiva/components/graph/api/Edge.java
+++ b/graph/src/main/java/org/apache/archiva/components/graph/api/Edge.java
@@ -24,7 +24,7 @@ package org.apache.archiva.components.graph.api;
  *
  * @param <V> The vertex implementation.
  */
-public interface Edge<V extends Vertex<V>> {
+public interface Edge<V extends Node<V>> {
 
     /**
      * Returns the identifier of this edge. The id must be unique for given 
graph.
@@ -74,7 +74,13 @@ public interface Edge<V extends Vertex<V>> {
      */
     double getWeight();
 
-
+    /**
+     * Returns the RelationType of the edge. If nothing is set, the {@link 
StandardRelationType#DEFAULT} should
+     * be returned.
+     *
+     * @return the type of the edge
+     */
+    RelationType getType();
 
 
 }
diff --git 
a/graph/src/main/java/org/apache/archiva/components/graph/api/Graph.java 
b/graph/src/main/java/org/apache/archiva/components/graph/api/Graph.java
index 13cdb90..af1c347 100644
--- a/graph/src/main/java/org/apache/archiva/components/graph/api/Graph.java
+++ b/graph/src/main/java/org/apache/archiva/components/graph/api/Graph.java
@@ -18,8 +18,7 @@ package org.apache.archiva.components.graph.api;
  * under the License.
  */
 
-import org.apache.archiva.components.graph.base.SimpleVertex;
-
+import java.util.List;
 import java.util.Set;
 
 /**
@@ -29,21 +28,123 @@ import java.util.Set;
  *
  * @param <V>
  */
-public interface Graph<V extends Vertex<V>> {
+public interface Graph<V extends Node<V>> {
+
+    /**
+     * Creates a node with the given label in the graph. The id of the node is 
generated
+     * by the graph implementation.
+     * The method returns always a new node instance, even if a node with the 
given label
+     * exists already.
+     *
+     * @param label the label of the new node
+     * @return a new node instance with the given label and a generated id
+     */
+    V newNode(String label);
+
+    /**
+     * Adds a new node if the id does not exist yet, otherwise returns the 
node with the given id
+     * and the new label set.
+     *
+     * @param id the id of the node
+     * @param label the label of the node
+     * @return a new node instance or the existing node with the given id
+     */
+    V addNode(String id, String label);
+
+    void removeNode(V node);
+
+
+    /**
+     * Creates a new edge instance with the given label. The method returns 
always a new edge instance,
+     * even if a edge with the given label exists already.
+     * The type is set to {@link StandardRelationType#DEFAULT}
+     *
+     * @param label the edge label
+     * @param sourceNode the source node
+     * @param destinationNode the destination node
+     * @throws IllegalArgumentException if source or destination is 
<code>null</code>
+     * @return a new edge instance
+     */
+    Edge<V> newEdge(String label, V sourceNode, V destinationNode) throws 
IllegalArgumentException;
+
+    /**
+     * Creates a new edge instance with the given label. The method returns 
always a new edge instance,
+     * even if a edge with the given label exists already.
+     *
+     * @param type the edge type
+     * @param label the edge label
+     * @param sourceNode the source node
+     * @param destinationNode the destination node
+     * @throws IllegalArgumentException if the source or destination node is 
<code>null</code>
+     * @return a new edge instance
+     */
+    Edge<V> newEdge(RelationType type, String label, V sourceNode, V 
destinationNode) throws IllegalArgumentException;
 
-    V addVertex(String label);
+    /**
+     * Creates a new edge instance with the given id or returns the edge 
instance with the given id and
+     * type.
+     * If a edge with the id exists already but with a different type it will 
throw a {@link IllegalArgumentException}
+     *
+     * @param type the type of the edge
+     * @param id the id
+     * @param label the edge label
+     * @param sourceNode the source node
+     * @param destinationNode the destination node
+     * @throws IllegalArgumentException if a edge instance with the given id 
but a different type exists already. Or if
+     * source or destination node is <code>null</code>
+     * @return
+     */
+    Edge<V> addEdge(RelationType type, String id, String label, V sourceNode, 
V destinationNode) throws IllegalArgumentException;
 
-    void removeVertex(V vertex);
+    /**
+     * Creates a new edge instance with the given id or returns the edge 
instance with the given id.
+     * If the edge is newly created it will get the type {@link 
StandardRelationType#DEFAULT}
+     *
+     * @param id the id
+     * @param label the edge label
+     * @param sourceNode the source node
+     * @param destinationNode the destination node
+     * @throws IllegalArgumentException if source or destination is 
<code>null</code>
+     * @return
+     */
+    Edge<V> addEdge(String id, String label, V sourceNode, V destinationNode) 
throws IllegalArgumentException;
 
-    Edge<V> addEdge(String label, V inVertex, V outVertex);
+    /**
+     * Removes the edge from the graph and unregisters it from the source and 
destination
+     *
+     * @param edge the edge to remove
+     */
+    void removeEdge(Edge<V> edge);
 
-    void removeEdge(Edge<SimpleVertex> edge);
+    /**
+     * Returns the node with the given id
+     *
+     * @param id the node id
+     * @return the found node, or <code>null</code>, if it does not exist
+     */
+    V getNode(String id);
 
-    V getVertex(String id);
+    /**
+     * Finds nodes using a given query. The query syntax depends on the graph 
implementation.
+     *
+     * @param query the query to find nodes
+     * @return the found nodes, or a empty list
+     */
+    List<V> findNodes(String query);
 
+    /**
+     * Returns the edge with the given id.
+     *
+     * @param id the edge id
+     * @return the found edge instance, or <code>null</code>, if it does not 
exist
+     */
     Edge<V> getEdge(String id);
 
-    Set<V> getVertices();
+    /**
+     * Returns all nodes of the graph
+     * @return
+     */
+    Set<V> getNodes();
 
 
 
diff --git 
a/graph/src/main/java/org/apache/archiva/components/graph/api/Vertex.java 
b/graph/src/main/java/org/apache/archiva/components/graph/api/Node.java
similarity index 81%
rename from 
graph/src/main/java/org/apache/archiva/components/graph/api/Vertex.java
rename to graph/src/main/java/org/apache/archiva/components/graph/api/Node.java
index d3937f3..e8a1c1c 100644
--- a/graph/src/main/java/org/apache/archiva/components/graph/api/Vertex.java
+++ b/graph/src/main/java/org/apache/archiva/components/graph/api/Node.java
@@ -26,7 +26,7 @@ import java.util.List;
  *
  * @param <V> The vertex implementation
  */
-public interface Vertex<V extends Vertex<V>> {
+public interface Node<V extends Node<V>> {
 
     /**
      * Returns the identifier of this vertex. The identifier is unique for a 
given graph.
@@ -66,5 +66,24 @@ public interface Vertex<V extends Vertex<V>> {
      */
     List<Edge<V>> getInEdges();
 
+    /**
+     * Returns the categories of the vertex.
+     *
+     * @return the list of categories of the vertex
+     */
+    List<Category> getCategories();
+
+    /**
+     * Adds a category to the node
+     * @param category the category to add
+     */
+    void addCategory(Category category);
+
 
+    /**
+     * Removes a category from the node.
+     *
+     * @param category the category to remove
+     */
+    void removeCategory(Category category);
 }
diff --git 
a/graph/src/main/java/org/apache/archiva/components/graph/api/VisitError.java 
b/graph/src/main/java/org/apache/archiva/components/graph/api/RelationType.java
similarity index 69%
copy from 
graph/src/main/java/org/apache/archiva/components/graph/api/VisitError.java
copy to 
graph/src/main/java/org/apache/archiva/components/graph/api/RelationType.java
index 41f1c09..dc83c01 100644
--- 
a/graph/src/main/java/org/apache/archiva/components/graph/api/VisitError.java
+++ 
b/graph/src/main/java/org/apache/archiva/components/graph/api/RelationType.java
@@ -18,21 +18,16 @@ package org.apache.archiva.components.graph.api;
  * under the License.
  */
 
-public class VisitError<V extends Vertex<V>> {
-
-    private final Throwable exception;
-    private final V vertex;
-
-    public VisitError(V vertex, Throwable exception) {
-        this.exception = exception;
-        this.vertex = vertex;
-    }
-
-    public Throwable getException() {
-        return exception;
-    }
+/**
+ * A edge must always have a single relation type.
+ * You can use enums to define the type for a specific domain.
+ *
+ */
+public interface RelationType {
 
-    public V getVertex() {
-        return vertex;
-    }
+    /**
+     * The type name
+     * @return
+     */
+    String name();
 }
diff --git 
a/graph/src/main/java/org/apache/archiva/components/graph/api/VisitError.java 
b/graph/src/main/java/org/apache/archiva/components/graph/api/StandardRelationType.java
similarity index 69%
copy from 
graph/src/main/java/org/apache/archiva/components/graph/api/VisitError.java
copy to 
graph/src/main/java/org/apache/archiva/components/graph/api/StandardRelationType.java
index 41f1c09..21c45f8 100644
--- 
a/graph/src/main/java/org/apache/archiva/components/graph/api/VisitError.java
+++ 
b/graph/src/main/java/org/apache/archiva/components/graph/api/StandardRelationType.java
@@ -18,21 +18,6 @@ package org.apache.archiva.components.graph.api;
  * under the License.
  */
 
-public class VisitError<V extends Vertex<V>> {
-
-    private final Throwable exception;
-    private final V vertex;
-
-    public VisitError(V vertex, Throwable exception) {
-        this.exception = exception;
-        this.vertex = vertex;
-    }
-
-    public Throwable getException() {
-        return exception;
-    }
-
-    public V getVertex() {
-        return vertex;
-    }
-}
+public enum StandardRelationType implements RelationType {
+    DEFAULT,DIRECTED;
+}
\ No newline at end of file
diff --git 
a/graph/src/main/java/org/apache/archiva/components/graph/api/TraversalStatus.java
 
b/graph/src/main/java/org/apache/archiva/components/graph/api/TraversalStatus.java
index eb589ce..1675537 100644
--- 
a/graph/src/main/java/org/apache/archiva/components/graph/api/TraversalStatus.java
+++ 
b/graph/src/main/java/org/apache/archiva/components/graph/api/TraversalStatus.java
@@ -27,11 +27,11 @@ import java.util.List;
  *
  * @param <V>
  */
-public class TraversalStatus<V extends Vertex<V>> {
+public class TraversalStatus<V extends Node<V>> {
 
     private int cycles = 0;
     private List<VisitError<V>> errorList;
-    private List<Vertex<V>> cycleVertices;
+    private List<V> cycleNodes;
 
     public TraversalStatus() {
 
@@ -68,14 +68,14 @@ public class TraversalStatus<V extends Vertex<V>> {
 
     /**
      * Add another cycle to the counter
-     * @param vertex
+     * @param node
      */
-    public void registerCycle(Vertex<V> vertex) {
+    public void registerCycle(V node) {
         cycles++;
-        if (cycleVertices==null) {
-            cycleVertices = new ArrayList<>();
+        if (cycleNodes ==null) {
+            cycleNodes = new ArrayList<>();
         }
-        cycleVertices.add(vertex);
+        cycleNodes.add(node);
     }
 
     /**
@@ -101,7 +101,7 @@ public class TraversalStatus<V extends Vertex<V>> {
      *
      * @return the list of vertices where cycles were detected
      */
-    public List<Vertex<V>> getCycleVertices() {
-        return cycleVertices;
+    public List<V> getCycleNodes() {
+        return cycleNodes;
     }
 }
diff --git 
a/graph/src/main/java/org/apache/archiva/components/graph/api/VisitError.java 
b/graph/src/main/java/org/apache/archiva/components/graph/api/VisitError.java
index 41f1c09..7e116a7 100644
--- 
a/graph/src/main/java/org/apache/archiva/components/graph/api/VisitError.java
+++ 
b/graph/src/main/java/org/apache/archiva/components/graph/api/VisitError.java
@@ -18,21 +18,21 @@ package org.apache.archiva.components.graph.api;
  * under the License.
  */
 
-public class VisitError<V extends Vertex<V>> {
+public class VisitError<V extends Node<V>> {
 
     private final Throwable exception;
-    private final V vertex;
+    private final V node;
 
-    public VisitError(V vertex, Throwable exception) {
+    public VisitError(V node, Throwable exception) {
         this.exception = exception;
-        this.vertex = vertex;
+        this.node = node;
     }
 
     public Throwable getException() {
         return exception;
     }
 
-    public V getVertex() {
-        return vertex;
+    public V getNode() {
+        return node;
     }
 }
diff --git 
a/graph/src/main/java/org/apache/archiva/components/graph/base/BaseEdge.java 
b/graph/src/main/java/org/apache/archiva/components/graph/base/BaseEdge.java
index bdf274e..39cb5cf 100644
--- a/graph/src/main/java/org/apache/archiva/components/graph/base/BaseEdge.java
+++ b/graph/src/main/java/org/apache/archiva/components/graph/base/BaseEdge.java
@@ -18,26 +18,33 @@ package org.apache.archiva.components.graph.base;
  * under the License.
  */
 
-import org.apache.archiva.components.graph.api.Edge;
-import org.apache.archiva.components.graph.api.Graph;
-import org.apache.archiva.components.graph.api.Vertex;
+import org.apache.archiva.components.graph.api.*;
 
-public class BaseEdge<V extends Vertex<V>> implements Edge<V>, 
Comparable<BaseEdge<V>> {
+public class BaseEdge<V extends Node<V>> implements Edge<V>, 
Comparable<BaseEdge<V>> {
 
     private final String id;
     private String label;
     private double weight = 1.0;
-    private V sourceVertex;
-    private V destinationVertex;
+    private V sourceNode;
+    private V destinationNode;
     private final Graph<V> graph;
+    private final RelationType type;
 
-    public BaseEdge(Graph<V> graph, String id, V sourceVertex, V 
destinationVertex) {
+    public BaseEdge(Graph<V> graph, String id, V sourceNode, V 
destinationNode) {
         this.id = id;
         this.graph = graph;
-        this.sourceVertex = sourceVertex;
-        this.destinationVertex = destinationVertex;
+        this.sourceNode = sourceNode;
+        this.destinationNode = destinationNode;
+        this.type = StandardRelationType.DEFAULT;
     }
 
+    public BaseEdge(Graph<V> graph, RelationType type, String id, V 
sourceNode, V destinationNode) {
+        this.id = id;
+        this.graph = graph;
+        this.sourceNode = sourceNode;
+        this.destinationNode = destinationNode;
+        this.type = type;
+    }
     @Override
     public String getId() {
         return id;
@@ -63,12 +70,12 @@ public class BaseEdge<V extends Vertex<V>> implements 
Edge<V>, Comparable<BaseEd
 
     @Override
     public V getSource() {
-        return sourceVertex;
+        return sourceNode;
     }
 
     @Override
     public V getDestination() {
-        return destinationVertex;
+        return destinationNode;
     }
 
     @Override
@@ -77,13 +84,18 @@ public class BaseEdge<V extends Vertex<V>> implements 
Edge<V>, Comparable<BaseEd
     }
 
     @Override
+    public RelationType getType() {
+        return type;
+    }
+
+    @Override
     public int hashCode() {
         return this.id.hashCode();
     }
 
     @Override
     public String toString() {
-        return this.id+"|"+this.label+": "+ sourceVertex.toString() + " -> " + 
destinationVertex.toString();
+        return this.id+"("+this.label+")("+ sourceNode.getId()+ " -> " + 
destinationNode.getId()+")";
     }
 
     @Override
@@ -94,4 +106,5 @@ public class BaseEdge<V extends Vertex<V>> implements 
Edge<V>, Comparable<BaseEd
             return this.id.compareTo(o.getId());
         }
     }
+
 }
diff --git 
a/graph/src/main/java/org/apache/archiva/components/graph/base/DirectedGraph.java
 
b/graph/src/main/java/org/apache/archiva/components/graph/base/DirectedGraph.java
index eb946b1..d53557b 100644
--- 
a/graph/src/main/java/org/apache/archiva/components/graph/base/DirectedGraph.java
+++ 
b/graph/src/main/java/org/apache/archiva/components/graph/base/DirectedGraph.java
@@ -18,12 +18,11 @@ package org.apache.archiva.components.graph.base;
  * under the License.
  */
 
-import org.apache.archiva.components.graph.api.Edge;
-import org.apache.archiva.components.graph.api.Graph;
-import org.apache.archiva.components.graph.api.Vertex;
+import org.apache.archiva.components.graph.api.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-import java.util.Set;
-import java.util.TreeMap;
+import java.util.*;
 import java.util.stream.Collectors;
 
 
@@ -31,51 +30,114 @@ import java.util.stream.Collectors;
  * Abstract implementation of a directed graph
  * @param <V> The vertex implementation.
  */
-public abstract class DirectedGraph<V extends Vertex<V>> implements Graph<V> {
+public abstract class DirectedGraph<V extends Node<V>> implements Graph<V> {
 
+    private static final Logger log = 
LoggerFactory.getLogger(DirectedGraph.class);
 
-    protected TreeMap<String, V> vertices = new TreeMap<>();
+    protected TreeMap<String, V> nodes = new TreeMap<>();
     protected TreeMap<String, Edge<V>> edges = new TreeMap<>();
 
-    public V addVertex(String label) {
-        V vtx = createNewVertex();
+    public V newNode(String label) {
+        V vtx = createNewNode();
         vtx.setLabel(label);
-        this.vertices.put(vtx.getId(), vtx);
+        this.nodes.put(vtx.getId(), vtx);
         return vtx;
     }
 
+    @Override
+    public V addNode(String id, String label) {
+        V node;
+        if (nodes.containsKey(id)) {
+            node = nodes.get(id);
+        } else {
+            node = createNewNode(id);
+            this.nodes.put(id, node);
+        }
+        node.setLabel(label);
+        return node;
+    }
+
+
+    protected V createNewNode() {
+        return createNewNode(UUID.randomUUID().toString());
+    }
+
     /**
      * Subclasses that implement this method must return a new vertex instance 
for
      * each call. The vertex should not be connected with any edges.
      *
      * @return A new vertex instance.
      */
-    abstract V createNewVertex();
+    abstract V createNewNode(String id);
+
+
+    protected Edge<V> createNewEdge(RelationType type, V sourceVertex, V 
destinationVertex) {
+        return createNewEdge(type, UUID.randomUUID().toString(), sourceVertex, 
destinationVertex);
+    }
+
 
     /**
      * Subclasses that implement this method must return a new instance of the 
edge with
      * the given source and destination vertices. The vertices must be linked 
by the new
      * edge.
      *
+     * @param type the type of the edge
      * @param sourceVertex the source vertex
      * @param destinationVertex the destination vertex
      * @return A new edge instance.
      */
-    abstract Edge<V> createNewEdge(V sourceVertex, V destinationVertex);
+    abstract Edge<V> createNewEdge(RelationType type, String id, V 
sourceVertex, V destinationVertex);
 
 
+    @Override
+    public Edge<V> newEdge(String label, V sourceNode, V destinationNode) {
+        return newEdge(StandardRelationType.DEFAULT, label, sourceNode, 
destinationNode);
+    }
 
     @Override
-    public Edge<V> addEdge(String label, V sourceVertex, V destinationVertex) {
-        Edge<V> edge = createNewEdge(sourceVertex, destinationVertex);
+    public Edge<V> newEdge(RelationType type, String label, V sourceNode, V 
destinationNode) {
+        if (sourceNode==null) {
+            throw new IllegalArgumentException("Source node may not be null");
+        }
+        if (destinationNode==null) {
+            throw new IllegalArgumentException("Destination node may not be 
null");
+        }
+        Edge<V> edge = createNewEdge(type, sourceNode, destinationNode);
         edge.setLabel(label);
         this.edges.put(edge.getId(), edge);
         return edge;
     }
 
     @Override
-    public V getVertex(String id) {
-        return vertices.get(id);
+    public Edge<V> addEdge(final RelationType type, final String id, final 
String label,
+                           final V sourceNode, final V destinationNode) throws 
IllegalArgumentException {
+        if (sourceNode==null) {
+            throw new IllegalArgumentException("Source node may not be null");
+        }
+        if (destinationNode==null) {
+            throw new IllegalArgumentException("Destination node may not be 
null");
+        }
+        Edge<V> edge;
+        if (this.edges.containsKey(id)) {
+            log.debug("Edge found " + id);
+            edge = this.edges.get(id);
+        } else {
+            edge = createNewEdge(type, id, sourceNode, destinationNode);
+            this.edges.put(id, edge);
+        }
+        edge.setLabel(label);
+        log.debug("Adding edge " + edge.toString());
+        return edge;
+    }
+
+    @Override
+    public Edge<V> addEdge(String id, String label, V sourceNode, V 
destinationNode) throws IllegalArgumentException {
+        return addEdge(StandardRelationType.DEFAULT, id, label, sourceNode, 
destinationNode);
+    }
+
+    @Override
+    public V getNode(String id) {
+        return nodes.get(id);
     }
 
     @Override
@@ -84,8 +146,31 @@ public abstract class DirectedGraph<V extends Vertex<V>> 
implements Graph<V> {
     }
 
     @Override
-    public Set<V> getVertices() {
-        return vertices.values().stream().collect(Collectors.toSet());
+    public Set<V> getNodes() {
+        return nodes.values().stream().collect(Collectors.toSet());
+    }
+
+    @Override
+    public List<V> findNodes(String query) {
+        return Collections.EMPTY_LIST;
+    }
+
+    @Override
+    public void removeNode(V node) {
+        List<Edge<V>> rmEdges = new ArrayList<>(node.getInEdges());
+        for (Edge<V> edge : rmEdges) {
+            removeEdge(edge);
+        }
+        rmEdges = new ArrayList<>(node.getOutEdges());
+        for (Edge<V> edge : rmEdges) {
+            removeEdge(edge);
+        }
+        nodes.remove(node.getId());
+    }
+
+    @Override
+    public void removeEdge(Edge<V> edge) {
+        edges.remove(edge.getId());
     }
 
 }
diff --git 
a/graph/src/main/java/org/apache/archiva/components/graph/base/SimpleGraph.java 
b/graph/src/main/java/org/apache/archiva/components/graph/base/SimpleGraph.java
index 9c51115..3497b07 100644
--- 
a/graph/src/main/java/org/apache/archiva/components/graph/base/SimpleGraph.java
+++ 
b/graph/src/main/java/org/apache/archiva/components/graph/base/SimpleGraph.java
@@ -19,8 +19,9 @@ package org.apache.archiva.components.graph.base;
  */
 
 import org.apache.archiva.components.graph.api.Edge;
+import org.apache.archiva.components.graph.api.RelationType;
 
-import java.util.UUID;
+import java.util.List;
 
 /**
  * Simple directed graph implementation that uses UUIDs as unique identifiers 
for
@@ -28,39 +29,39 @@ import java.util.UUID;
  *
  *
  */
-public class SimpleGraph extends DirectedGraph<SimpleVertex> {
+public class SimpleGraph extends DirectedGraph<SimpleNode> {
+
 
     @Override
-    SimpleVertex createNewVertex() {
-        return new SimpleVertex(this, UUID.randomUUID().toString());
+    SimpleNode createNewNode(String id) {
+        return new SimpleNode(this, id);
     }
 
+
+
     @Override
-    Edge<SimpleVertex> createNewEdge(SimpleVertex sourceVertex, SimpleVertex 
destinationVertex) {
-        BaseEdge edge = new BaseEdge<>(this, UUID.randomUUID().toString(), 
sourceVertex, destinationVertex);
-        addEdgeToVertex(sourceVertex, edge);
-        addEdgeToVertex(destinationVertex, edge);
+    Edge<SimpleNode> createNewEdge(RelationType type, String id, SimpleNode 
sourceVertex, SimpleNode destinationVertex) {
+        BaseEdge edge = new BaseEdge<>(this, id, sourceVertex, 
destinationVertex);
+        addEdgeToNode(sourceVertex, edge);
+        addEdgeToNode(destinationVertex, edge);
         return edge;
     }
 
-    private void addEdgeToVertex(SimpleVertex vertex, Edge<SimpleVertex> edge) 
{
+    private void addEdgeToNode(SimpleNode vertex, Edge<SimpleNode> edge) {
         vertex.addEdge(edge);
     }
 
+
     @Override
-    public void removeEdge(Edge<SimpleVertex> edge) {
-        edges.remove(edge);
-        edge.getSource().removeEdge(edge);
-        edge.getDestination().removeEdge(edge);
+    public List<SimpleNode> findNodes(String query) {
+        return null;
     }
 
+
     @Override
-    public void removeVertex(SimpleVertex vertex) {
-        for (Edge<SimpleVertex> edge : vertex.getInEdges()) {
-            removeEdge(edge);
-        }
-        for (Edge<SimpleVertex> edge : vertex.getOutEdges()) {
-            removeEdge(edge);
-        }
+    public void removeEdge(Edge<SimpleNode> edge) {
+        super.removeEdge(edge);
+        edge.getSource().removeEdge(edge);
+        edge.getDestination().removeEdge(edge);
     }
 }
diff --git 
a/graph/src/main/java/org/apache/archiva/components/graph/base/SimpleVertex.java
 b/graph/src/main/java/org/apache/archiva/components/graph/base/SimpleNode.java
similarity index 63%
rename from 
graph/src/main/java/org/apache/archiva/components/graph/base/SimpleVertex.java
rename to 
graph/src/main/java/org/apache/archiva/components/graph/base/SimpleNode.java
index 4cd3aa2..9f1dfd0 100644
--- 
a/graph/src/main/java/org/apache/archiva/components/graph/base/SimpleVertex.java
+++ 
b/graph/src/main/java/org/apache/archiva/components/graph/base/SimpleNode.java
@@ -18,9 +18,10 @@ package org.apache.archiva.components.graph.base;
  * under the License.
  */
 
+import org.apache.archiva.components.graph.api.Category;
 import org.apache.archiva.components.graph.api.Edge;
 import org.apache.archiva.components.graph.api.Graph;
-import org.apache.archiva.components.graph.api.Vertex;
+import org.apache.archiva.components.graph.api.Node;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -29,16 +30,17 @@ import java.util.List;
  * Simple vertex implementation. The hash value is based on the id.
  * Comparation is by label, if exists, otherwise by id.
  */
-public class SimpleVertex implements Vertex<SimpleVertex>, 
Comparable<SimpleVertex>
+public class SimpleNode implements Node<SimpleNode>, Comparable<SimpleNode>
 {
 
     private final String id;
     private String label;
-    private final Graph<SimpleVertex> graph;
-    private List<Edge<SimpleVertex>> outEdges = new ArrayList<>();
-    private List<Edge<SimpleVertex>> inEdges = new ArrayList<>();
+    private final Graph<SimpleNode> graph;
+    private List<Edge<SimpleNode>> outEdges = new ArrayList<>();
+    private List<Edge<SimpleNode>> inEdges = new ArrayList<>();
+    private List<Category> categories;
 
-    SimpleVertex(Graph<SimpleVertex> graph, String id) {
+    SimpleNode(Graph<SimpleNode> graph, String id) {
         this.id = id;
         this.graph = graph;
     }
@@ -59,21 +61,21 @@ public class SimpleVertex implements Vertex<SimpleVertex>, 
Comparable<SimpleVert
     }
 
     @Override
-    public Graph<SimpleVertex> getGraph() {
+    public Graph<SimpleNode> getGraph() {
         return graph;
     }
 
     @Override
-    public List<Edge<SimpleVertex>> getOutEdges() {
+    public List<Edge<SimpleNode>> getOutEdges() {
         return outEdges;
     }
 
     @Override
-    public List<Edge<SimpleVertex>> getInEdges() {
+    public List<Edge<SimpleNode>> getInEdges() {
         return inEdges;
     }
 
-    protected void addEdge(Edge<SimpleVertex> edge) {
+    protected void addEdge(Edge<SimpleNode> edge) {
         if (edge.getSource() == this) {
             outEdges.add(edge);
         } else if (edge.getDestination() == this) {
@@ -90,10 +92,10 @@ public class SimpleVertex implements Vertex<SimpleVertex>, 
Comparable<SimpleVert
 
     @Override
     public String toString() {
-        return this.id+"|"+this.label;
+        return this.id+"("+this.label+")";
     }
 
-    public void removeEdge(Edge<SimpleVertex> edge) {
+    public void removeEdge(Edge<SimpleNode> edge) {
         if (edge.getDestination()==this) {
             inEdges.remove(edge);
         } else if (edge.getSource()==this) {
@@ -102,11 +104,34 @@ public class SimpleVertex implements 
Vertex<SimpleVertex>, Comparable<SimpleVert
     }
 
     @Override
-    public int compareTo(SimpleVertex o) {
+    public int compareTo(SimpleNode o) {
         if (label!=null && o.getLabel()!=null) {
             return this.label.compareTo(o.getLabel());
         } else {
             return this.id.compareTo(o.getId());
         }
     }
+
+    public void addCategory(Category category) {
+        if (this.categories == null) {
+            this.categories = new ArrayList<>();
+        }
+        if (!this.categories.contains(category)) {
+            this.categories.add(category);
+        }
+    }
+
+    public void removeCategory(Category category) {
+        if (this.categories != null) {
+            this.categories.remove(category);
+        }
+    }
+
+    @Override
+    public List<Category> getCategories() {
+        if (this.categories ==null) {
+            this.categories = new ArrayList<>();
+        }
+        return categories;
+    }
 }
diff --git 
a/graph/src/main/java/org/apache/archiva/components/graph/util/Traversal.java 
b/graph/src/main/java/org/apache/archiva/components/graph/util/Traversal.java
index e80f26a..e55f7f9 100644
--- 
a/graph/src/main/java/org/apache/archiva/components/graph/util/Traversal.java
+++ 
b/graph/src/main/java/org/apache/archiva/components/graph/util/Traversal.java
@@ -19,14 +19,13 @@ package org.apache.archiva.components.graph.util;
  */
 
 import org.apache.archiva.components.graph.api.Edge;
+import org.apache.archiva.components.graph.api.Node;
 import org.apache.archiva.components.graph.api.TraversalStatus;
-import org.apache.archiva.components.graph.api.Vertex;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.*;
-import java.util.function.Consumer;
-import java.util.function.Function;
+import java.util.function.BiFunction;
 
 /**
  * Utility class for graph traversal.
@@ -46,84 +45,96 @@ public class Traversal {
      * @param start           the start node
      * @param consumer        The consumer function. The function must return 
<code>true</code>, if the traversal should
      *                        continue, otherwise <code>false</code>
-     * @param directed        If true, only outgoing edges are used to 
navigate to neighbours, otherwise incoming and outgoing
-     *                        edges are used.
-     * @param continueOnError If true, the traversal continues, even if the 
consumer function threw an error
+     * @param flags Sets some flags for traversal behaviour
      * @param <V>
      * @return The traversal status
      */
-    @SuppressWarnings("Duplicates")
-    public static <V extends Vertex<V>> TraversalStatus<V> depthFirst(final V 
start, final Function<V, Boolean> consumer,
-                                                                      final 
boolean directed, final boolean continueOnError) {
+    public static <V extends Node<V>> TraversalStatus<V> depthFirst(final V 
start, final BiFunction<V, TraversalStatus<V>, Boolean> consumer,
+                                                                    final 
BiFunction<V, TraversalStatus<V>, Boolean> afterChildConsumer,
+                                                                    final 
TraversalFlags flags) {
         TraversalStatus<V> status = new TraversalStatus<>();
         Set<V> visited = new LinkedHashSet<>();
         Stack<V> stack = new Stack<>();
         stack.push(start);
         while (!stack.isEmpty()) {
-            V vertex = stack.pop();
-            if (!visited.contains(vertex)) {
+            V node = stack.peek();
+            if (!visited.contains(node)) {
                 Boolean continueTraversal = Boolean.TRUE;
                 try {
-                    continueTraversal = consumer.apply(vertex);
+                    continueTraversal = consumer.apply(node, status);
                 } catch (Throwable e) {
-                    log.debug("Error during visit. Vertex: {}, Message: {}", 
vertex, e.getMessage());
-                    status.addError(vertex, e);
-                    if (!continueOnError) {
+                    log.debug("Error during visit. Node: {}, Message: {}", 
node, e.getMessage());
+                    status.addError(node, e);
+                    if (!flags.isContinueOnError()) {
                         break;
                     }
                 }
-                visited.add(vertex);
-                log.debug("Visited: " + vertex);
+                visited.add(node);
+                log.debug("Visited: " + node);
                 if (!continueTraversal) {
+                    log.debug("Aborting from consumer on node {}", 
node.getId());
                     break;
                 }
                 // We traverse using the order of the edges. This is a stack, 
so the elements that
                 // should be visited first are pushed last on the stack.
-                final List<Edge<V>> outEdges = vertex.getOutEdges();
-                final int outEdgeMaxIdx = vertex.getOutEdges().size() - 1;
+                final List<Edge<V>> outEdges = node.getOutEdges();
+                final int outEdgeMaxIdx = node.getOutEdges().size() - 1;
                 for (int i = outEdgeMaxIdx; i >= 0; i--) {
                     try {
                         Edge<V> v = outEdges.get(i);
-                        log.debug("Directed destination: " + 
v.getDestination());
-                        stack.push(v.getDestination());
+                        V dest = v.getDestination();
+                        log.debug("Directed destination: {}", dest.getId());
+                        if (!visited.contains(dest)) {
+                            log.debug("Adding to stack {}", dest.getId());
+                            stack.push(dest);
+                        } else if (stack.contains(dest)) {
+                            log.debug("Cycle detected {}", dest.getId());
+                            status.registerCycle(dest);
+                        }
                     } catch (IndexOutOfBoundsException e) {
-                        log.warn("Modification of graph during traversal of 
output edges: " + vertex + " Index: " + i);
+                        log.warn("Modification of graph during traversal of 
output edges: " + node + " Index: " + i);
                     }
                 }
-                if (!directed) {
-                    final List<Edge<V>> inEdges = vertex.getInEdges();
-                    final int inEdgeMaxIdx = vertex.getOutEdges().size() - 1;
+                if (!flags.isDirected()) {
+                    final List<Edge<V>> inEdges = node.getInEdges();
+                    final int inEdgeMaxIdx = node.getOutEdges().size() - 1;
                     for (int i = inEdgeMaxIdx; i >= 0; i--) {
                         try {
                             Edge<V> v = inEdges.get(i);
+                            V source = v.getSource();
                             log.debug("Undirected source: " + v.getSource());
-                            stack.push(v.getSource());
+                            if (!visited.contains(source)) {
+                                stack.push(source);
+                            } else if (stack.contains(source)) {
+                                status.registerCycle(source);
+                            }
                         } catch (IndexOutOfBoundsException e) {
-                            log.warn("Modification of graph during traversal 
of input edges: " + vertex + " Index: " + i);
+                            log.warn("Modification of graph during traversal 
of input edges: " + node + " Index: " + i);
                         }
                     }
                 }
             } else {
-                status.registerCycle(vertex);
+                node = stack.pop();
+                if (!afterChildConsumer.apply(node, status)) {
+                    log.debug("Aborting from after child consumer on node {}", 
node.getId());
+                    break;
+                }
             }
         }
         return status;
     }
 
-    /**
-     * Same as {@link #depthFirst(Vertex, Function, boolean, boolean)} but 
sets the <code>continueOnError</code> parameter to <code>true</code>.
-     */
-    public static <V extends Vertex<V>> TraversalStatus<V> depthFirst(V start, 
Function<V, Boolean> consumer,
-                                                                      boolean 
directed) {
-        return depthFirst(start, consumer, directed, true);
+    public static <V extends Node<V>> TraversalStatus<V> depthFirst(final V 
start, final BiFunction<V, TraversalStatus<V>, Boolean> consumer,
+                                                                    final 
TraversalFlags flags) {
+        return depthFirst(start, consumer, (v, s) -> true, flags);
     }
 
     /**
-     * Same as {@link #depthFirst(Vertex, Function, boolean, boolean)} but 
sets the <code>continueOnError</code>
+     * Same as {@link #depthFirst(Node, BiFunction, TraversalFlags)} but sets 
the <code>continueOnError</code>
      * parameter to <code>true</code> and <code>directed</code> parameter to 
<code>true</code>.
      */
-    public static <V extends Vertex<V>> TraversalStatus<V> depthFirst(V start, 
Function<V, Boolean> consumer) {
-        return depthFirst(start, consumer, true, true);
+    public static <V extends Node<V>> TraversalStatus<V> depthFirst(V start, 
BiFunction<V, TraversalStatus<V>, Boolean> consumer) {
+        return depthFirst(start, consumer, new TraversalFlags());
     }
 
     /**
@@ -133,70 +144,123 @@ public class Traversal {
      * traversal should continue.
      * If the directed flag is set to true, only outgoing edges are used for 
traversal from one one
      * to the other, otherwise, incoming edges are used too.
+     * This breadth first algorithm is not able to detect cycles, in a 
directed graph. Only in undirected.
      *
      * @param start           the start node
      * @param consumer        The consumer function. The function must return 
<code>true</code>, if the traversal should
      *                        continue, otherwise <code>false</code>
-     * @param directed        If true, only outgoing edges are used to 
navigate to neighbours, otherwise incoming and outgoing
-     *                        edges are used.
-     * @param continueOnError If true, the traversal continues, even if the 
consumer function threw an error
+     * @param flags flags that control traversal behaviour
      * @param <V>
      * @return The traversal status
      */
     @SuppressWarnings("Duplicates")
-    public static <V extends Vertex<V>> TraversalStatus<V> breadthFirst(final 
V start, final Function<V, Boolean> consumer,
-                                                                        final 
boolean directed, final boolean continueOnError) {
+    public static <V extends Node<V>> TraversalStatus<V> breadthFirst(final V 
start,
+                                                                      final 
BiFunction<V, TraversalStatus<V>, Boolean> consumer,
+                                                                      final 
TraversalFlags flags) {
         final TraversalStatus<V> status = new TraversalStatus<>();
         final Set<V> visited = new LinkedHashSet<>();
         final Queue<V> queue = new LinkedList<>();
         queue.add(start);
         while (!queue.isEmpty()) {
-            V vertex = queue.poll();
-            if (!visited.contains(vertex)) {
+            V node = queue.poll();
+            if (!visited.contains(node)) {
                 Boolean continueTraversal = Boolean.TRUE;
                 try {
-                    continueTraversal = consumer.apply(vertex);
+                    continueTraversal = consumer.apply(node, status);
                 } catch (Throwable e) {
-                    log.debug("Error during visit. Vertex: {}, Message: {}", 
vertex, e.getMessage());
-                    status.addError(vertex, e);
-                    if (!continueOnError) {
+                    log.debug("Error during visit. Node: {}, Message: {}", 
node, e.getMessage());
+                    status.addError(node, e);
+                    if (!flags.isContinueOnError()) {
                         break;
                     }
                 }
-                visited.add(vertex);
-                log.debug("Visited: " + vertex);
+                visited.add(node);
+                log.debug("Visited: " + node);
                 if (!continueTraversal) {
                     break;
                 }
-                for (Edge<V> v : vertex.getOutEdges()) {
+                for (Edge<V> v : node.getOutEdges()) {
                     queue.add(v.getDestination());
                 }
-                if (!directed) {
-                    for (Edge<V> v : vertex.getInEdges()) {
-                        queue.add(v.getSource());
+                if (!flags.isDirected()) {
+                    for (Edge<V> v : node.getInEdges()) {
+                       queue.add(v.getSource());
                     }
                 }
-            } else {
-                status.registerCycle(vertex);
+            } else if (!flags.isDirected()) {
+                status.registerCycle(node);
             }
         }
         return status;
     }
 
     /**
-     * Same as {@link #breadthFirst(Vertex, Function, boolean, boolean)} but 
sets <code>continueOnError</code>  to <code>true</code>.
+     * Same as {@link #breadthFirst(Node, BiFunction, TraversalFlags)} but 
sets <code>continueOnError</code> to <code>true</code>
+     * and <code>directed</code> to <code>true</code>.
      */
-    public static <V extends Vertex<V>> TraversalStatus<V> breadthFirst(final 
V start, final Function<V, Boolean> consumer,
-                                                                        final 
boolean directed) {
-        return breadthFirst(start, consumer, directed, true);
+    public static <V extends Node<V>> TraversalStatus<V> breadthFirst(final V 
start, final BiFunction<V, TraversalStatus<V>, Boolean> consumer) {
+        return breadthFirst(start, consumer, new TraversalFlags());
     }
 
     /**
-     * Same as {@link #breadthFirst(Vertex, Function, boolean, boolean)} but 
sets <code>continueOnError</code> to <code>true</code>
-     * and <code>directed</code> to <code>true</code>.
+     * Traverses the graph, stops and returns <code>true</code> if it founds a 
cycle, otherwise returns
+     * <code>false</code>
+     *
+     * @param startNode the start node where the traversal starts
+     * @param <V>
+     * @return <code>true</code>, if a cycle was found, otherwise 
<code>false</code>
+     */
+    public static <V extends Node<V>> boolean hasCycle(final V startNode) {
+        TraversalStatus<V> status = depthFirst(startNode, (n, s) -> 
!s.hasCycles());
+        return status.hasCycles();
+    }
+
+    /**
+     * Traverses the graph and if a cycle was detected returns the node where 
the cycle was detected.
+     * Otherwise returns <code>null</code>
+     * @param startNode the start node, where the traversal starts
+     * @param <V>
+     * @return the node, where the cycle was detected, otherwise 
<code>null</code>
+     */
+    public static <V extends Node<V>> V findFirstCycleNode(final V startNode) {
+        TraversalStatus<V> status = depthFirst(startNode, (n, s) -> 
!s.hasCycles());
+        if (status.hasCycles()) {
+            return status.getCycleNodes().get(0);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Traverses the graph and if a cycle was detected returns the node where 
the cycle was detected.
+     * Otherwise returns <code>null</code>
+     * @param startNode the start node, where the traversal starts
+     * @param <V>
+     * @return the node, where the cycle was detected, otherwise 
<code>null</code>
+     */
+    public static <V extends Node<V>> List<V> findAllCycleNodes(final V 
startNode) {
+        TraversalStatus<V> status = depthFirst(startNode, (n, s) -> true);
+        if (status.hasCycles()) {
+            return status.getCycleNodes();
+        } else {
+            return Collections.emptyList();
+        }
+    }
+
+    /**
+     * Sorts the graph starting at the <code>startNode</code> in topological 
order. That means
+     * for a given path the deepest nodes are before their ancestors.
+     * For nodes of the same level the order is the order of the edges on the 
source node.
+     *
+     * @param startNode the node where the traversal will start
+     * @param <V>
+     * @return A list of sorted nodes
      */
-    public static <V extends Vertex<V>> TraversalStatus<V> breadthFirst(final 
V start, final Function<V, Boolean> consumer) {
-        return breadthFirst(start, consumer, true, true);
+    public static <V extends Node<V>> List<V> topologialSort(final V 
startNode) {
+        List<V> nodeList = new ArrayList<>();
+        TraversalStatus<V> status = depthFirst(startNode, (n, s) -> true,
+                (n,s)->{nodeList.add(n); return true;}, new TraversalFlags());
+        return nodeList;
     }
 
 }
diff --git 
a/graph/src/main/java/org/apache/archiva/components/graph/util/TraversalFlags.java
 
b/graph/src/main/java/org/apache/archiva/components/graph/util/TraversalFlags.java
new file mode 100644
index 0000000..1019a54
--- /dev/null
+++ 
b/graph/src/main/java/org/apache/archiva/components/graph/util/TraversalFlags.java
@@ -0,0 +1,67 @@
+package org.apache.archiva.components.graph.util;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Flags that control traversal behaviour
+ */
+public class TraversalFlags {
+    private final boolean directed;
+    private final boolean continueOnError;
+
+    public TraversalFlags() {
+        this.directed = true;
+        this.continueOnError = true;
+    }
+
+    public TraversalFlags(boolean directed, boolean continueOnError) {
+        this.directed = directed;
+        this.continueOnError = continueOnError;
+    }
+
+    public TraversalFlags(boolean directed, boolean continueOnError, boolean 
consumeParentAfterChild) {
+        this.directed = directed;
+        this.continueOnError = continueOnError;
+    }
+
+    /**
+     * If the <code>directed=true</code>, traversal will only use source to 
destination links not reverse.
+     * If the value is <code>false</code> traversal will use every edge from a 
given node regardless of the
+     * direction.
+     * Default is <code>true</code>
+     *
+     * @return true, if the graph is directed otherwise false
+     */
+    public boolean isDirected() {
+        return directed;
+    }
+
+    /**
+     * If this flag is <code>true</code>, the traversal will continue, if the 
consumer function
+     * throws an error. Otherwise the traversal will be stopped.
+     * Default is <code>true</code>
+     *
+     * @return <code>true</code>, if traversal should continue on error, 
otherwise <code>false</code>
+     */
+    public boolean isContinueOnError() {
+        return continueOnError;
+    }
+
+
+}
diff --git 
a/graph/src/test/java/org/apache/archiva/components/graph/base/BaseEdgeTest.java
 
b/graph/src/test/java/org/apache/archiva/components/graph/base/BaseEdgeTest.java
index 22f2e3d..02e3f47 100644
--- 
a/graph/src/test/java/org/apache/archiva/components/graph/base/BaseEdgeTest.java
+++ 
b/graph/src/test/java/org/apache/archiva/components/graph/base/BaseEdgeTest.java
@@ -26,14 +26,14 @@ import static org.junit.jupiter.api.Assertions.*;
 class BaseEdgeTest {
 
 
-    private Graph<SimpleVertex> graph = new SimpleGraph();
+    private Graph<SimpleNode> graph = new SimpleGraph();
 
     @Test
     void getId() {
-        SimpleVertex vtx1 = new SimpleVertex(graph, "vtx1");
-        SimpleVertex vtx2 = new SimpleVertex(graph, "vtx2");
+        SimpleNode vtx1 = new SimpleNode(graph, "vtx1");
+        SimpleNode vtx2 = new SimpleNode(graph, "vtx2");
 
-        BaseEdge<SimpleVertex> edge = new BaseEdge<>(graph, "edge01", vtx1, 
vtx2);
+        BaseEdge<SimpleNode> edge = new BaseEdge<>(graph, "edge01", vtx1, 
vtx2);
 
         assertNotNull(edge.getId());
         assertEquals("edge01", edge.getId());
@@ -43,10 +43,10 @@ class BaseEdgeTest {
 
     @Test
     void getLabel() {
-        SimpleVertex vtx1 = new SimpleVertex(graph, "vtx1");
-        SimpleVertex vtx2 = new SimpleVertex(graph, "vtx2");
+        SimpleNode vtx1 = new SimpleNode(graph, "vtx1");
+        SimpleNode vtx2 = new SimpleNode(graph, "vtx2");
 
-        BaseEdge<SimpleVertex> edge = new BaseEdge<>(graph, "edge01", vtx1, 
vtx2);
+        BaseEdge<SimpleNode> edge = new BaseEdge<>(graph, "edge01", vtx1, 
vtx2);
 
         assertNull(edge.getLabel());
 
@@ -61,10 +61,10 @@ class BaseEdgeTest {
 
     @Test
     void setWeight() {
-        SimpleVertex vtx1 = new SimpleVertex(graph, "vtx1");
-        SimpleVertex vtx2 = new SimpleVertex(graph, "vtx2");
+        SimpleNode vtx1 = new SimpleNode(graph, "vtx1");
+        SimpleNode vtx2 = new SimpleNode(graph, "vtx2");
 
-        BaseEdge<SimpleVertex> edge = new BaseEdge<>(graph, "edge01", vtx1, 
vtx2);
+        BaseEdge<SimpleNode> edge = new BaseEdge<>(graph, "edge01", vtx1, 
vtx2);
 
         assertEquals(1.0, edge.getWeight());
 
@@ -77,30 +77,30 @@ class BaseEdgeTest {
 
     @Test
     void getGraph() {
-        SimpleVertex vtx1 = new SimpleVertex(graph, "vtx1");
-        SimpleVertex vtx2 = new SimpleVertex(graph, "vtx2");
+        SimpleNode vtx1 = new SimpleNode(graph, "vtx1");
+        SimpleNode vtx2 = new SimpleNode(graph, "vtx2");
 
-        BaseEdge<SimpleVertex> edge = new BaseEdge<>(graph, "edge01", vtx1, 
vtx2);
+        BaseEdge<SimpleNode> edge = new BaseEdge<>(graph, "edge01", vtx1, 
vtx2);
         assertNotNull(edge.getGraph());
         assertTrue(edge.getGraph() == graph);
     }
 
     @Test
     void getInVertex() {
-        SimpleVertex vtx1 = new SimpleVertex(graph, "vtx1");
-        SimpleVertex vtx2 = new SimpleVertex(graph, "vtx2");
+        SimpleNode vtx1 = new SimpleNode(graph, "vtx1");
+        SimpleNode vtx2 = new SimpleNode(graph, "vtx2");
 
-        BaseEdge<SimpleVertex> edge = new BaseEdge<>(graph, "edge01", vtx1, 
vtx2);
+        BaseEdge<SimpleNode> edge = new BaseEdge<>(graph, "edge01", vtx1, 
vtx2);
 
         assertEquals(vtx1, edge.getSource());
     }
 
     @Test
     void getOutVertex() {
-        SimpleVertex vtx1 = new SimpleVertex(graph, "vtx1");
-        SimpleVertex vtx2 = new SimpleVertex(graph, "vtx2");
+        SimpleNode vtx1 = new SimpleNode(graph, "vtx1");
+        SimpleNode vtx2 = new SimpleNode(graph, "vtx2");
 
-        BaseEdge<SimpleVertex> edge = new BaseEdge<>(graph, "edge01", vtx1, 
vtx2);
+        BaseEdge<SimpleNode> edge = new BaseEdge<>(graph, "edge01", vtx1, 
vtx2);
 
         assertEquals(vtx2, edge.getDestination());
     }
diff --git 
a/graph/src/test/java/org/apache/archiva/components/graph/base/SimpleGraphTest.java
 
b/graph/src/test/java/org/apache/archiva/components/graph/base/SimpleGraphTest.java
index 6455528..859a002 100644
--- 
a/graph/src/test/java/org/apache/archiva/components/graph/base/SimpleGraphTest.java
+++ 
b/graph/src/test/java/org/apache/archiva/components/graph/base/SimpleGraphTest.java
@@ -19,6 +19,7 @@ package org.apache.archiva.components.graph.base;
  */
 
 import org.apache.archiva.components.graph.api.Edge;
+import org.apache.archiva.components.graph.api.StandardRelationType;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
@@ -26,9 +27,9 @@ import static org.junit.jupiter.api.Assertions.*;
 class SimpleGraphTest {
 
     @Test
-    void createNewVertex() {
+    void createNewNode() {
         SimpleGraph graph = new SimpleGraph();
-        SimpleVertex vtx = graph.createNewVertex();
+        SimpleNode vtx = graph.createNewNode();
         assertNotNull(vtx);
         assertNotNull(vtx.getId());
         assertNotNull(java.util.UUID.fromString(vtx.getId()));
@@ -37,9 +38,9 @@ class SimpleGraphTest {
     @Test
     void createNewEdge() {
         SimpleGraph graph = new SimpleGraph();
-        SimpleVertex vtx1 = graph.createNewVertex();
-        SimpleVertex vtx2 = graph.createNewVertex();
-        Edge<SimpleVertex> edge = graph.createNewEdge(vtx1, vtx2);
+        SimpleNode vtx1 = graph.createNewNode();
+        SimpleNode vtx2 = graph.createNewNode();
+        Edge<SimpleNode> edge = 
graph.createNewEdge(StandardRelationType.DEFAULT, vtx1, vtx2);
         assertNotNull(edge);
         assertNotNull(edge.getId());
         assertNotNull(java.util.UUID.fromString(edge.getId()));
@@ -51,9 +52,9 @@ class SimpleGraphTest {
     @Test
     void removeEdge() {
         SimpleGraph graph = new SimpleGraph();
-        SimpleVertex vtx1 = graph.createNewVertex();
-        SimpleVertex vtx2 = graph.createNewVertex();
-        Edge<SimpleVertex> edge = graph.createNewEdge(vtx1, vtx2);
+        SimpleNode vtx1 = graph.createNewNode();
+        SimpleNode vtx2 = graph.createNewNode();
+        Edge<SimpleNode> edge = 
graph.createNewEdge(StandardRelationType.DEFAULT, vtx1, vtx2);
 
         graph.removeEdge(edge);
 
@@ -65,6 +66,79 @@ class SimpleGraphTest {
     }
 
     @Test
-    void removeVertex() {
+    void removeNode() {
+        String label = "root";
+        SimpleGraph graph = new SimpleGraph();
+        SimpleNode node = graph.newNode(label);
+
+        assertNotNull(node);
+        assertNotNull(graph.getNode(node.getId()));
+
+        graph.removeNode(node);
+        assertNull(graph.getNode(node.getId()));
+
+    }
+
+    @Test
+    void removeNodeWithEdges() {
+        String label = "root";
+        SimpleGraph graph = new SimpleGraph();
+        SimpleNode node1 = graph.newNode("1");
+        SimpleNode node2 = graph.newNode("2");
+        Edge<SimpleNode> edge1 = graph.newEdge("1:2", node1, node2);
+        Edge<SimpleNode> edge2 = graph.newEdge("2:1", node2, node1);
+
+
+
+        assertNotNull(node1);
+        assertNotNull(graph.getNode(node1.getId()));
+
+        graph.removeNode(node1);
+
+        assertNull(graph.getNode(node1.getId()));
+
+        assertEquals(0, node2.getInEdges().size());
+        assertEquals(0, node2.getOutEdges().size());
+
+
+    }
+
+    @Test
+    void getNode() {
+        String label = "root";
+        SimpleGraph graph = new SimpleGraph();
+        SimpleNode node = graph.newNode(label);
+
+        assertNotNull(node);
+        SimpleNode foundNode = graph.getNode(node.getId());
+        assertNotNull(foundNode);
+        assertEquals(node, foundNode);
+        assertEquals(label, foundNode.getLabel());
+
+    }
+
+
+    @Test
+    void newNode() {
+        String label = "root";
+        SimpleGraph graph = new SimpleGraph();
+        SimpleNode node = graph.newNode(label);
+
+        assertNotNull(node);
+        assertEquals(label, node.getLabel());
+
     }
+
+    @Test
+    void addNode() {
+        String id = "root";
+        SimpleGraph graph = new SimpleGraph();
+        SimpleNode node = graph.addNode(id, id);
+
+        assertNotNull(node);
+        assertNotNull(graph.getNode(id));
+        assertEquals(id, graph.getNode(id).getLabel());
+
+    }
+
 }
\ No newline at end of file
diff --git 
a/graph/src/test/java/org/apache/archiva/components/graph/base/SimpleVertexTest.java
 
b/graph/src/test/java/org/apache/archiva/components/graph/base/SimpleNodeTest.java
similarity index 86%
rename from 
graph/src/test/java/org/apache/archiva/components/graph/base/SimpleVertexTest.java
rename to 
graph/src/test/java/org/apache/archiva/components/graph/base/SimpleNodeTest.java
index e468e48..9b849d2 100644
--- 
a/graph/src/test/java/org/apache/archiva/components/graph/base/SimpleVertexTest.java
+++ 
b/graph/src/test/java/org/apache/archiva/components/graph/base/SimpleNodeTest.java
@@ -24,26 +24,26 @@ import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
 
-class SimpleVertexTest {
+class SimpleNodeTest {
 
-    private Graph<SimpleVertex> graph = new SimpleGraph();
+    private Graph<SimpleNode> graph = new SimpleGraph();
 
     @Test
 
     void getId() {
-        SimpleVertex vtx = new SimpleVertex(graph, "testid001");
+        SimpleNode vtx = new SimpleNode(graph, "testid001");
         assertNotNull(vtx.getId());
         assertEquals("testid001", vtx.getId());
     }
 
     @Test
     void getLabel() {
-        SimpleVertex vtx = new SimpleVertex(graph, "testid001");
+        SimpleNode vtx = new SimpleNode(graph, "testid001");
         assertNull(vtx.getLabel());
         vtx.setLabel("test");
         assertEquals("test", vtx.getLabel());
 
-        vtx = new SimpleVertex(graph, "testid001");
+        vtx = new SimpleNode(graph, "testid001");
         vtx.setLabel("Another label with more characters üy@~ ---");
         assertNotNull(vtx.getLabel());
         assertEquals("Another label with more characters üy@~ ---", 
vtx.getLabel());
@@ -53,15 +53,15 @@ class SimpleVertexTest {
 
     @Test
     void getGraph() {
-        SimpleVertex vtx = new SimpleVertex(graph, "test");
+        SimpleNode vtx = new SimpleNode(graph, "test");
         assertNotNull(vtx.getGraph());
         assertTrue(vtx.getGraph() == graph);
     }
 
     @Test
     void getInOutEdges() {
-        SimpleVertex vtx1 = new SimpleVertex(graph, "test1");
-        SimpleVertex vtx2 = new SimpleVertex(graph, "test2");
+        SimpleNode vtx1 = new SimpleNode(graph, "test1");
+        SimpleNode vtx2 = new SimpleNode(graph, "test2");
         vtx1.addEdge(new BaseEdge<>(graph, "edge11_1to2", vtx1, vtx2));
         vtx1.addEdge(new BaseEdge<>(graph, "edge12_1to2", vtx1, vtx2));
         vtx1.addEdge(new BaseEdge<>(graph, "edge13_1to2", vtx1, vtx2));
@@ -85,8 +85,8 @@ class SimpleVertexTest {
 
     @Test
     void removeEdge() {
-        SimpleVertex vtx1 = new SimpleVertex(graph, "test1");
-        SimpleVertex vtx2 = new SimpleVertex(graph, "test2");
+        SimpleNode vtx1 = new SimpleNode(graph, "test1");
+        SimpleNode vtx2 = new SimpleNode(graph, "test2");
         vtx1.addEdge(new BaseEdge<>(graph, "edge11_1to2", vtx1, vtx2));
         vtx1.addEdge(new BaseEdge<>(graph, "edge12_1to2", vtx1, vtx2));
         vtx1.addEdge(new BaseEdge<>(graph, "edge13_1to2", vtx1, vtx2));
@@ -100,7 +100,7 @@ class SimpleVertexTest {
         vtx1.addEdge(new BaseEdge<>(graph, "edge15_2to1", vtx2, vtx1));
         vtx1.addEdge(new BaseEdge<>(graph, "edge16_2to1", vtx2, vtx1));
         vtx2.addEdge(new BaseEdge<>(graph, "edge21_2to1", vtx2, vtx1));
-        Edge<SimpleVertex> edge = vtx1.getOutEdges().get(0);
+        Edge<SimpleNode> edge = vtx1.getOutEdges().get(0);
         vtx1.removeEdge(edge);
         edge = vtx1.getInEdges().get(0);
         vtx1.removeEdge(edge);
diff --git 
a/graph/src/test/java/org/apache/archiva/components/graph/util/TraversalTest.java
 
b/graph/src/test/java/org/apache/archiva/components/graph/util/TraversalTest.java
index cbc26f1..7ae9f33 100644
--- 
a/graph/src/test/java/org/apache/archiva/components/graph/util/TraversalTest.java
+++ 
b/graph/src/test/java/org/apache/archiva/components/graph/util/TraversalTest.java
@@ -20,12 +20,13 @@ package org.apache.archiva.components.graph.util;
 
 import org.apache.archiva.components.graph.api.TraversalStatus;
 import org.apache.archiva.components.graph.base.SimpleGraph;
-import org.apache.archiva.components.graph.base.SimpleVertex;
+import org.apache.archiva.components.graph.base.SimpleNode;
 import org.junit.jupiter.api.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 import static org.junit.jupiter.api.Assertions.*;
@@ -37,55 +38,55 @@ class TraversalTest {
     @Test
     void depthFirstWithoutCycleAndWithoutError() {
         SimpleGraph graph = new SimpleGraph();
-        SimpleVertex vtx0 = graph.addVertex("root");
-        SimpleVertex vtx1 = graph.addVertex("vertex1");
-        SimpleVertex vtx11 = graph.addVertex("vertex11");
-        SimpleVertex vtx12 = graph.addVertex("vertex12");
-        SimpleVertex vtx2 = graph.addVertex("vertex2");
-        SimpleVertex vtx21 = graph.addVertex("vertex21");
-        SimpleVertex vtx211 = graph.addVertex("vertex211");
-        SimpleVertex vtx212 = graph.addVertex("vertex212");
-
-        SimpleVertex vtx22 = graph.addVertex("vertex22");
-        SimpleVertex vtx221 = graph.addVertex("vertex221");
-        SimpleVertex vtx222 = graph.addVertex("vertex222");
-        SimpleVertex vtx223 = graph.addVertex("vertex223");
-
-        SimpleVertex vtx3 = graph.addVertex("vertex3");
-        SimpleVertex vtx31 = graph.addVertex("vertex31");
-        SimpleVertex vtx32 = graph.addVertex("vertex32");
-        SimpleVertex vtx33 = graph.addVertex("vertex33");
-
-        graph.addEdge("root->1", vtx0, vtx1);
-        graph.addEdge("root->2", vtx0, vtx2);
-        graph.addEdge("root->3", vtx0, vtx3);
-
-        graph.addEdge("1->11", vtx1, vtx11);
-        graph.addEdge("1->12", vtx1, vtx12);
-
-        graph.addEdge("2->21", vtx2, vtx21);
-        graph.addEdge("2->22", vtx2, vtx22);
-
-        graph.addEdge("21->211", vtx21, vtx211);
-        graph.addEdge("21->212", vtx21, vtx212);
-
-        graph.addEdge("22->221", vtx22, vtx221);
-        graph.addEdge("22->222", vtx22, vtx222);
-        graph.addEdge("22->223", vtx22, vtx223);
-
-        graph.addEdge("3->31", vtx3, vtx31);
-        graph.addEdge("3->32", vtx3, vtx32);
-        graph.addEdge("3->33", vtx3, vtx33);
-
-        List<SimpleVertex> visitedNodes = new ArrayList<>();
-        TraversalStatus<SimpleVertex> status = Traversal.depthFirst(vtx0, v -> 
{
+        SimpleNode vtx0 = graph.newNode("root");
+        SimpleNode vtx1 = graph.newNode("vertex1");
+        SimpleNode vtx11 = graph.newNode("vertex11");
+        SimpleNode vtx12 = graph.newNode("vertex12");
+        SimpleNode vtx2 = graph.newNode("vertex2");
+        SimpleNode vtx21 = graph.newNode("vertex21");
+        SimpleNode vtx211 = graph.newNode("vertex211");
+        SimpleNode vtx212 = graph.newNode("vertex212");
+
+        SimpleNode vtx22 = graph.newNode("vertex22");
+        SimpleNode vtx221 = graph.newNode("vertex221");
+        SimpleNode vtx222 = graph.newNode("vertex222");
+        SimpleNode vtx223 = graph.newNode("vertex223");
+
+        SimpleNode vtx3 = graph.newNode("vertex3");
+        SimpleNode vtx31 = graph.newNode("vertex31");
+        SimpleNode vtx32 = graph.newNode("vertex32");
+        SimpleNode vtx33 = graph.newNode("vertex33");
+
+        graph.newEdge("root->1", vtx0, vtx1);
+        graph.newEdge("root->2", vtx0, vtx2);
+        graph.newEdge("root->3", vtx0, vtx3);
+
+        graph.newEdge("1->11", vtx1, vtx11);
+        graph.newEdge("1->12", vtx1, vtx12);
+
+        graph.newEdge("2->21", vtx2, vtx21);
+        graph.newEdge("2->22", vtx2, vtx22);
+
+        graph.newEdge("21->211", vtx21, vtx211);
+        graph.newEdge("21->212", vtx21, vtx212);
+
+        graph.newEdge("22->221", vtx22, vtx221);
+        graph.newEdge("22->222", vtx22, vtx222);
+        graph.newEdge("22->223", vtx22, vtx223);
+
+        graph.newEdge("3->31", vtx3, vtx31);
+        graph.newEdge("3->32", vtx3, vtx32);
+        graph.newEdge("3->33", vtx3, vtx33);
+
+        List<SimpleNode> visitedNodes = new ArrayList<>();
+        TraversalStatus<SimpleNode> status = Traversal.depthFirst(vtx0, ( v, s 
) -> {
             log.debug("Visiting vertex " + v);
             if (visitedNodes.contains(v)) {
                 throw new RuntimeException("Double visit of vertex: " + v);
             }
             visitedNodes.add(v);
             return true;
-        }, true);
+        });
 
         assertEquals(vtx0, visitedNodes.get(0));
         assertEquals(vtx1, visitedNodes.get(1));
@@ -111,57 +112,57 @@ class TraversalTest {
     @Test
     void depthFirstWithCycleAndWithoutError() {
         SimpleGraph graph = new SimpleGraph();
-        SimpleVertex vtx0 = graph.addVertex("root");
-        SimpleVertex vtx1 = graph.addVertex("vertex1");
-        SimpleVertex vtx11 = graph.addVertex("vertex11");
-        SimpleVertex vtx12 = graph.addVertex("vertex12");
-        SimpleVertex vtx2 = graph.addVertex("vertex2");
-        SimpleVertex vtx21 = graph.addVertex("vertex21");
-        SimpleVertex vtx211 = graph.addVertex("vertex211");
-        SimpleVertex vtx212 = graph.addVertex("vertex212");
-
-        SimpleVertex vtx22 = graph.addVertex("vertex22");
-        SimpleVertex vtx221 = graph.addVertex("vertex221");
-        SimpleVertex vtx222 = graph.addVertex("vertex222");
-        SimpleVertex vtx223 = graph.addVertex("vertex223");
-
-        SimpleVertex vtx3 = graph.addVertex("vertex3");
-        SimpleVertex vtx31 = graph.addVertex("vertex31");
-        SimpleVertex vtx32 = graph.addVertex("vertex32");
-        SimpleVertex vtx33 = graph.addVertex("vertex33");
-
-        graph.addEdge("root->1", vtx0, vtx1);
-        graph.addEdge("root->2", vtx0, vtx2);
-        graph.addEdge("root->3", vtx0, vtx3);
-
-        graph.addEdge("1->11", vtx1, vtx11);
-        graph.addEdge("1->12", vtx1, vtx12);
-
-        graph.addEdge("2->21", vtx2, vtx21);
-        graph.addEdge("2->22", vtx2, vtx22);
-        graph.addEdge("22->2", vtx22, vtx2);
-
-        graph.addEdge("21->211", vtx21, vtx211);
-        graph.addEdge("21->212", vtx21, vtx212);
-
-        graph.addEdge("22->221", vtx22, vtx221);
-        graph.addEdge("22->222", vtx22, vtx222);
-        graph.addEdge("22->223", vtx22, vtx223);
-        graph.addEdge("223->root", vtx223, vtx0);
-
-        graph.addEdge("3->31", vtx3, vtx31);
-        graph.addEdge("3->32", vtx3, vtx32);
-        graph.addEdge("3->33", vtx3, vtx33);
-
-        List<SimpleVertex> visitedNodes = new ArrayList<>();
-        TraversalStatus<SimpleVertex> status = Traversal.depthFirst(vtx0, v -> 
{
+        SimpleNode vtx0 = graph.newNode("root");
+        SimpleNode vtx1 = graph.newNode("vertex1");
+        SimpleNode vtx11 = graph.newNode("vertex11");
+        SimpleNode vtx12 = graph.newNode("vertex12");
+        SimpleNode vtx2 = graph.newNode("vertex2");
+        SimpleNode vtx21 = graph.newNode("vertex21");
+        SimpleNode vtx211 = graph.newNode("vertex211");
+        SimpleNode vtx212 = graph.newNode("vertex212");
+
+        SimpleNode vtx22 = graph.newNode("vertex22");
+        SimpleNode vtx221 = graph.newNode("vertex221");
+        SimpleNode vtx222 = graph.newNode("vertex222");
+        SimpleNode vtx223 = graph.newNode("vertex223");
+
+        SimpleNode vtx3 = graph.newNode("vertex3");
+        SimpleNode vtx31 = graph.newNode("vertex31");
+        SimpleNode vtx32 = graph.newNode("vertex32");
+        SimpleNode vtx33 = graph.newNode("vertex33");
+
+        graph.newEdge("root->1", vtx0, vtx1);
+        graph.newEdge("root->2", vtx0, vtx2);
+        graph.newEdge("root->3", vtx0, vtx3);
+
+        graph.newEdge("1->11", vtx1, vtx11);
+        graph.newEdge("1->12", vtx1, vtx12);
+
+        graph.newEdge("2->21", vtx2, vtx21);
+        graph.newEdge("2->22", vtx2, vtx22);
+        graph.newEdge("22->2", vtx22, vtx2);
+
+        graph.newEdge("21->211", vtx21, vtx211);
+        graph.newEdge("21->212", vtx21, vtx212);
+
+        graph.newEdge("22->221", vtx22, vtx221);
+        graph.newEdge("22->222", vtx22, vtx222);
+        graph.newEdge("22->223", vtx22, vtx223);
+        graph.newEdge("223->root", vtx223, vtx0);
+
+        graph.newEdge("3->31", vtx3, vtx31);
+        graph.newEdge("3->32", vtx3, vtx32);
+        graph.newEdge("3->33", vtx3, vtx33);
+
+        List<SimpleNode> visitedNodes = new ArrayList<>();
+        TraversalStatus<SimpleNode> status = Traversal.depthFirst(vtx0, (v, s) 
-> {
             log.debug("Visiting vertex " + v);
             if (visitedNodes.contains(v)) {
                 throw new RuntimeException("Double visit of vertex: " + v);
             }
             visitedNodes.add(v);
             return true;
-        }, true);
+        });
 
         assertEquals(vtx0, visitedNodes.get(0));
         assertEquals(vtx1, visitedNodes.get(1));
@@ -189,50 +190,50 @@ class TraversalTest {
     @Test
     void depthFirstWithCycleAndWithError() {
         SimpleGraph graph = new SimpleGraph();
-        SimpleVertex vtx0 = graph.addVertex("root");
-        SimpleVertex vtx1 = graph.addVertex("vertex1");
-        SimpleVertex vtx11 = graph.addVertex("vertex11");
-        SimpleVertex vtx12 = graph.addVertex("vertex12");
-        SimpleVertex vtx2 = graph.addVertex("vertex2");
-        SimpleVertex vtx21 = graph.addVertex("vertex21");
-        SimpleVertex vtx211 = graph.addVertex("vertex211");
-        SimpleVertex vtx212 = graph.addVertex("vertex212");
-
-        SimpleVertex vtx22 = graph.addVertex("vertex22");
-        SimpleVertex vtx221 = graph.addVertex("vertex221");
-        SimpleVertex vtx222 = graph.addVertex("vertex222");
-        SimpleVertex vtx223 = graph.addVertex("vertex223");
-
-        SimpleVertex vtx3 = graph.addVertex("vertex3");
-        SimpleVertex vtx31 = graph.addVertex("vertex31");
-        SimpleVertex vtx32 = graph.addVertex("vertex32");
-        SimpleVertex vtx33 = graph.addVertex("vertex33");
-
-        graph.addEdge("root->1", vtx0, vtx1);
-        graph.addEdge("root->2", vtx0, vtx2);
-        graph.addEdge("root->3", vtx0, vtx3);
-
-        graph.addEdge("1->11", vtx1, vtx11);
-        graph.addEdge("1->12", vtx1, vtx12);
-
-        graph.addEdge("2->21", vtx2, vtx21);
-        graph.addEdge("2->22", vtx2, vtx22);
-        graph.addEdge("22->2", vtx22, vtx2);
-
-        graph.addEdge("21->211", vtx21, vtx211);
-        graph.addEdge("21->212", vtx21, vtx212);
-
-        graph.addEdge("22->221", vtx22, vtx221);
-        graph.addEdge("22->222", vtx22, vtx222);
-        graph.addEdge("22->223", vtx22, vtx223);
-        graph.addEdge("223->root", vtx223, vtx0);
-
-        graph.addEdge("3->31", vtx3, vtx31);
-        graph.addEdge("3->32", vtx3, vtx32);
-        graph.addEdge("3->33", vtx3, vtx33);
-
-        List<SimpleVertex> visitedNodes = new ArrayList<>();
-        TraversalStatus<SimpleVertex> status = Traversal.depthFirst(vtx0, v -> 
{
+        SimpleNode vtx0 = graph.newNode("root");
+        SimpleNode vtx1 = graph.newNode("vertex1");
+        SimpleNode vtx11 = graph.newNode("vertex11");
+        SimpleNode vtx12 = graph.newNode("vertex12");
+        SimpleNode vtx2 = graph.newNode("vertex2");
+        SimpleNode vtx21 = graph.newNode("vertex21");
+        SimpleNode vtx211 = graph.newNode("vertex211");
+        SimpleNode vtx212 = graph.newNode("vertex212");
+
+        SimpleNode vtx22 = graph.newNode("vertex22");
+        SimpleNode vtx221 = graph.newNode("vertex221");
+        SimpleNode vtx222 = graph.newNode("vertex222");
+        SimpleNode vtx223 = graph.newNode("vertex223");
+
+        SimpleNode vtx3 = graph.newNode("vertex3");
+        SimpleNode vtx31 = graph.newNode("vertex31");
+        SimpleNode vtx32 = graph.newNode("vertex32");
+        SimpleNode vtx33 = graph.newNode("vertex33");
+
+        graph.newEdge("root->1", vtx0, vtx1);
+        graph.newEdge("root->2", vtx0, vtx2);
+        graph.newEdge("root->3", vtx0, vtx3);
+
+        graph.newEdge("1->11", vtx1, vtx11);
+        graph.newEdge("1->12", vtx1, vtx12);
+
+        graph.newEdge("2->21", vtx2, vtx21);
+        graph.newEdge("2->22", vtx2, vtx22);
+        graph.newEdge("22->2", vtx22, vtx2);
+
+        graph.newEdge("21->211", vtx21, vtx211);
+        graph.newEdge("21->212", vtx21, vtx212);
+
+        graph.newEdge("22->221", vtx22, vtx221);
+        graph.newEdge("22->222", vtx22, vtx222);
+        graph.newEdge("22->223", vtx22, vtx223);
+        graph.newEdge("223->root", vtx223, vtx0);
+
+        graph.newEdge("3->31", vtx3, vtx31);
+        graph.newEdge("3->32", vtx3, vtx32);
+        graph.newEdge("3->33", vtx3, vtx33);
+
+        List<SimpleNode> visitedNodes = new ArrayList<>();
+        TraversalStatus<SimpleNode> status = Traversal.depthFirst(vtx0, (v,s) 
-> {
             log.debug("Visiting vertex " + v);
             if (visitedNodes.contains(v)) {
                 throw new RuntimeException("Double visit of vertex: " + v);
@@ -242,7 +243,7 @@ class TraversalTest {
                 throw new RuntimeException("Error for node " + v);
             }
             return true;
-        }, true);
+        });
 
         assertEquals(vtx0, visitedNodes.get(0));
         assertEquals(vtx1, visitedNodes.get(1));
@@ -270,57 +271,106 @@ class TraversalTest {
     }
 
     @Test
+    void hasCycle() {
+        SimpleGraph graph = new SimpleGraph();
+        SimpleNode vtx0 = graph.newNode("root");
+        SimpleNode vtx1 = graph.newNode("vertex1");
+        SimpleNode vtx11 = graph.newNode("vertex11");
+        SimpleNode vtx12 = graph.newNode("vertex12");
+        SimpleNode vtx2 = graph.newNode("vertex2");
+        SimpleNode vtx21 = graph.newNode("vertex21");
+        SimpleNode vtx211 = graph.newNode("vertex211");
+        SimpleNode vtx212 = graph.newNode("vertex212");
+
+        SimpleNode vtx22 = graph.newNode("vertex22");
+        SimpleNode vtx221 = graph.newNode("vertex221");
+        SimpleNode vtx222 = graph.newNode("vertex222");
+        SimpleNode vtx223 = graph.newNode("vertex223");
+
+        SimpleNode vtx3 = graph.newNode("vertex3");
+        SimpleNode vtx31 = graph.newNode("vertex31");
+        SimpleNode vtx32 = graph.newNode("vertex32");
+        SimpleNode vtx33 = graph.newNode("vertex33");
+
+        graph.newEdge("root->1", vtx0, vtx1);
+        graph.newEdge("root->2", vtx0, vtx2);
+        graph.newEdge("root->3", vtx0, vtx3);
+
+        graph.newEdge("1->11", vtx1, vtx11);
+        graph.newEdge("1->12", vtx1, vtx12);
+
+        graph.newEdge("2->21", vtx2, vtx21);
+        graph.newEdge("2->22", vtx2, vtx22);
+        graph.newEdge("22->2", vtx22, vtx2);
+
+        graph.newEdge("21->211", vtx21, vtx211);
+        graph.newEdge("21->212", vtx21, vtx212);
+
+        graph.newEdge("22->221", vtx22, vtx221);
+        graph.newEdge("22->222", vtx22, vtx222);
+        graph.newEdge("22->223", vtx22, vtx223);
+        graph.newEdge("223->root", vtx223, vtx0);
+
+        graph.newEdge("3->31", vtx3, vtx31);
+        graph.newEdge("3->32", vtx3, vtx32);
+        graph.newEdge("3->33", vtx3, vtx33);
+
+        assertTrue(Traversal.hasCycle(vtx0));
+        assertFalse(Traversal.hasCycle(vtx1));
+    }
+
+    @Test
     void breadthFirstWithoutCyclesAndWithoutError() {
         SimpleGraph graph = new SimpleGraph();
-        SimpleVertex vtx0 = graph.addVertex("root");
-        SimpleVertex vtx1 = graph.addVertex("vertex1");
-        SimpleVertex vtx11 = graph.addVertex("vertex11");
-        SimpleVertex vtx12 = graph.addVertex("vertex12");
-        SimpleVertex vtx2 = graph.addVertex("vertex2");
-        SimpleVertex vtx21 = graph.addVertex("vertex21");
-        SimpleVertex vtx211 = graph.addVertex("vertex211");
-        SimpleVertex vtx212 = graph.addVertex("vertex212");
-
-        SimpleVertex vtx22 = graph.addVertex("vertex22");
-        SimpleVertex vtx221 = graph.addVertex("vertex221");
-        SimpleVertex vtx222 = graph.addVertex("vertex222");
-        SimpleVertex vtx223 = graph.addVertex("vertex223");
-
-        SimpleVertex vtx3 = graph.addVertex("vertex3");
-        SimpleVertex vtx31 = graph.addVertex("vertex31");
-        SimpleVertex vtx32 = graph.addVertex("vertex32");
-        SimpleVertex vtx33 = graph.addVertex("vertex33");
-
-        graph.addEdge("root->1", vtx0, vtx1);
-        graph.addEdge("root->2", vtx0, vtx2);
-        graph.addEdge("root->3", vtx0, vtx3);
-
-        graph.addEdge("1->11", vtx1, vtx11);
-        graph.addEdge("1->12", vtx1, vtx12);
-
-        graph.addEdge("2->21", vtx2, vtx21);
-        graph.addEdge("2->22", vtx2, vtx22);
-
-        graph.addEdge("21->211", vtx21, vtx211);
-        graph.addEdge("21->212", vtx21, vtx212);
-
-        graph.addEdge("22->221", vtx22, vtx221);
-        graph.addEdge("22->222", vtx22, vtx222);
-        graph.addEdge("22->223", vtx22, vtx223);
-
-        graph.addEdge("3->31", vtx3, vtx31);
-        graph.addEdge("3->32", vtx3, vtx32);
-        graph.addEdge("3->33", vtx3, vtx33);
-
-        List<SimpleVertex> visitedNodes = new ArrayList<>();
-        TraversalStatus<SimpleVertex> status = Traversal.breadthFirst(vtx0, v 
-> {
+        SimpleNode vtx0 = graph.newNode("root");
+        SimpleNode vtx1 = graph.newNode("vertex1");
+        SimpleNode vtx11 = graph.newNode("vertex11");
+        SimpleNode vtx12 = graph.newNode("vertex12");
+        SimpleNode vtx2 = graph.newNode("vertex2");
+        SimpleNode vtx21 = graph.newNode("vertex21");
+        SimpleNode vtx211 = graph.newNode("vertex211");
+        SimpleNode vtx212 = graph.newNode("vertex212");
+
+        SimpleNode vtx22 = graph.newNode("vertex22");
+        SimpleNode vtx221 = graph.newNode("vertex221");
+        SimpleNode vtx222 = graph.newNode("vertex222");
+        SimpleNode vtx223 = graph.newNode("vertex223");
+
+        SimpleNode vtx3 = graph.newNode("vertex3");
+        SimpleNode vtx31 = graph.newNode("vertex31");
+        SimpleNode vtx32 = graph.newNode("vertex32");
+        SimpleNode vtx33 = graph.newNode("vertex33");
+
+        graph.newEdge("root->1", vtx0, vtx1);
+        graph.newEdge("root->2", vtx0, vtx2);
+        graph.newEdge("root->3", vtx0, vtx3);
+
+        graph.newEdge("1->11", vtx1, vtx11);
+        graph.newEdge("1->12", vtx1, vtx12);
+
+        graph.newEdge("2->21", vtx2, vtx21);
+        graph.newEdge("2->22", vtx2, vtx22);
+
+        graph.newEdge("21->211", vtx21, vtx211);
+        graph.newEdge("21->212", vtx21, vtx212);
+
+        graph.newEdge("22->221", vtx22, vtx221);
+        graph.newEdge("22->222", vtx22, vtx222);
+        graph.newEdge("22->223", vtx22, vtx223);
+
+        graph.newEdge("3->31", vtx3, vtx31);
+        graph.newEdge("3->32", vtx3, vtx32);
+        graph.newEdge("3->33", vtx3, vtx33);
+
+        List<SimpleNode> visitedNodes = new ArrayList<>();
+        TraversalStatus<SimpleNode> status = Traversal.breadthFirst(vtx0, 
(v,s) -> {
             log.debug("Visiting vertex " + v);
             if (visitedNodes.contains(v)) {
                 throw new RuntimeException("Double visit of vertex: " + v);
             }
             visitedNodes.add(v);
             return true;
-        }, true);
+        });
 
         assertEquals(vtx0, visitedNodes.get(0));
         assertEquals(vtx1, visitedNodes.get(1));
@@ -346,127 +396,128 @@ class TraversalTest {
     @Test
     void breadthFirstWithCyclesAndWithoutError() {
         SimpleGraph graph = new SimpleGraph();
-        SimpleVertex vtx0 = graph.addVertex("root");
-        SimpleVertex vtx1 = graph.addVertex("vertex1");
-        SimpleVertex vtx11 = graph.addVertex("vertex11");
-        SimpleVertex vtx12 = graph.addVertex("vertex12");
-        SimpleVertex vtx2 = graph.addVertex("vertex2");
-        SimpleVertex vtx21 = graph.addVertex("vertex21");
-        SimpleVertex vtx211 = graph.addVertex("vertex211");
-        SimpleVertex vtx212 = graph.addVertex("vertex212");
-
-        SimpleVertex vtx22 = graph.addVertex("vertex22");
-        SimpleVertex vtx221 = graph.addVertex("vertex221");
-        SimpleVertex vtx222 = graph.addVertex("vertex222");
-        SimpleVertex vtx223 = graph.addVertex("vertex223");
-
-        SimpleVertex vtx3 = graph.addVertex("vertex3");
-        SimpleVertex vtx31 = graph.addVertex("vertex31");
-        SimpleVertex vtx32 = graph.addVertex("vertex32");
-        SimpleVertex vtx33 = graph.addVertex("vertex33");
-
-        graph.addEdge("root->1", vtx0, vtx1);
-        graph.addEdge("root->2", vtx0, vtx2);
-        graph.addEdge("root->3", vtx0, vtx3);
-
-        graph.addEdge("1->11", vtx1, vtx11);
-        graph.addEdge("1->12", vtx1, vtx12);
-
-        graph.addEdge("2->21", vtx2, vtx21);
-        graph.addEdge("2->22", vtx2, vtx22);
-
-        graph.addEdge("21->211", vtx21, vtx211);
-        graph.addEdge("21->212", vtx21, vtx212);
-        graph.addEdge("211->21", vtx211, vtx21);
-
-        graph.addEdge("22->221", vtx22, vtx221);
-        graph.addEdge("22->222", vtx22, vtx222);
-        graph.addEdge("22->223", vtx22, vtx223);
-        graph.addEdge("223->root", vtx223, vtx0);
-
-        graph.addEdge("3->31", vtx3, vtx31);
-        graph.addEdge("3->32", vtx3, vtx32);
-        graph.addEdge("3->33", vtx3, vtx33);
-
-        List<SimpleVertex> visitedNodes = new ArrayList<>();
-        TraversalStatus<SimpleVertex> status = Traversal.breadthFirst(vtx0, v 
-> {
+        SimpleNode vtx0 = graph.newNode("root");
+        SimpleNode vtx1 = graph.newNode("vertex1");
+        SimpleNode vtx11 = graph.newNode("vertex11");
+        SimpleNode vtx12 = graph.newNode("vertex12");
+        SimpleNode vtx2 = graph.newNode("vertex2");
+        SimpleNode vtx21 = graph.newNode("vertex21");
+        SimpleNode vtx211 = graph.newNode("vertex211");
+        SimpleNode vtx212 = graph.newNode("vertex212");
+
+        SimpleNode vtx22 = graph.newNode("vertex22");
+        SimpleNode vtx221 = graph.newNode("vertex221");
+        SimpleNode vtx222 = graph.newNode("vertex222");
+        SimpleNode vtx223 = graph.newNode("vertex223");
+
+        SimpleNode vtx3 = graph.newNode("vertex3");
+        SimpleNode vtx31 = graph.newNode("vertex31");
+        SimpleNode vtx32 = graph.newNode("vertex32");
+        SimpleNode vtx33 = graph.newNode("vertex33");
+
+        graph.newEdge("root->1", vtx0, vtx1);
+        graph.newEdge("root->2", vtx0, vtx2);
+        graph.newEdge("root->3", vtx0, vtx3);
+
+        graph.newEdge("1->11", vtx1, vtx11);
+        graph.newEdge("1->12", vtx1, vtx12);
+
+        graph.newEdge("2->21", vtx2, vtx21);
+        graph.newEdge("2->22", vtx2, vtx22);
+
+        graph.newEdge("21->211", vtx21, vtx211);
+        graph.newEdge("21->212", vtx21, vtx212);
+        graph.newEdge("211->21", vtx211, vtx21);
+
+        graph.newEdge("22->221", vtx22, vtx221);
+        graph.newEdge("22->222", vtx22, vtx222);
+        graph.newEdge("22->223", vtx22, vtx223);
+        graph.newEdge("223->root", vtx223, vtx0);
+
+        graph.newEdge("3->31", vtx3, vtx31);
+        graph.newEdge("3->32", vtx3, vtx32);
+        graph.newEdge("3->33", vtx3, vtx33);
+
+        List<SimpleNode> visitedNodes = new ArrayList<>();
+        TraversalStatus<SimpleNode> status = Traversal.breadthFirst(vtx0, (v, 
s) -> {
             log.debug("Visiting vertex " + v);
             if (visitedNodes.contains(v)) {
                 throw new RuntimeException("Double visit of vertex: " + v);
             }
             visitedNodes.add(v);
             return true;
-        }, true);
+        }, new TraversalFlags(false, true));
 
         assertEquals(vtx0, visitedNodes.get(0));
         assertEquals(vtx1, visitedNodes.get(1));
         assertEquals(vtx2, visitedNodes.get(2));
         assertEquals(vtx3, visitedNodes.get(3));
-        assertEquals(vtx11, visitedNodes.get(4));
-        assertEquals(vtx12, visitedNodes.get(5));
-        assertEquals(vtx21, visitedNodes.get(6));
-        assertEquals(vtx22, visitedNodes.get(7));
-        assertEquals(vtx31, visitedNodes.get(8));
-        assertEquals(vtx32, visitedNodes.get(9));
-        assertEquals(vtx33, visitedNodes.get(10));
-        assertEquals(vtx211, visitedNodes.get(11));
-        assertEquals(vtx212, visitedNodes.get(12));
-        assertEquals(vtx221, visitedNodes.get(13));
-        assertEquals(vtx222, visitedNodes.get(14));
-        assertEquals(vtx223, visitedNodes.get(15));
+        assertEquals(vtx223, visitedNodes.get(4));
+        assertEquals(vtx11, visitedNodes.get(5));
+        assertEquals(vtx12, visitedNodes.get(6));
+        assertEquals(vtx21, visitedNodes.get(7));
+        assertEquals(vtx22, visitedNodes.get(8));
+        assertEquals(vtx31, visitedNodes.get(9));
+        assertEquals(vtx32, visitedNodes.get(10));
+        assertEquals(vtx33, visitedNodes.get(11));
+        assertEquals(vtx211, visitedNodes.get(12));
+        assertEquals(vtx212, visitedNodes.get(13));
+        assertEquals(vtx221, visitedNodes.get(14));
+        assertEquals(vtx222, visitedNodes.get(15));
+
 
         assertTrue(status.hasCycles());
-        assertEquals(2, status.getCycleCount());
+        assertEquals(19, status.getCycleCount());
         assertFalse(status.hasErrors());
     }
 
     @Test
     void breadthFirstWithCyclesAndWithError() {
         SimpleGraph graph = new SimpleGraph();
-        SimpleVertex vtx0 = graph.addVertex("root");
-        SimpleVertex vtx1 = graph.addVertex("vertex1");
-        SimpleVertex vtx11 = graph.addVertex("vertex11");
-        SimpleVertex vtx12 = graph.addVertex("vertex12");
-        SimpleVertex vtx2 = graph.addVertex("vertex2");
-        SimpleVertex vtx21 = graph.addVertex("vertex21");
-        SimpleVertex vtx211 = graph.addVertex("vertex211");
-        SimpleVertex vtx212 = graph.addVertex("vertex212");
-
-        SimpleVertex vtx22 = graph.addVertex("vertex22");
-        SimpleVertex vtx221 = graph.addVertex("vertex221");
-        SimpleVertex vtx222 = graph.addVertex("vertex222");
-        SimpleVertex vtx223 = graph.addVertex("vertex223");
-
-        SimpleVertex vtx3 = graph.addVertex("vertex3");
-        SimpleVertex vtx31 = graph.addVertex("vertex31");
-        SimpleVertex vtx32 = graph.addVertex("vertex32");
-        SimpleVertex vtx33 = graph.addVertex("vertex33");
-
-        graph.addEdge("root->1", vtx0, vtx1);
-        graph.addEdge("root->2", vtx0, vtx2);
-        graph.addEdge("root->3", vtx0, vtx3);
-
-        graph.addEdge("1->11", vtx1, vtx11);
-        graph.addEdge("1->12", vtx1, vtx12);
-
-        graph.addEdge("2->21", vtx2, vtx21);
-        graph.addEdge("2->22", vtx2, vtx22);
-
-        graph.addEdge("21->211", vtx21, vtx211);
-        graph.addEdge("21->212", vtx21, vtx212);
-        graph.addEdge("211->21", vtx211, vtx21);
-
-        graph.addEdge("22->221", vtx22, vtx221);
-        graph.addEdge("22->222", vtx22, vtx222);
-        graph.addEdge("22->223", vtx22, vtx223);
-        graph.addEdge("223->root", vtx223, vtx0);
-
-        graph.addEdge("3->31", vtx3, vtx31);
-        graph.addEdge("3->32", vtx3, vtx32);
-        graph.addEdge("3->33", vtx3, vtx33);
-
-        List<SimpleVertex> visitedNodes = new ArrayList<>();
-        TraversalStatus<SimpleVertex> status = Traversal.breadthFirst(vtx0, v 
-> {
+        SimpleNode vtx0 = graph.newNode("root");
+        SimpleNode vtx1 = graph.newNode("vertex1");
+        SimpleNode vtx11 = graph.newNode("vertex11");
+        SimpleNode vtx12 = graph.newNode("vertex12");
+        SimpleNode vtx2 = graph.newNode("vertex2");
+        SimpleNode vtx21 = graph.newNode("vertex21");
+        SimpleNode vtx211 = graph.newNode("vertex211");
+        SimpleNode vtx212 = graph.newNode("vertex212");
+
+        SimpleNode vtx22 = graph.newNode("vertex22");
+        SimpleNode vtx221 = graph.newNode("vertex221");
+        SimpleNode vtx222 = graph.newNode("vertex222");
+        SimpleNode vtx223 = graph.newNode("vertex223");
+
+        SimpleNode vtx3 = graph.newNode("vertex3");
+        SimpleNode vtx31 = graph.newNode("vertex31");
+        SimpleNode vtx32 = graph.newNode("vertex32");
+        SimpleNode vtx33 = graph.newNode("vertex33");
+
+        graph.newEdge("root->1", vtx0, vtx1);
+        graph.newEdge("root->2", vtx0, vtx2);
+        graph.newEdge("root->3", vtx0, vtx3);
+
+        graph.newEdge("1->11", vtx1, vtx11);
+        graph.newEdge("1->12", vtx1, vtx12);
+
+        graph.newEdge("2->21", vtx2, vtx21);
+        graph.newEdge("2->22", vtx2, vtx22);
+
+        graph.newEdge("21->211", vtx21, vtx211);
+        graph.newEdge("21->212", vtx21, vtx212);
+        graph.newEdge("211->21", vtx211, vtx21);
+
+        graph.newEdge("22->221", vtx22, vtx221);
+        graph.newEdge("22->222", vtx22, vtx222);
+        graph.newEdge("22->223", vtx22, vtx223);
+        graph.newEdge("223->root", vtx223, vtx0);
+
+        graph.newEdge("3->31", vtx3, vtx31);
+        graph.newEdge("3->32", vtx3, vtx32);
+        graph.newEdge("3->33", vtx3, vtx33);
+
+        List<SimpleNode> visitedNodes = new ArrayList<>();
+        TraversalStatus<SimpleNode> status = Traversal.breadthFirst(vtx0, (v, 
s) -> {
             log.debug("Visiting vertex " + v);
             if (visitedNodes.contains(v)) {
                 throw new RuntimeException("Double visit of vertex: " + v);
@@ -476,30 +527,110 @@ class TraversalTest {
                 throw new RuntimeException("Error on node: " + v);
             }
             return true;
-        }, true);
+        }, new TraversalFlags(false, true));
 
         assertEquals(vtx0, visitedNodes.get(0));
         assertEquals(vtx1, visitedNodes.get(1));
         assertEquals(vtx2, visitedNodes.get(2));
         assertEquals(vtx3, visitedNodes.get(3));
-        assertEquals(vtx11, visitedNodes.get(4));
-        assertEquals(vtx12, visitedNodes.get(5));
-        assertEquals(vtx21, visitedNodes.get(6));
-        assertEquals(vtx22, visitedNodes.get(7));
-        assertEquals(vtx31, visitedNodes.get(8));
-        assertEquals(vtx32, visitedNodes.get(9));
-        assertEquals(vtx33, visitedNodes.get(10));
-        assertEquals(vtx211, visitedNodes.get(11));
-        assertEquals(vtx212, visitedNodes.get(12));
-        assertEquals(vtx221, visitedNodes.get(13));
-        assertEquals(vtx222, visitedNodes.get(14));
-        assertEquals(vtx223, visitedNodes.get(15));
+        assertEquals(vtx223, visitedNodes.get(4));
+        assertEquals(vtx11, visitedNodes.get(5));
+        assertEquals(vtx12, visitedNodes.get(6));
+        assertEquals(vtx21, visitedNodes.get(7));
+        assertEquals(vtx22, visitedNodes.get(8));
+        assertEquals(vtx31, visitedNodes.get(9));
+        assertEquals(vtx32, visitedNodes.get(10));
+        assertEquals(vtx33, visitedNodes.get(11));
+        assertEquals(vtx211, visitedNodes.get(12));
+        assertEquals(vtx212, visitedNodes.get(13));
+        assertEquals(vtx221, visitedNodes.get(14));
+        assertEquals(vtx222, visitedNodes.get(15));
 
         assertTrue(status.hasCycles());
-        assertEquals(2, status.getCycleCount());
+        // Undirected graph
+        assertEquals(19, status.getCycleCount());
         assertTrue(status.hasErrors());
         assertEquals(3, status.getErrorList().size());
         
assertTrue(status.getErrorList().get(0).getException().getMessage().startsWith("Error
 on node"));
     }
 
+
+    @Test
+    void topologicalSort() {
+        SimpleGraph graph = new SimpleGraph();
+        SimpleNode vtx0 = graph.newNode("root");
+        SimpleNode vtx1 = graph.newNode("vertex1");
+        SimpleNode vtx11 = graph.newNode("vertex11");
+        SimpleNode vtx12 = graph.newNode("vertex12");
+        SimpleNode vtx2 = graph.newNode("vertex2");
+        SimpleNode vtx21 = graph.newNode("vertex21");
+        SimpleNode vtx211 = graph.newNode("vertex211");
+        SimpleNode vtx212 = graph.newNode("vertex212");
+
+        SimpleNode vtx22 = graph.newNode("vertex22");
+        SimpleNode vtx221 = graph.newNode("vertex221");
+        SimpleNode vtx222 = graph.newNode("vertex222");
+        SimpleNode vtx223 = graph.newNode("vertex223");
+
+        SimpleNode vtx3 = graph.newNode("vertex3");
+        SimpleNode vtx31 = graph.newNode("vertex31");
+        SimpleNode vtx32 = graph.newNode("vertex32");
+        SimpleNode vtx33 = graph.newNode("vertex33");
+        SimpleNode vtx331 = graph.newNode("vertex331");
+        SimpleNode vtx3311 = graph.newNode("vertex3311");
+
+
+        graph.newEdge("root->1", vtx0, vtx1);
+        graph.newEdge("root->2", vtx0, vtx2);
+        graph.newEdge("root->3", vtx0, vtx3);
+
+        graph.newEdge("1->11", vtx1, vtx11);
+        graph.newEdge("1->12", vtx1, vtx12);
+
+        graph.newEdge("2->21", vtx2, vtx21);
+        graph.newEdge("2->22", vtx2, vtx22);
+        graph.newEdge("22->2", vtx22, vtx2);
+
+        graph.newEdge("21->211", vtx21, vtx211);
+        graph.newEdge("21->212", vtx21, vtx212);
+
+        graph.newEdge("22->221", vtx22, vtx221);
+        graph.newEdge("22->222", vtx22, vtx222);
+        graph.newEdge("22->223", vtx22, vtx223);
+        graph.newEdge("223->root", vtx223, vtx0);
+
+        graph.newEdge("3->31", vtx3, vtx31);
+        graph.newEdge("3->32", vtx3, vtx32);
+        graph.newEdge("3->33", vtx3, vtx33);
+        graph.newEdge("33->331", vtx33, vtx331);
+        graph.newEdge("331->3311", vtx331, vtx3311);
+        graph.newEdge("22->33", vtx22, vtx33);
+        // graph.newEdge("33->22", vtx33, vtx22);
+
+
+        List<SimpleNode> result = Traversal.topologialSort(vtx0);
+
+        assertEquals(vtx11, result.get(0));
+        assertEquals(vtx12, result.get(1));
+        assertEquals(vtx1, result.get(2));
+        assertEquals(vtx211, result.get(3));
+        assertEquals(vtx212, result.get(4));
+        assertEquals(vtx21, result.get(5));
+        assertEquals(vtx221, result.get(6));
+        assertEquals(vtx222, result.get(7));
+        assertEquals(vtx223, result.get(8));
+        assertEquals(vtx3311, result.get(9));
+        assertEquals(vtx331, result.get(10));
+        assertEquals(vtx33, result.get(11));
+        assertEquals(vtx22, result.get(12));
+        assertEquals(vtx2, result.get(13));
+        assertEquals(vtx31, result.get(14));
+        assertEquals(vtx32, result.get(15));
+        assertEquals(vtx3, result.get(16));
+        assertEquals(vtx0, result.get(17));
+
+
+    }
+
+
 }
\ No newline at end of file

Reply via email to