package com.sap.finex.interpreter.expressions;
import java.lang.reflect.InvocationTargetException;
import java.util.HashSet;
import java.util.Set;
import structure.Association;
import structure.Field;
import structure.FinexClass;
import structure.Type;
import behavior.actions.Statement;
import behavior.expressions.Expression;
import behavior.expressions.FieldInitializer;
import behavior.expressions.ObjectCreationExpression;
import behavior.functions.NativeImpl;
import behavior.functions.SignatureImplementation;
import com.sap.finex.interpreter.FinexInterpreter;
import com.sap.finex.interpreter.FinexStackFrame;
import com.sap.runlet.abstractinterpreter.Interpreter;
import com.sap.runlet.abstractinterpreter.Side;
import com.sap.runlet.abstractinterpreter.objects.ClassTypedObject;
import com.sap.runlet.abstractinterpreter.objects.EntityObject;
import com.sap.runlet.abstractinterpreter.objects.RunletObject;
import com.sap.tc.moin.repository.mmi.reflect.JmiException;
public class ObjectCreationInterpreter
implements Interpreter<ObjectCreationExpression, FinexClass, Type, FinexClass, Association, Field,
Statement, Expression, SignatureImplementation, FinexStackFrame, NativeImpl, FinexInterpreter> {
private ObjectCreationExpression oce;
public ObjectCreationInterpreter(ObjectCreationExpression oce) {
this.oce = oce;
}
@Override
public ClassTypedObject<Field, Type, FinexClass> evaluate(FinexInterpreter interpreter)
throws JmiException, SecurityException, IllegalArgumentException, NoSuchMethodException,
InstantiationException, IllegalAccessException, InvocationTargetException {
FinexStackFrame frame = interpreter.getCallstack().peek();
EntityObject<Association, Field, FinexClass, Type, FinexClass> result =
interpreter.createEntityObject(oce.getClassToInstantiate());
Set<Field> allFieldsWithDefault = new HashSet<Field>(oce.getClassToInstantiate().getFieldsWithDefaultValue());
// execute field initializers from create expression
for (FieldInitializer fieldInitializer : oce.getFieldInitializers()) {
Field fieldToInitialize = fieldInitializer.getFieldToInitialize();
allFieldsWithDefault.remove(fieldToInitialize); // don't use default if explicit initialization provided
RunletObject<Field, Type, FinexClass> value =
interpreter.evaluate(fieldInitializer.getInitExpression());
for (RunletObject<Field, Type, FinexClass> o : value.flatten()) {
if (interpreter.getModelAdapter().getSideOfEnd(fieldToInitialize).equals(Side.LEFT)) {
interpreter.addLink((ClassTypedObject<Field, Type, FinexClass>) o, result, fieldToInitialize.getAssociation(), null);
} else {
interpreter.addLink(result, (ClassTypedObject<Field, Type, FinexClass>) o, fieldToInitialize.getAssociation(), null);
}
frame.getAliasValues().used(o, fieldInitializer.getInitExpression(), result, oce);
}
}
// fill remaining fields with their default values
for (Field fieldWithDefault : allFieldsWithDefault) {
RunletObject<Field, Type, FinexClass> value =
interpreter.evaluate(fieldWithDefault.getDefaultValue());
for (RunletObject<Field, Type, FinexClass> o : value.flatten()) {
if (interpreter.getModelAdapter().getSideOfEnd(fieldWithDefault).equals(Side.LEFT)) {
interpreter.addLink((ClassTypedObject<Field, Type, FinexClass>) o, result, fieldWithDefault.getAssociation(), null);
} else {
interpreter.addLink(result, (ClassTypedObject<Field, Type, FinexClass>) o, fieldWithDefault.getAssociation(), null);
}
}
}
// All entities are automatically all stored persistently
interpreter.storeEntity(result);
return result;
}
}