package com.sap.runlet.interpreter.rucola;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import com.sap.runlet.abstractinterpreter.objects.RunletObject;
import com.sap.runlet.interpreter.RunletInterpreter;
import com.sap.runlet.interpreter.expressions.MethodCallInterpreter;
import data.classes.AssociationEnd;
import data.classes.ClassTypeDefinition;
import data.classes.MethodSignature;
import data.classes.Parameter;
import data.classes.SapClass;
import data.classes.TypeDefinition;
import dataaccess.expressions.ExpressionsFactory;
import dataaccess.expressions.MethodCallExpression;
public class ClassTypedObject extends RucolaObject {
public ClassTypedObject(Rucola rucola, RunletObject<AssociationEnd, TypeDefinition, ClassTypeDefinition> object) {
super(rucola, object);
}
public RucolaObject call(String methodName, Object... args) {
MethodCallExpression mce = ExpressionsFactory.eINSTANCE.createMethodCallExpression();
// TODO for NestedTypeDefinitions this won't work and we'd need to resolve the innermost type definition
SapClass c = ((ClassTypeDefinition) getObject().getType()).getClazz();
MethodSignature ms = null;
for (MethodSignature m : c.allSignatures()) {
if (m.getName().equals(methodName)) {
ms = m;
break;
}
}
if (ms == null) {
throw new RucolaException("Method "+methodName+" not found on "+getObject()+" of type "+getObject().getType());
}
mce.setMethodSignature(ms);
List<RucolaObject> argsAsRucola = new LinkedList<RucolaObject>();
Iterator<Parameter> paramIter = ms.getInput().iterator();
for (Object arg:args) {
argsAsRucola.add(getRucola().wrap(arg, paramIter.next().getType()));
}
List<RunletObject<AssociationEnd, TypeDefinition, ClassTypeDefinition>> argsAsRiver = new LinkedList<RunletObject<AssociationEnd, TypeDefinition, ClassTypeDefinition>>();
for (RucolaObject rucolaArg:argsAsRucola) {
argsAsRiver.add(rucolaArg.getObject());
}
RucolaMethodCallInterpreter mcInterpreter = new RucolaMethodCallInterpreter(mce, getObject(), argsAsRiver);
try {
RunletObject<AssociationEnd, TypeDefinition, ClassTypeDefinition> riverResult = mcInterpreter.evaluate(getInterpreter());
return getRucola().createRucolaObjectForRiverObject(riverResult);
} catch (Exception e) {
throw new RucolaException("Error during evaluating method call to "+methodName+" on "+getObject()+
": "+e.getMessage(), e);
}
}
public RucolaObject get(String remoteAssociationEndName) {
// TODO extend such that it works based on non-exposed but navigable association ends too
return call("."+remoteAssociationEndName);
}
public RucolaObject set(String remoteAssociationEndName, Object value) {
// TODO extend such that it works based on non-exposed but navigable association ends too
return call(remoteAssociationEndName+"=", value);
}
private class RucolaMethodCallInterpreter extends MethodCallInterpreter {
private RunletObject<AssociationEnd, TypeDefinition, ClassTypeDefinition> thiz;
private List<RunletObject<AssociationEnd, TypeDefinition, ClassTypeDefinition>> params;
public RucolaMethodCallInterpreter(MethodCallExpression mce, RunletObject<AssociationEnd, TypeDefinition, ClassTypeDefinition> thiz, List<RunletObject<AssociationEnd, TypeDefinition, ClassTypeDefinition>> params) {
super(mce);
this.thiz = thiz;
this.params = params;
}
@Override
protected RunletObject<AssociationEnd, TypeDefinition, ClassTypeDefinition> getOnObject(RunletInterpreter interpreter) {
return thiz;
}
@Override
protected List<RunletObject<AssociationEnd, TypeDefinition, ClassTypeDefinition>> getParameterValues(RunletInterpreter interpreter) {
return params;
}
}
}