package com.sap.finex.interpreter.expressions;
import java.lang.reflect.InvocationTargetException;
import java.util.LinkedList;
import java.util.List;
import structure.Association;
import structure.Field;
import structure.FinexClass;
import structure.Type;
import behavior.actions.Statement;
import behavior.expressions.Expression;
import behavior.expressions.FilterExpression;
import behavior.functions.NativeImpl;
import behavior.functions.SignatureImplementation;
import com.sap.finex.interpreter.FinexInterpreter;
import com.sap.finex.interpreter.FinexStackFrame;
import com.sap.finex.interpreter.objects.FinexNativeObject;
import com.sap.runlet.abstractinterpreter.Interpreter;
import com.sap.runlet.abstractinterpreter.objects.MultiValuedObject;
import com.sap.runlet.abstractinterpreter.objects.RunletObject;
import com.sap.tc.moin.repository.mmi.reflect.JmiException;
public class FilterExpressionInterpreter
implements Interpreter<FilterExpression, FinexClass, Type, FinexClass, Association, Field,
Statement, Expression, SignatureImplementation, FinexStackFrame, NativeImpl, FinexInterpreter> {
private FilterExpression fe;
public FilterExpressionInterpreter(FilterExpression fe) {
this.fe = fe;
}
@Override
public RunletObject<Field, Type, FinexClass> evaluate(FinexInterpreter interpreter)
throws JmiException, SecurityException, IllegalArgumentException, NoSuchMethodException,
InstantiationException, IllegalAccessException, InvocationTargetException {
RunletObject<Field, Type, FinexClass> operand = interpreter.evaluate(fe.getOperand());
Expression condition = fe.getCondition();
FinexStackFrame currentStackFrame = interpreter.getCallstack().peek();
// TODO can there be outer joins for filter expressions such that when no operand results, there shall still be one tuple?
RunletObject<Field, Type, FinexClass> result;
List<RunletObject<Field, Type, FinexClass>> filteredResults = new LinkedList<RunletObject<Field, Type, FinexClass>>();
for (RunletObject<Field, Type, FinexClass> o : operand.flatten()) {
// TODO if o has alias, put alias value on stack frame
FinexStackFrame conditionFrame = new FinexStackFrame(interpreter.getCallstack().peek());
conditionFrame.setImplicitContext(o);
conditionFrame.enterCurrentAliasValues(fe.getOperand(), o);
interpreter.push(conditionFrame);
try {
if ((Boolean) ((FinexNativeObject) interpreter.evaluate(condition)).getNativeObject()) {
filteredResults.add(o);
currentStackFrame.getAliasValues().used(o, fe.getOperand(), o, fe);
}
} finally {
interpreter.pop();
}
}
result = FinexInterpreter.turnIntoObjectOfAppropriateMultiplicity(fe.getType(), interpreter, filteredResults,
operand instanceof MultiValuedObject<?, ?, ?>);
return result;
}
}