package jqian.sootex.util.graph;
import java.util.*;
import soot.toolkits.graph.*;
/**
* Floyd-Warshall path table
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public class PathTable implements IPathQuery{
public PathTable(DirectedGraph graph){
//establish the map between an Unit and its index
int nodeNum=graph.size();
_entrys.addAll(graph.getHeads());
//the hash map is initialized as examples in soot 2.2.1 tuturial
_node2Int=new HashMap(nodeNum*2 + 1, 0.7f);
_id2Node=new Object[nodeNum];
int i=0;
for (Iterator it =graph.iterator(); it.hasNext(); i++) {
Object node = it.next();
_node2Int.put(node, new Integer(i));
_id2Node[i] = node;
}
//Use floyd-warshall algortihm to build a path table
//init the path matrix
_pathTbl = new boolean[nodeNum][nodeNum];
for (i = 0; i < nodeNum; i++) {
Object node = _id2Node[i];
List succs = graph.getSuccsOf(node);
for (Iterator it = succs.iterator(); it.hasNext();) {
Object to = it.next();
int toIndex =((Integer)_node2Int.get(to)).intValue();
_pathTbl[i][toIndex] = true;
}
}
//Floyd-WarShall
for (i = 0; i < nodeNum; i++){
for (int j = 0; j < nodeNum; j++) {
if (_pathTbl[j][i]) {
for (int k = 0; k < nodeNum; k++)
_pathTbl[j][k] = _pathTbl[j][k] || _pathTbl[i][k];
}
}
}
}
public int getNodeId(Object obj){
return ((Integer)_node2Int.get(obj)).intValue();
}
public boolean hasPath(Object src,Object dest){
int srcIndex=((Integer)_node2Int.get(src)).intValue();
int destIndex=((Integer)_node2Int.get(dest)).intValue();
return _pathTbl[srcIndex][destIndex];
}
public boolean hasPath(int src,int dest){
return _pathTbl[src][dest];
}
public boolean reachableFromHead(int nodeId){
for(Iterator it=_entrys.iterator();it.hasNext();){
Object entry= it.next();
int entryId=((Integer)_node2Int.get(entry)).intValue();
if(entryId==nodeId) return true;
if(hasPath(entryId,nodeId)) return true;
}
return false;
}
public String toString(){
String str="\n----------------------Nodes--------------------------";
for(int i=0;i<_id2Node.length;i++){
str+="\n["+i+"] ";
if(_id2Node[i]!=null)
str+=_id2Node[i].hashCode()+": "+_id2Node[i].toString();
}
str+="\n--------------------Path Table----------------------\n ";
for(int i=0;i<_id2Node.length;i++) {
str+=" "+formatString(2,i);
}
for(int i=0;i<_id2Node.length;i++){
str+="\n"+formatString(2,i);
for(int j=0;j<_id2Node.length;j++){
char c=_pathTbl[i][j]? 'X':' ';
str+=" "+c;
}
}
str+="\n--------------------End Table-----------------------";
return str;
}
private String formatString(int setw,int val){
String str=String.valueOf(val);
while(str.length()<setw){
str=" "+str; //fill the left with blank
}
return str;
}
/////////////////////////////////////////////////////////
private boolean _pathTbl[][];
private Map/*<Object,Integer>*/ _node2Int;
private Object[] _id2Node;
private List _entrys=new LinkedList();
}