package fr.inria.diversify.logger.stack.stackTraceOperation;
import fr.inria.diversify.logger.logger.KeyWord;
import fr.inria.diversify.logger.stack.stackElement.*;
import fr.inria.diversify.logger.stack.stackElement.StackTraceElement;
import fr.inria.diversify.util.Log;
import java.util.*;
/**
* Created by Simon on 17/04/14.
*/
public class StackTrace {
private List<StackTraceOperation> stackTraceOperations;
protected Stack<StackTraceCall> stackTraceCalls;
protected Map<String,Object> variablesValue;
protected int position;
protected int deep;
protected String name;
protected boolean variablesValueChange;
public void reset() {
stackTraceCalls = new Stack();
variablesValue = new HashMap();
deep = 0;
position = 0;
}
public StackTrace() {
stackTraceCalls = new Stack();
stackTraceOperations = new ArrayList();
variablesValue = new HashMap();
}
public int getDeep() {
return deep;
}
public void next() {
if(position < getStackTraceOperations().size()) {
variablesValueChange = false;
getStackTraceOperations().get(position).apply(this);
position++;
}
}
public void previous() {
if(position > 0) {
variablesValueChange = false;
position--;
getStackTraceOperations().get(position).restore(this);
}
}
public void next(int count) {
for(int i = 0; i < count; i++)
next();
}
public void previous(int count) {
for(int i = 0; i < count; i++)
previous();
}
public StackTraceCall getTop() {
if(stackTraceCalls.isEmpty())
return new StackTraceCall(0, 0, new HashMap<Integer, String>());
return stackTraceCalls.peek();
}
public StackTraceCall getTop2() {
if (stackTraceCalls.size() - 2 < 0)
return new StackTraceCall(0, 0, new HashMap<Integer, String>());
return stackTraceCalls.get(stackTraceCalls.size() - 2);
}
public boolean hasNext() {
return position < getStackTraceOperations().size();
}
public void parseTrace(String name, List<String> trace, Map<Integer, String> idMap) throws Exception {
this.name = name;
for(String operation: trace) {
try {
if(operation.length() < 1000000) {
addElement(operation, idMap);
} else {
Log.warn("error too big operation");
}
} catch (Exception e) {
// e.printStackTrace();
}
}
stackTraceCalls.clear();
}
protected void addElement(String line, Map<Integer,String> idMap) {
String[] split = line.split(";");
String type = split[0];
int i = line.indexOf(";".charAt(0), 0);
Integer deep = Integer.parseInt(split[1]);
i = line.indexOf(";".charAt(0),i);
Integer methodId = Integer.parseInt(split[2]);
i = line.indexOf(";".charAt(0),i);
StackTraceElement elem = parseElement(type, deep, methodId, line.substring(i + 1, line.length()), idMap);
if (elem instanceof StackTraceCall) {
addCall((StackTraceCall) elem, deep);
}
else {
try {
getStackTraceOperations().add(new StackTraceVariableObservation((StackTraceVariable) elem));
} catch (Exception e) {
Log.warn("error in add element");
}
}
}
/**
* Adds an element to the trace
*
* @param element Element to be added
*/
public void addElement(fr.inria.diversify.logger.stack.stackElement.StackTraceElement element) {
if ( element instanceof StackTraceCall) {
addCall((StackTraceCall) element, element.getOriginalDeep());
}
try {
getStackTraceOperations().add(new StackTraceVariableObservation((StackTraceVariable) element));
} catch (Exception e) {
Log.warn("CANNOT add an StackTraceOperation");
}
}
protected void addCall(StackTraceCall elem, int deep) {
int pop = 0;
while(!stackTraceCalls.isEmpty() && stackTraceCalls.peek().getOriginalDeep() >= deep) {
stackTraceCalls.pop();
pop++;
}
if(pop != 0)
getStackTraceOperations().add(new StackTracePop(pop));
stackTraceCalls.push(elem);
getStackTraceOperations().add(new StackTracePush(elem));
}
protected StackTraceElement parseElement(String type, int deep, int methodId, String info, Map<Integer,String> idMap) {
StackTraceElement st = null;
if(type.equals(KeyWord.methodCallObservation))
st = new StackTraceCall(methodId, deep, idMap);
if(type.equals(KeyWord.variableObservation))
st = new StackTraceVariable(methodId, deep, info, idMap);
if(type.equals(KeyWord.throwObservation))
st = new StackTraceException(methodId, deep, info);
if(type.equals(KeyWord.catchObservation))
st = new StackTraceCatch(methodId, deep, info);
return st;
}
@Override
public String toString() {
return name;
}
public String getName() {
return name;
}
public void setName(String name) { this.name = name; }
public String getFullName() {
return name;
}
public Stack<StackTraceCall> getStackTraceCalls() {
return stackTraceCalls;
}
public Map<String,Object> getVariable() {
return variablesValue;
}
public boolean getVariablesValueChange() {
return variablesValueChange;
}
public void setDepth(int depth) {
this.deep = depth;
}
public List<StackTraceOperation> getStackTraceOperations() {
return stackTraceOperations;
}
public boolean nextIsVar() {
return stackTraceOperations.get(position) instanceof StackTraceVariableObservation;
}
public void copy(StackTrace originalStackTrace) {
deep = originalStackTrace.deep;
variablesValue.clear();
variablesValue.putAll(originalStackTrace.variablesValue);
stackTraceCalls = (Stack) originalStackTrace.stackTraceCalls.clone();
}
}