All Downloads are FREE. Search and download functionalities are using the official Maven repository.

soot.toolkits.graph.HashMutableEdgeLabelledDirectedGraph Maven / Gradle / Ivy

There is a newer version: 1.12.0
Show newest version
/* Soot - a J*va Optimization Framework
 * Copyright (C) 1999 Patrice Pominville, Raja Vallee-Rai, Patrick Lam
 * Copyright (C) 2007 Richard L. Halpert
 *
 * 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.
 */

/*
 * Modified by the Sable Research Group and others 1997-1999.  
 * See the 'credits' file distributed with Soot for the complete list of
 * contributors.  (Soot is distributed at http://www.sable.mcgill.ca/soot)
 */


package soot.toolkits.graph;


import java.util.*;

import soot.*;
import soot.util.*;




/**
 *   HashMap based implementation of a MutableEdgeLabelledDirectedGraph.
 */
class DGEdge
{
	Object from;
	Object to;
	
	public DGEdge(Object from, Object to)
	{
		this.from = from;
		this.to = to;
	}
	
	public Object from()
	{
		return from;
	}
	
	public Object to()
	{
		return to;
	}
	
	public boolean equals(Object o)
	{
		if(o instanceof DGEdge)
		{
			DGEdge other = (DGEdge) o;
			return from.equals(other.from) && to.equals(other.to);
		}
		return false;
	}
	
	public int hashCode()
	{
		return from.hashCode() + to.hashCode();
	}
}

public class HashMutableEdgeLabelledDirectedGraph implements MutableEdgeLabelledDirectedGraph
{
    protected HashMap nodeToPreds = new HashMap();
    protected HashMap nodeToSuccs = new HashMap();
    
    protected HashMap> edgeToLabels = new HashMap();
    protected HashMap> labelToEdges = new HashMap();

    protected Chain heads = new HashChain();
    protected Chain tails = new HashChain();

    public HashMutableEdgeLabelledDirectedGraph()
    {
    }

    /** Removes all nodes and edges. */
    public void clearAll() {
        nodeToPreds = new HashMap();
        nodeToSuccs = new HashMap();
        edgeToLabels = new HashMap();
        labelToEdges = new HashMap();
        heads = new HashChain();
        tails = new HashChain();
    }

    public Object clone() {
        HashMutableEdgeLabelledDirectedGraph g = new HashMutableEdgeLabelledDirectedGraph();
        g.nodeToPreds = (HashMap)nodeToPreds.clone();
        g.nodeToSuccs = (HashMap)nodeToSuccs.clone();
        g.edgeToLabels = (HashMap)edgeToLabels.clone();
        g.labelToEdges = (HashMap)labelToEdges.clone();
        g.heads = HashChain.listToHashChain(HashChain.toList(heads));
        g.tails = HashChain.listToHashChain(HashChain.toList(tails));
        return g;
    }

    /* Returns an unbacked list of heads for this graph. */
    public List getHeads()
    {
        ArrayList l = new ArrayList(); l.addAll(heads);
        return Collections.unmodifiableList(l);
    }

    /* Returns an unbacked list of tails for this graph. */
    public List getTails()
    {
        ArrayList l = new ArrayList(); l.addAll(tails);
        return Collections.unmodifiableList(l);
    }

    public List getPredsOf(Object s)
    {
        List l = nodeToPreds.get(s);
        if (l != null)
            return Collections.unmodifiableList(l);
        else
            throw new RuntimeException(s+"not in graph!");
    }

    public List getSuccsOf(Object s)
    {
        List l = nodeToSuccs.get(s);
        if (l != null)
            return Collections.unmodifiableList(l);
        else
            throw new RuntimeException(s+"not in graph!");
    }

    public int size()
    {
        return nodeToPreds.keySet().size();
    }

    public Iterator iterator()
    {
        return nodeToPreds.keySet().iterator();
    }

    public void addEdge(Object from, Object to, Object label)
    {
        if (from == null || to == null)
						throw new RuntimeException("edge from or to null");
						
		if (label == null)
						throw new RuntimeException("edge with null label");

        if (containsEdge(from, to, label))
            return;

        List succsList = nodeToSuccs.get(from);
        if (succsList == null)
            throw new RuntimeException(from + " not in graph!");

        List predsList = nodeToPreds.get(to);
        if (predsList == null)
            throw new RuntimeException(to + " not in graph!");

        if (heads.contains(to))
            heads.remove(to);

        if (tails.contains(from))
            tails.remove(from);
		
		if(!succsList.contains(to))
	        succsList.add(to);
	    if(!predsList.contains(from))
	        predsList.add(from);
	    
	    DGEdge edge = new DGEdge(from, to);
		if(!edgeToLabels.containsKey(edge))
			edgeToLabels.put(edge, new ArrayList());
	    List labels = edgeToLabels.get(edge);
	    
	    if(!labelToEdges.containsKey(label))
	    	labelToEdges.put(label, new ArrayList());
	    List edges = labelToEdges.get(label);
		
//		if(!labels.contains(label))
			labels.add(label);
//		if(!edges.contains(edge))
			edges.add(edge);
    }

	public List getLabelsForEdges(Object from, Object to)
	{
		DGEdge edge = new DGEdge(from, to);
		return edgeToLabels.get(edge);
	}
	
