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;
23 * Represents a graph consisting of nodes and edges.
25 * @author Erik Brakkee
29 private List<Node> _nodes;
30 private List<Edge> _edges;
33 * Constructs the graph.
36 _nodes = new ArrayList<Node>();
37 _edges = new ArrayList<Edge>();
45 * @throws IllegalArgumentException
46 * In case the node already exists. Node equality is checked
47 * using <code>equals</code>.
49 public void addNode(Node aNode) {
50 if (_nodes.contains(aNode)) {
51 throw new IllegalArgumentException("Node '" + aNode.getName()
52 + "' already exists");
58 * Finds a node with the given name.
62 * @return Node or null if not found.
64 public Node findNode(String aName) {
65 for (Node node : _nodes) {
66 if (node.getName().equals(aName)) {
78 * @return True iff the node was removed.
79 * @throws IllegalArgumentException
80 * In case there are edges of which the node is a part.
82 public boolean removeNode(Node aNode) {
83 if (!findOutgoing(aNode).isEmpty() || !findIncoming(aNode).isEmpty()) {
84 throw new IllegalArgumentException("Cannot remove node '"
86 + "' because it is connected to one or more edges");
88 return _nodes.remove(aNode);
92 * Adds a list of nodes.
99 public void addNodes(List<Node> aNodes) {
100 for (Node node : aNodes) {
110 * @throws IllegalArgumentException
111 * In case one of the nodes of the edges is not part of the
112 * graph or if the same edge (as determined by
113 * {@link #equals(Object)} is already a part of the graph.
115 public void addEdge(Edge aEdge) {
116 if (_edges.contains(aEdge)) {
117 throw new IllegalArgumentException("Edge '" + aEdge
118 + "' already exists");
120 if (!_nodes.contains(aEdge.getFrom())) {
121 throw new IllegalArgumentException("From node '" + aEdge.getFrom()
122 + "' from edge '" + aEdge + "' is not part of the graph");
124 if (!_nodes.contains(aEdge.getTo())) {
125 throw new IllegalArgumentException("To node '" + aEdge.getTo()
126 + "' from edge '" + aEdge + "' is not part of the graph");
133 * @param aEdge Edge to remove.
134 * @return True if the edge was removed.
136 public boolean removeEdge(Edge aEdge) {
137 return _edges.remove(aEdge);
141 * Adds a number of edges.
142 * @param aEdges Edges to add.
144 public void addEdges(List<Edge> aEdges) {
145 for (Edge edge : aEdges) {
152 * @return Copy of the list of nodes of the graph.
154 public List<Node> getNodes() {
155 return new ArrayList<Node>(_nodes);
160 * @return Copy of the list of edges of the graph.
162 public List<Edge> getEdges() {
163 return new ArrayList<Edge>(_edges);
167 * Extends the graph with edges using an edge factory. All combinations of
168 * nodes are passed to the factory which creates additional edges.
169 * @param aFactory Edge factory.
171 public void extend(EdgeFactory aFactory) {
172 for (Node from : _nodes) {
173 for (Node to : _nodes) {
174 _edges.addAll(aFactory.create(from, to));
180 * Applies a filter to the graph for removing elements.
181 * @param aFilter Filter to apply.
183 public void applyFilter(EdgeFilter aFilter) {
184 for (Iterator<Edge> edge = _edges.iterator(); edge.hasNext(); ) {
185 if (aFilter.isViolated(edge.next())) {
192 * Finds all outgoing edges of a node. More specifically, finds
193 * all edges <code>e</code> for which <code>e.getFrom().getName() = aNode.getName()</code>.
194 * @param aNode Node for which to find outgoing edges.
195 * @return List of outgoing edges.
197 public List<Edge> findOutgoing(Node aNode) {
198 List<Edge> result = new ArrayList<Edge>();
199 for (Edge edge : _edges) {
200 if (edge.getFrom().getName().equals(aNode.getName())) {
208 * Finds all incoming edges of a node.
209 * More specifically, finds
210 * all edges <code>e</code> for which <code>e.getTo().getName() = aNode.getName()</code>.
211 * @param aNode Node for which to find incoming edges.
212 * @return List of incoming edges.
214 public List<Edge> findIncoming(Node aNode) {
215 List<Edge> result = new ArrayList<Edge>();
216 for (Edge edge : _edges) {
217 if (edge.getTo().getName().equals(aNode.getName())) {
225 * Implements a visitor design pattern.
226 * This loops over all nodes and all edges and invokes the appropriate visit
227 * methods on the visitor.
228 * @param aVisitor Visitor.
230 public void accept(Visitor aVisitor) {
231 List<Node> nodes = getNodes(); // copy to make sure the visitor can
233 // list of nodes as part of the loop.
234 List<Edge> edges = getEdges(); // copy ..... (see above).
236 for (Node node : nodes) {
237 aVisitor.visitNode(node);
239 for (Edge edge : edges) {
240 aVisitor.visitEdge(edge);