package jqian.sootex.dependency.slicing;
import java.util.*;
import jqian.sootex.dependency.pdg.*;
import jqian.sootex.util.SootUtils;
import soot.*;
/**
*
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public class ProgramSlice {
private Collection<SlicingCriterion> _criteria;
private Map<MethodOrMethodContext,Collection> _mc2stmts; //covered statement in each method context
private Map<MethodOrMethodContext,Collection> _mc2params; //relevant parameter indexes
public ProgramSlice(Collection criteria,Collection<DependenceNode> depNodes){
this._criteria = criteria;
_mc2stmts = new HashMap<MethodOrMethodContext,Collection>();
_mc2params = new HashMap<MethodOrMethodContext,Collection>();
for(DependenceNode n: depNodes){
MethodOrMethodContext mc = n.getMethodOrMethodContext();
if(n instanceof JimpleStmtNode){
Collection stmts = openMappedCollection(_mc2stmts,mc);
stmts.add(n.getBinding());
}
else if(n instanceof FormalIn){
FormalIn fm = (FormalIn)n;
int paramIdx = fm.getParamIndex();
if(paramIdx>=0){
Collection params = openMappedCollection(_mc2params,mc);
params.add(new Integer(paramIdx));
}
}
}
}
public Collection<SlicingCriterion> criterion(){
return _criteria;
}
public Collection<MethodOrMethodContext> getMethodOrMethodContexts(){
return _mc2stmts.keySet();
}
public Collection<Unit> getRelevantStmts(SootClass cls){
//TODO Here we do not actually handle context-sensitive analysis
Collection<Unit> units = new LinkedList<Unit>();
for(Iterator<?> it=cls.methodIterator();it.hasNext();){
SootMethod m = (SootMethod)it.next();
Collection<Unit> relevants = getRelevantStmts(m);
if(relevants!=null)
units.addAll(relevants);
}
return units;
}
public Collection<Unit> getRelevantStmts(MethodOrMethodContext mc){
return _mc2stmts.get(mc);
}
/** Return indexes of relevant parameters. */
public Collection<Integer> getRelevantParams(MethodOrMethodContext mc){
return _mc2params.get(mc);
}
public Collection<Integer> getRelevantLines(MethodOrMethodContext mc){
Collection<Unit> stmts = getRelevantStmts(mc);
if(stmts==null)
return Collections.emptyList();
return toJavaLines(stmts);
}
public Collection<Integer> getRelevantLines(SootClass cls){
Collection<Unit> stmts = getRelevantStmts(cls);
if(stmts==null)
return new LinkedList<Integer>();
return toJavaLines(stmts);
}
private Collection openMappedCollection(Map map,MethodOrMethodContext mc){
Collection out = (Collection)map.get(mc);
if(out==null){
out = new LinkedList();
map.put(mc,out);
}
return out;
}
private static Collection<Integer> toJavaLines(Collection<Unit> in){
Collection<Integer> lines = new HashSet<Integer>();
for(Unit s: in){
int line = SootUtils.getLine(s);
lines.add(line);
}
return lines;
}
}