/* * 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(); } }