	public MutableDirectedGraph getEdgesForLabel(Object label)
	{
		List edges = labelToEdges.get(label);
		MutableDirectedGraph ret = new HashMutableDirectedGraph();
		if(edges == null)
			return ret;
		for(DGEdge edge : edges)
		{
			if(!ret.containsNode(edge.from()))
				ret.addNode(edge.from());
			if(!ret.containsNode(edge.to()))
				ret.addNode(edge.to());
			ret.addEdge(edge.from(), edge.to());
		}
		return ret;
	}

    public void removeEdge(Object from, Object to, Object label)
    {
        if (!containsEdge(from, to, label))
            return;
            
        DGEdge edge = new DGEdge(from, to);
        List labels = edgeToLabels.get(edge);
        if( labels == null )
        	throw new RuntimeException("edge " + edge + " not in graph!");
        
        List edges = labelToEdges.get(label);
        if( edges == null )
        	throw new RuntimeException("label " + label + " not in graph!");

		labels.remove(label);
		edges.remove(edge);
		
		// if this edge has no more labels, then it's gone!
		if(labels.isEmpty())
		{
			edgeToLabels.remove(edge);

	        List succsList = nodeToSuccs.get(from);
	        if (succsList == null)
	            throw new RuntimeException(from + " not in graph!");

	        List predsList = nodeToPreds.get(to);
	        if (predsList == null)
	            throw new RuntimeException(to + " not in graph!");
			
	        succsList.remove(to);
	        predsList.remove(from);

	        if (succsList.isEmpty())
	            tails.add(from);

	        if (predsList.isEmpty())
	            heads.add(to);
	    }
	    
	    // if this label has no more edges, then who cares?
	    if(edges.isEmpty())
	    	labelToEdges.remove(label);
    }

    public void removeAllEdges(Object from, Object to)
	{
        if (!containsAnyEdge(from, to))
            return;
            
        DGEdge edge = new DGEdge(from, to);
        List labels = edgeToLabels.get(edge);
        if( labels == null )
        	throw new RuntimeException("edge " + edge + " not in graph!");
        
        for(Object label : labels)
        {        
	        removeEdge(from, to, label);
	    }
	}

    public void removeAllEdges(Object label)
    {
		if( !containsAnyEdge(label) )
			return;
		
		List edges = labelToEdges.get(label);
		if( edges == null )
			throw new RuntimeException("label " + label + " not in graph!");
			
		for(DGEdge edge : edges)
		{
			removeEdge(edge.from(), edge.to(), label);
		}
	}

    public boolean containsEdge(Object from, Object to, Object label)
    {
		DGEdge edge = new DGEdge(from, to);
		if(edgeToLabels.get(edge) != null && edgeToLabels.get(edge).contains(label))
			return true;
		return false;
    }

    public boolean containsAnyEdge(Object from, Object to)
    {
		DGEdge edge = new DGEdge(from, to);
		if(edgeToLabels.get(edge) != null && edgeToLabels.get(edge).isEmpty())
			return false;
		return true;
    }

    public boolean containsAnyEdge(Object label)
    {
		if(labelToEdges.get(label) != null && labelToEdges.get(label).isEmpty())
			return false;
		return true;
    }

    public boolean containsNode(Object node)
    {
        return nodeToPreds.keySet().contains(node);
    }

    public List getNodes()
    {
        return Arrays.asList(nodeToPreds.keySet().toArray());
    }

    public void addNode(Object node)
    {
				if (containsNode(node))
						throw new RuntimeException("Node already in graph");
				
				nodeToSuccs.put(node, new ArrayList());
        nodeToPreds.put(node, new ArrayList());
        heads.add(node); 
				tails.add(node);
    }

    public void removeNode(Object node)
    {
        List succs = (List)nodeToSuccs.get(node).clone();
        for (Iterator succsIt = succs.iterator(); succsIt.hasNext(); )
            removeAllEdges(node, succsIt.next());
        nodeToSuccs.remove(node);

        List preds = (List)nodeToPreds.get(node).clone();
        for (Iterator predsIt = preds.iterator(); predsIt.hasNext(); )
            removeAllEdges(predsIt.next(), node);
        nodeToPreds.remove(node);

        if (heads.contains(node))
            heads.remove(node); 

        if (tails.contains(node))
            tails.remove(node);
    }

    public void printGraph()
    {

		for (Iterator it = iterator(); it.hasNext(); )
		{
		    Object node = it.next();
		    G.v().out.println("Node = "+node);
		    G.v().out.println("Preds:");
		    for (Iterator predsIt = getPredsOf(node).iterator(); predsIt.hasNext(); )
		    {
		    	Object pred = predsIt.next();
		        DGEdge edge = new DGEdge(pred, node);
		        List labels = edgeToLabels.get(edge);
				G.v().out.println("     " + pred + " [" + labels + "]");
		    }
		    G.v().out.println("Succs:");
		    for (Iterator succsIt = getSuccsOf(node).iterator(); succsIt.hasNext(); )
		    {
		    	Object succ = succsIt.next();
		        DGEdge edge = new DGEdge(node, succ);
		        List labels = edgeToLabels.get(edge);
				G.v().out.println("     " + succ + " [" + labels + "]");
		    }
		}
    }

}