package com.sap.runlet.interpreter.expressions; import java.lang.reflect.InvocationTargetException; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import behavioral.actions.Statement; import com.sap.runlet.abstractinterpreter.Interpreter; import com.sap.runlet.abstractinterpreter.objects.ClassTypedObject; import com.sap.runlet.abstractinterpreter.objects.RunletObject; import com.sap.runlet.interpreter.RunletInterpreter; import com.sap.runlet.interpreter.RunletStackFrame; import com.sap.runlet.interpreter.objects.ValueObject; import data.classes.ActualObjectParameter; import data.classes.Association; import data.classes.AssociationEnd; import data.classes.ClassTypeDefinition; import data.classes.NativeImpl; import data.classes.Parameter; import data.classes.SapClass; import data.classes.SignatureImplementation; import data.classes.TypeDefinition; import dataaccess.expressions.Expression; import dataaccess.expressions.literals.ObjectLiteral; import dataaccess.expressions.literals.ValueInit; public class ObjectLiteralInterpreter implements Interpreter<ObjectLiteral, SapClass, TypeDefinition, ClassTypeDefinition, Association, AssociationEnd, Statement, Expression, SignatureImplementation, RunletStackFrame, NativeImpl, RunletInterpreter> { private ObjectLiteral objectLiteral; public ObjectLiteralInterpreter(ObjectLiteral objectLiteral) { this.objectLiteral = objectLiteral; } @Override public ValueObject evaluate(RunletInterpreter interpreter) throws SecurityException, IllegalArgumentException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { ClassTypeDefinition ctd = (ClassTypeDefinition) objectLiteral.getType(); assert ctd.getClazz().isValueType() && !ctd.getClazz().isAbstract(); RunletStackFrame actualObjectParamsFrame = null; // push a stack frame linked to the current frame as its parent frame and put // the actual object parameters on the frame if any; this is required to resolve // the formal parameters when they are used, e.g., as actual parameters in // feature type definitions of the value class of which this interpreter // is creating an instance try { if (ctd.getClazz().getFormalObjectParameters().size() > 0) { actualObjectParamsFrame = new RunletStackFrame(interpreter.getCallstack().peek()); Iterator<Parameter> fopIter = ctd.getClazz().getFormalObjectParameters().iterator(); for (ActualObjectParameter aop : ctd.getObjectParameters()) { Parameter fop = fopIter.next(); RunletObject<AssociationEnd, TypeDefinition, ClassTypeDefinition> aopValue = interpreter.evaluate(aop.getValue()); // coerce the actual parameter to the type of the formal parameter if necessary RunletObject<AssociationEnd, TypeDefinition, ClassTypeDefinition> convertedAopValue = interpreter.convert(aopValue, fop.getType()); actualObjectParamsFrame.enterValue(fop, convertedAopValue); } // fill up with default parameters for (int i=ctd.getObjectParameters().size(); i<ctd.getClazz().getFormalObjectParameters().size(); i++) { Parameter fop = fopIter.next(); RunletObject<AssociationEnd, TypeDefinition, ClassTypeDefinition> defaultValue = interpreter.evaluate(fop.getDefaultValue()); // coerce the actual parameter to the type of the formal parameter if necessary RunletObject<AssociationEnd, TypeDefinition, ClassTypeDefinition> convertedAopValue = interpreter.convert(defaultValue, fop.getType()); actualObjectParamsFrame.enterValue(fop, convertedAopValue); } interpreter.push(actualObjectParamsFrame); } Map<AssociationEnd, Collection<ClassTypedObject<AssociationEnd, TypeDefinition, ClassTypeDefinition>>> propertyValues = new HashMap<AssociationEnd, Collection<ClassTypedObject<AssociationEnd, TypeDefinition, ClassTypeDefinition>>>(); for (ValueInit vi : objectLiteral.getPropertyValues()) { Collection<ClassTypedObject<AssociationEnd, TypeDefinition, ClassTypeDefinition>> values = RunletObject.createCollection(vi.getForEnd() .getType().isOrdered(), vi.getForEnd().getType().isUnique()); Iterable<RunletObject<AssociationEnd, TypeDefinition, ClassTypeDefinition>> featureValue = interpreter.evaluate(vi.getValue()).flatten(); for (RunletObject<AssociationEnd, TypeDefinition, ClassTypeDefinition> value : featureValue) { ClassTypedObject<AssociationEnd, TypeDefinition, ClassTypeDefinition> propertyValue = (ClassTypedObject<AssociationEnd, TypeDefinition, ClassTypeDefinition>) interpreter.convert(value, vi.getForEnd().getType()); values.add(propertyValue); } propertyValues.put(vi.getForEnd(), values); } ValueObject result = interpreter.createValueObject((ClassTypeDefinition) objectLiteral.getType(), propertyValues); interpreter.loadEqualityRelevantLinksOfValue(result); return result; } finally { if (actualObjectParamsFrame != null) { interpreter.pop(); } } } }