/*
* Created on Sep 24, 2005
*
* Copyright (c) 2005, the JUNG Project and the Regents of the University
* of California
* All rights reserved.
*
* This software is open-source under the BSD license; see either
* "license.txt" or
* http://jung.sourceforge.net/license.txt for a description.
*/
package edu.uci.ics.jung.graph.util;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import edu.uci.ics.jung.graph.Graph;
/**
* A class which creates and maintains indices for parallel edges. Parallel
* edges are defined here to be the collection of edges that are returned by
* <code>v.findEdgeSet(w)</code> for some <code>v</code> and <code>w</code>.
*
* <p>
* At this time, users are responsible for resetting the indices (by calling
* <code>reset()</code>) if changes to the graph make it appropriate.
* </p>
*
* @author Joshua O'Madadhain
* @author Tom Nelson
*
*/
public class DefaultParallelEdgeIndexFunction<V, E>
implements EdgeIndexFunction<V, E> {
protected Map<Context<Graph<V, E>, E>, Integer> edge_index = new HashMap<Context<Graph<V, E>, E>, Integer>();
private DefaultParallelEdgeIndexFunction() {
}
/**
* Returns an instance of this class.
*
* @param <V>
* the vertex type
* @param <E>
* the edge type
*/
public static <V, E> DefaultParallelEdgeIndexFunction<V, E> getInstance() {
return new DefaultParallelEdgeIndexFunction<V, E>();
}
/**
* Returns the index for <code>e</code> in <code>graph</code>. Calculates
* the indices for <code>e</code> and for all edges parallel to
* <code>e</code>, if they are not already assigned.
*/
@Override
public int getIndex(Graph<V, E> graph, E e) {
Integer index = edge_index
.get(Context.<Graph<V, E>, E> getInstance(graph, e));
// edge_index.get(e);
if (index == null) {
Pair<V> endpoints = graph.getEndpoints(e);
V u = endpoints.getFirst();
V v = endpoints.getSecond();
if (u.equals(v)) {
index = getIndex(graph, e, v);
} else {
index = getIndex(graph, e, u, v);
}
}
return index.intValue();
}
protected int getIndex(Graph<V, E> graph, E e, V v, V u) {
Collection<E> commonEdgeSet = new HashSet<E>(graph.getIncidentEdges(u));
commonEdgeSet.retainAll(graph.getIncidentEdges(v));
for (Iterator<E> iterator = commonEdgeSet.iterator(); iterator
.hasNext();) {
E edge = iterator.next();
Pair<V> ep = graph.getEndpoints(edge);
V first = ep.getFirst();
V second = ep.getSecond();
// remove loops
if (first.equals(second) == true) {
iterator.remove();
}
// remove edges in opposite direction
if (first.equals(v) == false) {
iterator.remove();
}
}
int count = 0;
for (E other : commonEdgeSet) {
if (e.equals(other) == false) {
edge_index.put(
Context.<Graph<V, E>, E> getInstance(graph, other),
count);
count++;
}
}
edge_index.put(Context.<Graph<V, E>, E> getInstance(graph, e), count);
return count;
}
protected int getIndex(Graph<V, E> graph, E e, V v) {
Collection<E> commonEdgeSet = new HashSet<E>();
for (E another : graph.getIncidentEdges(v)) {
V u = graph.getOpposite(v, another);
if (u.equals(v)) {
commonEdgeSet.add(another);
}
}
int count = 0;
for (E other : commonEdgeSet) {
if (e.equals(other) == false) {
edge_index.put(
Context.<Graph<V, E>, E> getInstance(graph, other),
count);
count++;
}
}
edge_index.put(Context.<Graph<V, E>, E> getInstance(graph, e), count);
return count;
}
/**
* Resets the indices for this edge and its parallel edges. Should be
* invoked when an edge parallel to <code>e</code> has been added or
* removed.
*
* @param e
*/
@Override
public void reset(Graph<V, E> graph, E e) {
Pair<V> endpoints = graph.getEndpoints(e);
getIndex(graph, e, endpoints.getFirst());
getIndex(graph, e, endpoints.getFirst(), endpoints.getSecond());
}
/**
* Clears all edge indices for all edges in all graphs. Does not recalculate
* the indices.
*/
@Override
public void reset() {
edge_index.clear();
}
}