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.visualization.util;
13  
14  import java.util.Collection;
15  import java.util.HashMap;
16  import java.util.HashSet;
17  import java.util.Iterator;
18  import java.util.Map;
19  
20  import com.google.common.base.Predicate;
21  
22  import edu.uci.ics.jung.graph.Graph;
23  import edu.uci.ics.jung.graph.util.EdgeIndexFunction;
24  import edu.uci.ics.jung.graph.util.Pair;
25  
26  /**
27   * A class which creates and maintains indices for parallel edges.
28   * Edges are evaluated by a Predicate function and those that
29   * evaluate to true are excluded from computing a parallel offset
30   * 
31   * @author Tom Nelson
32   *
33   */
34  public class PredicatedParallelEdgeIndexFunction<V,E> implements EdgeIndexFunction<V,E> {
35      protected Map<E, Integer> edge_index = new HashMap<E, Integer>();
36      protected Predicate<E> predicate;
37      
38  	/**
39       * @param graph the graph with respect to which the index is calculated
40  	 */
41      private PredicatedParallelEdgeIndexFunction() {
42      }
43      
44      public static <V,E> PredicatedParallelEdgeIndexFunction<V,E> getInstance() {
45          return new PredicatedParallelEdgeIndexFunction<V,E>();
46      }
47  
48      /**
49       * Returns the index for the specified edge.
50       * Calculates the indices for <code>e</code> and for all edges parallel
51       * to <code>e</code>.
52       * @param graph the graph with respect to which the index is calculated
53       * @param e the edge whose index is to be calculated
54       * 
55       * @return the index of the edge with respect to this index function
56       */
57      public int getIndex(Graph<V, E> graph, E e) {
58      	
59      	if(predicate.apply(e)) {
60      		return 0;
61      	}
62          Integer index = edge_index.get(e);
63          if(index == null) {
64          	Pair<V> endpoints = graph.getEndpoints(e);
65          	V u = endpoints.getFirst();
66          	V v = endpoints.getSecond();
67          	if(u.equals(v)) {
68          		index = getIndex(graph, e, v);
69          	} else {
70          		index = getIndex(graph, e, u, v);
71          	}
72          }
73          return index.intValue();
74      }
75  
76      protected int getIndex(Graph<V,E> graph, E e, V v, V u) {
77      	Collection<E> commonEdgeSet = new HashSet<E>(graph.getIncidentEdges(u));
78      	commonEdgeSet.retainAll(graph.getIncidentEdges(v));
79      	for(Iterator<E> iterator=commonEdgeSet.iterator(); iterator.hasNext(); ) {
80      		E edge = iterator.next();
81      		Pair<V> ep = graph.getEndpoints(edge);
82      		V first = ep.getFirst();
83      		V second = ep.getSecond();
84      		// remove loops
85      		if(first.equals(second) == true) {
86      			iterator.remove();
87      		}
88      		// remove edges in opposite direction
89      		if(first.equals(v) == false) {
90      			iterator.remove();
91      		}
92      	}
93      	int count=0;
94      	for(E other : commonEdgeSet) {
95      		if(e.equals(other) == false) {
96      			edge_index.put(other, count);
97      			count++;
98      		}
99      	}
100     	edge_index.put(e, count);
101     	return count;
102      }
103     
104     protected int getIndex(Graph<V,E> graph, E e, V v) {
105     	Collection<E> commonEdgeSet = new HashSet<E>();
106     	for(E another : graph.getIncidentEdges(v)) {
107     		V u = graph.getOpposite(v, another);
108     		if(u.equals(v)) {
109     			commonEdgeSet.add(another);
110     		}
111     	}
112     	int count=0;
113     	for(E other : commonEdgeSet) {
114     		if(e.equals(other) == false) {
115     			edge_index.put(other, count);
116     			count++;
117     		}
118     	}
119     	edge_index.put(e, count);
120     	return count;
121     }
122 
123 	public Predicate<E> getPredicate() {
124 		return predicate;
125 	}
126 
127 	public void setPredicate(Predicate<E> predicate) {
128 		this.predicate = predicate;
129 	}
130 
131 	/**
132      * Resets the indices for this edge and its parallel edges.
133      * Should be invoked when an edge parallel to <code>e</code>
134      * has been added or removed in this graph.
135      * @param graph the graph with respect to which the index is calculated
136      * @param e the edge whose indices are to be reset for {@code graph}
137      */
138     public void reset(Graph<V,E> graph, E e) {
139     	Pair<V> endpoints = graph.getEndpoints(e);
140         getIndex(graph, e, endpoints.getFirst());
141         getIndex(graph, e, endpoints.getFirst(), endpoints.getSecond());
142     }
143     
144     /**
145      * Clears all edge indices for all edges in all graphs.
146      * Does not recalculate the indices.
147      */
148     public void reset()
149     {
150         edge_index.clear();
151     }
152 }