T
- The content type for the graphpublic final class DependencyGraph<T>
extends java.lang.Object
implements java.util.Collection<T>
This class implements a dependency graph using a strongly connected Directed Acyclic Graph (DAG) that provides sorting of its nodes in topological order.
Some important characteristics of this class are:
toOrderedList()
will not destroy the graph:
the same graph instance can be safely reused after a topological sort operation.findCycles()
).Constructor and Description |
---|
DependencyGraph()
Construct a non-thread-safe graph
|
DependencyGraph(boolean threadSafe)
Constructor
|
DependencyGraph(int initialCapacity)
Construct a non-thread-safe graph
|
DependencyGraph(int initialCapacity,
boolean threadSafe)
Constructor
|
Modifier and Type | Method and Description |
---|---|
boolean |
add(T content)
Add content to the graph as a new node only if the given content does not
exist in the graph already.
|
boolean |
addAll(java.util.Collection<? extends T> content) |
void |
addDependencies(T dependent,
java.util.Collection<T> dependencies)
Adds 1 or more dependencies to the given dependent node.
|
void |
addDependencies(T dependent,
T... dependencies)
See method
#addDependencies(T dependent, Collection |
void |
clear() |
boolean |
contains(java.lang.Object content)
Check if a given content exists in the graph
|
boolean |
containsAll(java.util.Collection c) |
java.util.Collection<java.util.Collection<T>> |
findCycles()
Identifies all cycles (circular dependency paths) in the graph, if any.
|
java.util.Collection<T> |
getDependentFreeNodes()
Identifies all the nodes that no other nodes depend on
|
java.util.Collection<T> |
getDirectDependencies(T content)
Retrieves the contents of all nodes that the given content directly depends on.
|
java.util.Collection<T> |
getDirectDependents(T content)
Retrieves the contents of all nodes that the given content is a direct
dependency of.
|
java.util.Collection<T> |
getIndependentNodes()
Identifies all the nodes that do not depend on any other node
|
boolean |
isEmpty() |
java.util.Iterator<T> |
iterator() |
boolean |
remove(java.lang.Object object)
Will remove the node containing the given content, if it exists in the graph.
|
boolean |
removeAll(java.util.Collection content) |
void |
removeDependencies(T dependent,
T... dependencies)
Removes 1 or more dependencies from the given dependent node.
|
boolean |
retainAll(java.util.Collection content) |
int |
size() |
java.lang.Object[] |
toArray() |
<E> E[] |
toArray(E[] array) |
java.util.List<T> |
toOrderedList()
This method will perform a topological sorting of its content, based
on the algorithm described by Arthur B.
|
java.lang.String |
toString()
Returns a string representation of this collection.
|
public DependencyGraph(boolean threadSafe)
threadSafe
- whether the graph must be thread-safe or not.
Thread-safety will impact performance in some degree.public DependencyGraph()
public DependencyGraph(int initialCapacity, boolean threadSafe)
initialCapacity
- sets the initial capacity for some internal
data structures.threadSafe
- whether the graph must be thread-safe or not.
Thread-safety will impact performance in some degree.public DependencyGraph(int initialCapacity)
initialCapacity
- sets the initial capacity for some internal
data structures.public int size()
size
in interface java.util.Collection<T>
public java.util.Collection<T> getDependentFreeNodes()
public java.util.Collection<T> getIndependentNodes()
public boolean add(T content)
add
in interface java.util.Collection<T>
content
- non-null content to be added to the graphpublic void addDependencies(T dependent, java.util.Collection<T> dependencies)
Adds 1 or more dependencies to the given dependent node.
If the dependent content or any of the given dependencies don't exist as nodes in the graph, new nodes will automatically be created and added first.
Because this is a strongly connected digraph, each new dependency will represent 2 new edges (or connections) between 2 nodes (dependent and dependency). For example, if A depends on B then B will have an outgoing connection to A as well as A will have an incoming connection from B.
dependent
- The node that depends on each node provided in the
dependencies collectiondependencies
- All nodes that dependent depends onpublic void addDependencies(T dependent, T... dependencies)
See method #addDependencies(T dependent, Collection
dependent
- The node that depends on each node provided in the
dependencies arraydependencies
- Optional list of nodes that dependent depends onpublic void removeDependencies(T dependent, T... dependencies)
Removes 1 or more dependencies from the given dependent node.
Including nodes in the dependencies array that are not connected to the dependent node won't have any effect.
See method #addDependencies(T dependent, Collection
for more details on some dependency
internals.
dependent
- The node that depends on each node provided in the
dependencies arraydependencies
- All nodes that should be removed as dependencies of
the dependent nodepublic boolean remove(java.lang.Object object)
Will remove the node containing the given content, if it exists in the graph. As a result, all edges directly connecting this node to other nodes will also be removed.
remove
in interface java.util.Collection<T>
object
- The content to be removed from the graphpublic boolean contains(java.lang.Object content)
Check if a given content exists in the graph
contains
in interface java.util.Collection<T>
content
- Content to be verifiedpublic java.util.Collection<T> getDirectDependencies(T content)
content
- The node to retrieve all direct dependencies frompublic java.util.Collection<T> getDirectDependents(T content)
content
- The node to retrieve all direct dependents frompublic java.util.List<T> toOrderedList()
This method will perform a topological sorting of its content, based on the algorithm described by Arthur B. Kahn[1962] in article "Topological sorting of large networks", Communications of the ACM 5 (11): 558562
During the sorting, if a directed cycle (or a circular reference) is detected, an IllegalStateException will be thrown.
In order to be non-destructive and keep the graph reusable after this operation, this method will take snapshots of all required internal data structures and use them to perform the sorting.
When running in thread-safe mode, this method will hold a read lock during the entire sort operation in order to avoid unpredicted results if the graph's contents were to be modified during the sorting.
public java.util.Collection<java.util.Collection<T>> findCycles()
public boolean addAll(java.util.Collection<? extends T> content)
addAll
in interface java.util.Collection<T>
public void clear()
clear
in interface java.util.Collection<T>
public boolean containsAll(java.util.Collection c)
containsAll
in interface java.util.Collection<T>
public boolean isEmpty()
isEmpty
in interface java.util.Collection<T>
public java.util.Iterator<T> iterator()
public boolean removeAll(java.util.Collection content)
removeAll
in interface java.util.Collection<T>
public boolean retainAll(java.util.Collection content)
retainAll
in interface java.util.Collection<T>
public java.lang.Object[] toArray()
toArray
in interface java.util.Collection<T>
public <E> E[] toArray(E[] array)
toArray
in interface java.util.Collection<T>
public java.lang.String toString()
String.valueOf(Object)
.toString
in class java.lang.Object