2 * Copyright 2008 the original author or authors.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.wamblee.system.graph;
18 import java.util.ArrayList;
19 import java.util.Iterator;
20 import java.util.List;
24 * Represents a graph consisting of nodes and edges.
26 * @author Erik Brakkee
32 private List<Node> nodes;
37 private List<Edge> edges;
40 * Constructs the graph.
43 nodes = new ArrayList<Node>();
44 edges = new ArrayList<Edge>();
50 * @param aNode Node to add.
52 * @throws IllegalArgumentException In case the node already exists. Node
53 * equality is checked using <code>equals</code>.
55 public void addNode(Node aNode) {
56 if (nodes.contains(aNode)) {
57 throw new IllegalArgumentException("Node '" + aNode.getName()
58 + "' already exists");
65 * Finds a node with the given name.
67 * @param aName Node name.
69 * @return Node or null if not found.
71 public Node findNode(String aName) {
72 for (Node node : nodes) {
73 if (node.getName().equals(aName)) {
84 * @param aNode Node to remove.
86 * @return True iff the node was removed.
88 * @throws IllegalArgumentException In case there are edges of which the
91 public boolean removeNode(Node aNode) {
92 if (!findOutgoing(aNode).isEmpty() || !findIncoming(aNode).isEmpty()) {
93 throw new IllegalArgumentException("Cannot remove node '"
95 + "' because it is connected to one or more edges");
98 return nodes.remove(aNode);
102 * Adds a list of nodes.
104 * @param aNodes Nodes to add.
106 * @see #addNode(Node)
108 public void addNodes(List<Node> aNodes) {
109 for (Node node : aNodes) {
117 * @param aEdge Edge to add.
119 * @throws IllegalArgumentException In case one of the nodes of the edges
120 * is not part of the graph or if the same edge (as determined by
121 * {@link #equals(Object)} is already a part of the graph.
123 public void addEdge(Edge aEdge) {
124 if (edges.contains(aEdge)) {
125 throw new IllegalArgumentException("Edge '" + aEdge
126 + "' already exists");
129 if (!nodes.contains(aEdge.getFrom())) {
130 throw new IllegalArgumentException("From node '" + aEdge.getFrom()
131 + "' from edge '" + aEdge + "' is not part of the graph");
134 if (!nodes.contains(aEdge.getTo())) {
135 throw new IllegalArgumentException("To node '" + aEdge.getTo()
136 + "' from edge '" + aEdge + "' is not part of the graph");
145 * @param aEdge Edge to remove.
147 * @return True if the edge was removed.
149 public boolean removeEdge(Edge aEdge) {
150 return edges.remove(aEdge);
154 * Adds a number of edges.
156 * @param aEdges Edges to add.
158 public void addEdges(List<Edge> aEdges) {
159 for (Edge edge : aEdges) {
167 * @return Copy of the list of nodes of the graph.
169 public List<Node> getNodes() {
170 return new ArrayList<Node>(nodes);
176 * @return Copy of the list of edges of the graph.
178 public List<Edge> getEdges() {
179 return new ArrayList<Edge>(edges);
183 * Extends the graph with edges using an edge factory. All
184 * combinations of nodes are passed to the factory which creates
187 * @param aFactory Edge factory.
189 public void extend(EdgeFactory aFactory) {
190 for (Node from : nodes) {
191 for (Node to : nodes) {
192 edges.addAll(aFactory.create(from, to));
198 * Applies a filter to the graph for removing elements.
200 * @param aFilter Filter to apply.
202 public void applyFilter(EdgeFilter aFilter) {
203 for (Iterator<Edge> edge = edges.iterator(); edge.hasNext();) {
204 if (aFilter.isViolated(edge.next())) {
211 * Finds all outgoing edges of a node. More specifically, finds
212 * all edges <code>e</code> for which <code>e.getFrom().getName() =
213 * aNode.getName()</code>.
215 * @param aNode Node for which to find outgoing edges.
217 * @return List of outgoing edges.
219 public List<Edge> findOutgoing(Node aNode) {
220 List<Edge> result = new ArrayList<Edge>();
222 for (Edge edge : edges) {
223 if (edge.getFrom().getName().equals(aNode.getName())) {
232 * Finds all incoming edges of a node. More specifically, finds
233 * all edges <code>e</code> for which <code>e.getTo().getName() =
234 * aNode.getName()</code>.
236 * @param aNode Node for which to find incoming edges.
238 * @return List of incoming edges.
240 public List<Edge> findIncoming(Node aNode) {
241 List<Edge> result = new ArrayList<Edge>();
243 for (Edge edge : edges) {
244 if (edge.getTo().getName().equals(aNode.getName())) {
253 * Implements a visitor design pattern. This loops over all nodes
254 * and all edges and invokes the appropriate visit methods on the visitor.
256 * @param aVisitor Visitor.
258 public void accept(Visitor aVisitor) {
259 List<Node> nodes = getNodes(); // copy to make sure the visitor can
261 // list of nodes as part of the loop.
263 List<Edge> edges = getEdges(); // copy ..... (see above).
265 for (Node node : nodes) {
266 aVisitor.visitNode(node);
269 for (Edge edge : edges) {
270 aVisitor.visitEdge(edge);