View Javadoc
1   /*
2    * Created on Apr 2, 2006
3    *
4    * Copyright (c) 2006, The JUNG Authors 
5    *
6    * All rights reserved.
7    *
8    * This software is open-source under the BSD license; see either
9    * "license.txt" or
10   * https://github.com/jrtom/jung/blob/master/LICENSE for a description.
11   */
12  package edu.uci.ics.jung.graph;
13  
14  import java.io.Serializable;
15  import java.util.ArrayList;
16  import java.util.Collection;
17  import java.util.Collections;
18  
19  import edu.uci.ics.jung.graph.util.EdgeType;
20  import edu.uci.ics.jung.graph.util.Pair;
21  
22  /**
23   * Abstract implementation of the <code>Graph</code> interface.  
24   * Designed to simplify implementation of new graph classes.
25   * 
26   * @author Joshua O'Madadhain
27   */
28  @SuppressWarnings("serial")
29  public abstract class AbstractGraph<V, E> implements Graph<V,E>, Serializable 
30  {
31  	public boolean addEdge(E edge, Collection<? extends V> vertices) 
32  	{
33  		return addEdge(edge, vertices, this.getDefaultEdgeType());
34  	}
35  
36  	@SuppressWarnings("unchecked")
37  	public boolean addEdge(E edge, Collection<? extends V> vertices, EdgeType edgeType) {
38  	    if (vertices == null)
39  	        throw new IllegalArgumentException("'vertices' parameter must not be null");
40  	    if (vertices.size() == 2)
41  	        return addEdge(edge, 
42  	        			   vertices instanceof Pair ? (Pair<V>)vertices : new Pair<V>(vertices), 
43  	        			   edgeType);
44          else if (vertices.size() == 1)
45          {
46              V vertex = vertices.iterator().next();
47              return addEdge(edge, new Pair<V>(vertex, vertex), edgeType);
48          }
49          else
50              throw new IllegalArgumentException("Graph objects connect 1 or 2 vertices; vertices arg has " + vertices.size());
51  	}
52  	
53  	public boolean addEdge(E e, V v1, V v2)
54  	{
55  		return addEdge(e, v1, v2, this.getDefaultEdgeType());
56  	}
57  
58  	public boolean addEdge(E e, V v1, V v2, EdgeType edge_type)
59  	{
60  		return addEdge(e, new Pair<V>(v1, v2), edge_type);
61  	}
62  	
63  	/**
64  	 * Adds {@code edge} to this graph with the specified {@code endpoints},
65  	 * with the default edge type.
66  	 * 
67  	 * @param edge the edge to be added
68  	 * @param endpoints the endpoints to be connected to this edge
69  	 * @return {@code true} iff the graph was modified as a result of this call
70  	 */
71  	public boolean addEdge(E edge, Pair<? extends V> endpoints)
72  	{
73  		return addEdge(edge, endpoints, this.getDefaultEdgeType());
74  	}
75  	
76      /**
77       * Adds {@code edge} to this graph with the specified {@code endpoints}
78       * and {@code EdgeType}.
79       * 
80  	 * @param edge the edge to be added
81  	 * @param endpoints the endpoints to be connected to this edge
82  	 * @param edgeType the type of edge to add
83       * @return {@code} true iff the graph was modified as a result of this call
84       */
85  	public abstract boolean addEdge(E edge, Pair<? extends V> endpoints, EdgeType edgeType);
86  
87      protected Pair<V> getValidatedEndpoints(E edge, Pair<? extends V> endpoints)
88      {
89          if (edge == null)
90              throw new IllegalArgumentException("input edge may not be null");
91          
92          if (endpoints == null)
93              throw new IllegalArgumentException("endpoints may not be null");
94          
95          Pair<V> new_endpoints = new Pair<V>(endpoints.getFirst(), endpoints.getSecond());
96          if (containsEdge(edge))
97          {
98              Pair<V> existing_endpoints = getEndpoints(edge);
99              if (!existing_endpoints.equals(new_endpoints)) {
100                 throw new IllegalArgumentException("edge " + edge + 
101                         " already exists in this graph with endpoints " + existing_endpoints + 
102                         " and cannot be added with endpoints " + endpoints);
103             } else {
104                 return null;
105             }
106         }
107         return new_endpoints;
108     }
109     
110     public int inDegree(V vertex)
111     {
112         return this.getInEdges(vertex).size();
113     }
114 
115     public int outDegree(V vertex)
116     {
117         return this.getOutEdges(vertex).size();
118     }
119 
120     public boolean isPredecessor(V v1, V v2)
121     {
122         return this.getPredecessors(v1).contains(v2);
123     }
124 
125     public boolean isSuccessor(V v1, V v2)
126     {
127         return this.getSuccessors(v1).contains(v2);
128     }
129 
130     public int getPredecessorCount(V vertex)
131     {
132         return this.getPredecessors(vertex).size();
133     }
134 
135     public int getSuccessorCount(V vertex)
136     {
137         return this.getSuccessors(vertex).size();
138     }
139 
140     public boolean isNeighbor(V v1, V v2)
141     {
142         if (!containsVertex(v1) || !containsVertex(v2))
143             throw new IllegalArgumentException("At least one of these not in this graph: " + v1 + ", " + v2);
144         return this.getNeighbors(v1).contains(v2);
145     }
146 
147     public boolean isIncident(V vertex, E edge)
148     {
149         if (!containsVertex(vertex) || !containsEdge(edge))
150             throw new IllegalArgumentException("At least one of these not in this graph: " + vertex + ", " + edge);
151         return this.getIncidentEdges(vertex).contains(edge);
152     }
153 
154     public int getNeighborCount(V vertex)
155     {
156         if (!containsVertex(vertex))
157             throw new IllegalArgumentException(vertex + " is not a vertex in this graph");
158         return this.getNeighbors(vertex).size();
159     }
160 
161     public int degree(V vertex)
162     {
163         if (!containsVertex(vertex))
164             throw new IllegalArgumentException(vertex + " is not a vertex in this graph");
165         return this.getIncidentEdges(vertex).size();
166     }
167 
168     public int getIncidentCount(E edge)
169     {
170         Pair<V> incident = this.getEndpoints(edge);
171         if (incident == null)
172             return 0;
173         if (incident.getFirst() == incident.getSecond())
174             return 1;
175         else
176             return 2;
177     }
178     
179     public V getOpposite(V vertex, E edge)
180     {
181         Pair<V> incident = this.getEndpoints(edge); 
182         V first = incident.getFirst();
183         V second = incident.getSecond();
184         if (vertex.equals(first))
185             return second;
186         else if (vertex.equals(second))
187             return first;
188         else 
189             throw new IllegalArgumentException(vertex + " is not incident to " + edge + " in this graph");
190     }
191 
192     public E findEdge(V v1, V v2)
193     {
194         for (E e : getOutEdges(v1))
195         {
196             if (getOpposite(v1, e).equals(v2))
197                 return e;
198         }
199         return null;
200     }
201     
202     public Collection<E> findEdgeSet(V v1, V v2)
203     {
204         if (!getVertices().contains(v1))
205             throw new IllegalArgumentException(v1 + " is not an element of this graph");
206         
207         if (!getVertices().contains(v2))
208             throw new IllegalArgumentException(v2 + " is not an element of this graph");
209         
210         Collection<E> edges = new ArrayList<E>();
211         for (E e : getOutEdges(v1))
212         {
213             if (getOpposite(v1, e).equals(v2))
214                 edges.add(e);
215         }
216         return Collections.unmodifiableCollection(edges);
217     }
218     
219     public Collection<V> getIncidentVertices(E edge)
220     {
221         Pair<V> endpoints = this.getEndpoints(edge);
222         Collection<V> incident = new ArrayList<V>();
223         incident.add(endpoints.getFirst());
224         incident.add(endpoints.getSecond());
225         
226         return Collections.unmodifiableCollection(incident);
227     }
228     
229     @Override
230     public String toString() {
231     	StringBuffer sb = new StringBuffer("Vertices:");
232     	for(V v : getVertices()) {
233     		sb.append(v+",");
234     	}
235     	sb.setLength(sb.length()-1);
236     	sb.append("\nEdges:");
237     	for(E e : getEdges()) {
238     		Pair<V> ep = getEndpoints(e);
239     		sb.append(e+"["+ep.getFirst()+","+ep.getSecond()+"] ");
240     	}
241         return sb.toString();
242     }
243 
244 }