/* * Generic graph library * Copyright (C) 2000,2003,2004 University of Maryland * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // $Revision: 1.13 $ package edu.umd.cs.findbugs.graph; import java.util.Iterator; import java.util.Set; import java.util.TreeSet; /** * Algorithm to merge a set of vertices into a single vertex. Note that the * graph is modified as part of this process. */ public class MergeVertices<GraphType extends Graph<EdgeType, VertexType>, EdgeType extends GraphEdge<EdgeType, VertexType>, VertexType extends GraphVertex<VertexType>> { /** * Constructor. */ public MergeVertices() { } /** * Merge the specified set of vertices into a single vertex. * * @param vertexSet * the set of vertices to be merged * @param g * the graph to be modified * @param combinator * object used to combine vertices * @param toolkit * GraphToolkit used to copy auxiliary information for edges */ public void mergeVertices(Set<VertexType> vertexSet, GraphType g, VertexCombinator<VertexType> combinator, GraphToolkit<GraphType, EdgeType, VertexType> toolkit) { // Special case: if the vertex set contains a single vertex // or is empty, there is nothing to do if (vertexSet.size() <= 1) return; // Get all vertices to which we have outgoing edges // or from which we have incoming edges, since they'll need // to be fixed TreeSet<EdgeType> edgeSet = new TreeSet<EdgeType>(); for (Iterator<EdgeType> i = g.edgeIterator(); i.hasNext();) { EdgeType e = i.next(); if (vertexSet.contains(e.getSource()) || vertexSet.contains(e.getTarget())) edgeSet.add(e); } // Combine all of the vertices into a single composite vertex VertexType compositeVertex = combinator.combineVertices(vertexSet); // For each original edge into or out of the vertex set, // create an equivalent edge referencing the composite // vertex for (EdgeType e : edgeSet) { VertexType source = vertexSet.contains(e.getSource()) ? compositeVertex : e.getSource(); VertexType target = vertexSet.contains(e.getTarget()) ? compositeVertex : e.getTarget(); // if (source != compositeVertex && target != compositeVertex) // System.out.println("BIG OOPS!"); // Don't create a self edge for the composite vertex // unless one of the vertices in the vertex set // had a self edge if (source == compositeVertex && target == compositeVertex && e.getSource() != e.getTarget()) continue; // Don't create duplicate edges. if (g.lookupEdge(source, target) != null) continue; EdgeType compositeEdge = g.createEdge(source, target); // FIXME: we really should have an EdgeCombinator here toolkit.copyEdge(e, compositeEdge); } // Remove all of the vertices in the vertex set; this will // automatically remove the edges into and out of those // vertices for (VertexType aVertexSet : vertexSet) { g.removeVertex(aVertexSet); } } } // vim:ts=4