View Javadoc
1   /*
2    * Created on Sep 24, 2005
3    *
4    * Copyright (c) 2005, 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.util;
13  
14  import static com.google.common.base.Preconditions.checkNotNull;
15  
16  import java.util.Collection;
17  import java.util.HashMap;
18  import java.util.HashSet;
19  import java.util.Iterator;
20  import java.util.Map;
21  
22  import edu.uci.ics.jung.graph.Graph;
23  
24  /**
25   * A class which creates and maintains indices for parallel edges.
26   * Parallel edges are defined here to be the collection of edges 
27   * that are returned by <code>v.findEdgeSet(w)</code> for some 
28   * <code>v</code> and <code>w</code>.
29   * 
30   * <p>At this time, users are responsible for resetting the indices 
31   * (by calling <code>reset()</code>) if changes to the
32   * graph make it appropriate.
33   * 
34   * @author Joshua O'Madadhain
35   * @author Tom Nelson
36   *
37   */
38  public class DefaultParallelEdgeIndexFunction<V,E> implements EdgeIndexFunction<V,E>
39  {
40      protected Map<Context<Graph<V,E>,E>, Integer> edge_index = new HashMap<Context<Graph<V,E>,E>, Integer>();
41      
42      private DefaultParallelEdgeIndexFunction() {
43      }
44      
45      /**
46       * @param <V> the vertex type
47       * @param <E> the edge type
48       * @return an instance of this class
49       */
50      public static <V,E> DefaultParallelEdgeIndexFunction<V,E> getInstance() {
51          return new DefaultParallelEdgeIndexFunction<V,E>();
52      }
53      
54      /**
55       * Returns the index for <code>e</code> in <code>graph</code>.
56       * Calculates the indices for <code>e</code> and for all edges parallel
57       * to <code>e</code>, if they are not already assigned.
58       */
59      public int getIndex(Graph<V, E> graph, E e)
60      {
61      	checkNotNull(graph, "graph must not be null");
62      	checkNotNull(e, "'e' must not be null");
63          Integer index = edge_index.get(Context.<Graph<V,E>,E>getInstance(graph,e));
64          	//edge_index.get(e);
65          if(index == null) {
66          	Pair<V> endpoints = graph.getEndpoints(e);
67          	V u = endpoints.getFirst();
68          	V v = endpoints.getSecond();
69          	if(u.equals(v)) {
70          		index = getIndex(graph, e, v);
71          	} else {
72          		index = getIndex(graph, e, u, v);
73          	}
74          }
75          return index.intValue();
76      }
77  
78      protected int getIndex(Graph<V,E> graph, E e, V v, V u) {
79      	Collection<E> commonEdgeSet = new HashSet<E>(graph.getIncidentEdges(u));
80      	commonEdgeSet.retainAll(graph.getIncidentEdges(v));
81      	for(Iterator<E> iterator=commonEdgeSet.iterator(); iterator.hasNext(); ) {
82      		E edge = iterator.next();
83      		Pair<V> ep = graph.getEndpoints(edge);
84      		V first = ep.getFirst();
85      		V second = ep.getSecond();
86      		// remove loops
87      		if(first.equals(second) == true) {
88      			iterator.remove();
89      		}
90      		// remove edges in opposite direction
91      		if(first.equals(v) == false) {
92      			iterator.remove();
93      		}
94      	}
95      	int count=0;
96      	for(E other : commonEdgeSet) {
97      		if(e.equals(other) == false) {
98      			edge_index.put(Context.<Graph<V,E>,E>getInstance(graph,other), count);
99      			count++;
100     		}
101     	}
102     	edge_index.put(Context.<Graph<V,E>,E>getInstance(graph,e), count);
103     	return count;
104      }
105     
106     protected int getIndex(Graph<V,E> graph, E e, V v) {
107     	Collection<E> commonEdgeSet = new HashSet<E>();
108     	for(E another : graph.getIncidentEdges(v)) {
109     		V u = graph.getOpposite(v, another);
110     		if(u.equals(v)) {
111     			commonEdgeSet.add(another);
112     		}
113     	}
114     	int count=0;
115     	for(E other : commonEdgeSet) {
116     		if(e.equals(other) == false) {
117     			edge_index.put(Context.<Graph<V,E>,E>getInstance(graph,other), count);
118     			count++;
119     		}
120     	}
121     	edge_index.put(Context.<Graph<V,E>,E>getInstance(graph,e), count);
122     	return count;
123     }
124 
125     
126     /**
127      * Resets the indices for this edge and its parallel edges.
128      * Should be invoked when an edge parallel to <code>e</code>
129      * has been added or removed.
130      * @param graph the graph for which the indices are to be reset
131      * @param e the edge whose indices are to be reset
132      * 
133      */
134     public void reset(Graph<V,E> graph, E e) {
135     	Pair<V> endpoints = graph.getEndpoints(e);
136         getIndex(graph, e, endpoints.getFirst());
137         getIndex(graph, e, endpoints.getFirst(), endpoints.getSecond());
138     }
139     
140     /**
141      * Clears all edge indices for all edges in all graphs.
142      * Does not recalculate the indices.
143      */
144     public void reset()
145     {
146         edge_index.clear();
147     }
148 }