package com.sap.finex.interpreter; import java.lang.reflect.InvocationTargetException; import java.util.Collection; import java.util.List; import java.util.Map; import structure.Association; import structure.Field; import structure.FinexClass; import structure.Type; import behavior.actions.ExpressionStatement; import behavior.actions.Statement; import behavior.expressions.Alias; import behavior.expressions.All; import behavior.expressions.BinaryBooleanOperator; import behavior.expressions.BinaryNumericOperator; import behavior.expressions.Count; import behavior.expressions.Equals; import behavior.expressions.Expression; import behavior.expressions.FilterExpression; import behavior.expressions.ImplicitContext; import behavior.expressions.NamedValueExpression; import behavior.expressions.Not; import behavior.expressions.NumericAggregate; import behavior.expressions.ObjectCreationExpression; import behavior.expressions.PathExpression; import behavior.expressions.This; import behavior.expressions.Tuple; import behavior.expressions.Unequals; import behavior.expressions.literals.BinaryLiteral; import behavior.expressions.literals.BooleanLiteral; import behavior.expressions.literals.DateLiteral; import behavior.expressions.literals.DecimalLiteral; import behavior.expressions.literals.IntegerLiteral; import behavior.expressions.literals.MultiObjectLiteral; import behavior.expressions.literals.StringLiteral; import behavior.expressions.oql.OqlQuery; import behavior.functions.NativeImpl; import behavior.functions.SignatureImplementation; import com.sap.finex.interpreter.expressions.AllInterpreter; import com.sap.finex.interpreter.expressions.BinaryBooleanOperatorInterpreter; import com.sap.finex.interpreter.expressions.BinaryLiteralInterpreter; import com.sap.finex.interpreter.expressions.BinaryNumericOperatorInterpreter; import com.sap.finex.interpreter.expressions.BooleanLiteralInterpreter; import com.sap.finex.interpreter.expressions.CountInterpreter; import com.sap.finex.interpreter.expressions.DateLiteralInterpreter; import com.sap.finex.interpreter.expressions.DecimalLiteralInterpreter; import com.sap.finex.interpreter.expressions.EqualsInterpreter; import com.sap.finex.interpreter.expressions.FilterExpressionInterpreter; import com.sap.finex.interpreter.expressions.ImplicitContextInterpreter; import com.sap.finex.interpreter.expressions.IntegerLiteralInterpreter; import com.sap.finex.interpreter.expressions.MultiObjectLiteralInterpreter; import com.sap.finex.interpreter.expressions.NamedValueInterpreter; import com.sap.finex.interpreter.expressions.NotInterpreter; import com.sap.finex.interpreter.expressions.NumericAggregateInterpreter; import com.sap.finex.interpreter.expressions.ObjectCreationInterpreter; import com.sap.finex.interpreter.expressions.OqlQueryInterpreter; import com.sap.finex.interpreter.expressions.PathExpressionInterpreter; import com.sap.finex.interpreter.expressions.StringLiteralInterpreter; import com.sap.finex.interpreter.expressions.ThisInterpreter; import com.sap.finex.interpreter.expressions.TupleInterpreter; import com.sap.finex.interpreter.expressions.UnequalsInterpreter; import com.sap.finex.interpreter.objects.FinexNativeObject; import com.sap.finex.interpreter.statements.ExpressionStatementInterpreter; import com.sap.finex.metamodel.utils.MetamodelUtils; import com.sap.runlet.abstractinterpreter.AbstractRunletInterpreter; import com.sap.runlet.abstractinterpreter.Interpreter; import com.sap.runlet.abstractinterpreter.objects.ClassTypedObject; import com.sap.runlet.abstractinterpreter.objects.EmptyObject; import com.sap.runlet.abstractinterpreter.objects.MultiValuedObject; import com.sap.runlet.abstractinterpreter.objects.RunletObject; import com.sap.runlet.abstractinterpreter.repository.Repository; import com.sap.runlet.abstractinterpreter.util.Fraction; import com.sap.tc.moin.repository.Connection; public class FinexInterpreter extends AbstractRunletInterpreter<FinexClass, Type, FinexClass, Association, Field, Statement, Expression, SignatureImplementation, FinexStackFrame, NativeImpl, FinexInterpreter> { public FinexInterpreter( Connection conn, Repository<Association, Field, FinexClass, Type, FinexClass> repository) { super(conn, repository, new FinexModelAdapter(), new NativeInterpreterFactory(), new FinexLinkContainer( Activator.getDefault().getModelAdapter(), repository)); } /** * Spawns a new interpreter for parallel execution. This interpreter re-uses * the registries for subinterpreters for expressions, statements etc., the * MOIN {@link #connection}, the {@link #debugSession} as well as the shared * state consisting of the {@link #linkContainer}. The spawned interpreter * has a new {@link #callstack call stack} that is initialized with the * <tt>parent</tt> interpreter's top stack frame. * <p> * * This means that a spawned interpreter may not have all of the first stack * frame's scope parent frames on its own stack. If this first frame happens * to have a scope parent, this is referenced by a regular Java reference. * <p> * * The spawned interpreter created here will start out with an empty set of * {@link #runningChildren} child interpreters. It starts out in non- * {@link #running running} mode. * <p> */ private FinexInterpreter(FinexInterpreter parent) { super(parent); } @Override protected FinexValueObject createValueObjectWithoutEqualityRelevantLinks( FinexClass type, Map<Field, Collection<ClassTypedObject<Field, Type, FinexClass>>> propertyValues) { return new FinexValueObject(type, propertyValues, getUpdatingTag(), this); } @Override public FinexValueObject createValueObject( FinexClass type, Map<Field, Collection<ClassTypedObject<Field, Type, FinexClass>>> propertyValues) { return (FinexValueObject) super.createValueObject(type, propertyValues); } @Override protected void initExpressionInterpreterFactory(Connection conn) { getExpressionInterpreterFactory().registerInterpreter(StringLiteralInterpreter.class, conn.getClass(StringLiteral.CLASS_DESCRIPTOR).refMetaObject()); getExpressionInterpreterFactory().registerInterpreter(BinaryLiteralInterpreter.class, conn.getClass(BinaryLiteral.CLASS_DESCRIPTOR).refMetaObject()); getExpressionInterpreterFactory().registerInterpreter(BooleanLiteralInterpreter.class, conn.getClass(BooleanLiteral.CLASS_DESCRIPTOR).refMetaObject()); getExpressionInterpreterFactory().registerInterpreter(DateLiteralInterpreter.class, conn.getClass(DateLiteral.CLASS_DESCRIPTOR).refMetaObject()); getExpressionInterpreterFactory().registerInterpreter(DecimalLiteralInterpreter.class, conn.getClass(DecimalLiteral.CLASS_DESCRIPTOR).refMetaObject()); getExpressionInterpreterFactory().registerInterpreter(IntegerLiteralInterpreter.class, conn.getClass(IntegerLiteral.CLASS_DESCRIPTOR).refMetaObject()); getExpressionInterpreterFactory().registerInterpreter(BinaryBooleanOperatorInterpreter.class, conn.getClass(BinaryBooleanOperator.CLASS_DESCRIPTOR).refMetaObject()); getExpressionInterpreterFactory().registerInterpreter(NotInterpreter.class, conn.getClass(Not.CLASS_DESCRIPTOR).refMetaObject()); getExpressionInterpreterFactory().registerInterpreter(BinaryNumericOperatorInterpreter.class, conn.getClass(BinaryNumericOperator.CLASS_DESCRIPTOR).refMetaObject()); getExpressionInterpreterFactory().registerInterpreter(ObjectCreationInterpreter.class, conn.getClass(ObjectCreationExpression.CLASS_DESCRIPTOR).refMetaObject()); getExpressionInterpreterFactory().registerInterpreter(CountInterpreter.class, conn.getClass(Count.CLASS_DESCRIPTOR).refMetaObject()); getExpressionInterpreterFactory().registerInterpreter(PathExpressionInterpreter.class, conn.getClass(PathExpression.CLASS_DESCRIPTOR).refMetaObject()); getExpressionInterpreterFactory().registerInterpreter(FilterExpressionInterpreter.class, conn.getClass(FilterExpression.CLASS_DESCRIPTOR).refMetaObject()); getExpressionInterpreterFactory().registerInterpreter(ImplicitContextInterpreter.class, conn.getClass(ImplicitContext.CLASS_DESCRIPTOR).refMetaObject()); getExpressionInterpreterFactory().registerInterpreter(ThisInterpreter.class, conn.getClass(This.CLASS_DESCRIPTOR).refMetaObject()); getExpressionInterpreterFactory().registerInterpreter(EqualsInterpreter.class, conn.getClass(Equals.CLASS_DESCRIPTOR).refMetaObject()); getExpressionInterpreterFactory().registerInterpreter(UnequalsInterpreter.class, conn.getClass(Unequals.CLASS_DESCRIPTOR).refMetaObject()); getExpressionInterpreterFactory().registerInterpreter(TupleInterpreter.class, conn.getClass(Tuple.CLASS_DESCRIPTOR).refMetaObject()); getExpressionInterpreterFactory().registerInterpreter(NamedValueInterpreter.class, conn.getClass(NamedValueExpression.CLASS_DESCRIPTOR).refMetaObject()); getExpressionInterpreterFactory().registerInterpreter(MultiObjectLiteralInterpreter.class, conn.getClass(MultiObjectLiteral.CLASS_DESCRIPTOR).refMetaObject()); getExpressionInterpreterFactory().registerInterpreter(NumericAggregateInterpreter.class, conn.getClass(NumericAggregate.CLASS_DESCRIPTOR).refMetaObject()); getExpressionInterpreterFactory().registerInterpreter(AllInterpreter.class, conn.getClass(All.CLASS_DESCRIPTOR).refMetaObject()); getExpressionInterpreterFactory().registerInterpreter(OqlQueryInterpreter.class, conn.getClass(OqlQuery.CLASS_DESCRIPTOR).refMetaObject()); } @Override protected void initNativeInterpreterFactory(Connection conn) { // TODO Auto-generated method stub } @Override protected void initSignatureImplementationInterpreterFactory(Connection conn) { // TODO Auto-generated method stub } @Override protected void initStatementInterpreterFactory(Connection conn) { getStatementInterpreterFactory().registerInterpreter(ExpressionStatementInterpreter.class, conn.getClass(ExpressionStatement.CLASS_DESCRIPTOR).refMetaObject()); } @Override public FinexInterpreter spawn() { return new FinexInterpreter(this); } /** * If <tt>isMany</tt> is <tt>true</tt>, the result will be a {@link MultiValuedObject}. Otherwise, * the result will be an {@link EmptyObject} if the <tt>source</tt> object contains no objects, * or the single first object of <tt>source</tt> otherwise. */ public static RunletObject<Field, Type, FinexClass> turnIntoObjectOfAppropriateMultiplicity( Type type, FinexInterpreter interpreter, List<RunletObject<Field, Type, FinexClass>> source, boolean isMany) { RunletObject<Field, Type, FinexClass> result; if (isMany) { // TODO what about ordering and uniqueness? result = new MultiValuedObject<Field, Type, FinexClass>(type, source, /* ordered */ false, /* unique */ false); } else { if (source.size() > 0) { result = source.iterator().next(); } else { result = new EmptyObject<Field, FinexClass, Type, FinexClass>(type, interpreter.getModelAdapter()); } } return result; } /** * In addition to calling the superclass method, if an {@link Alias} is defined for <tt>e</tt>, then for each object of the * flattened results adds an entry to the current stack frame's {@link AliasValues} map. * <p> * * Implementations of the micro-{@link Interpreter}s for expression types must ensure that for any operand they compute they * enter alias values for the operand's evaluation onto the operand evaluation's stack frame. */ @Override public RunletObject<Field, Type, FinexClass> evaluate(Expression e) throws SecurityException, IllegalArgumentException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { RunletObject<Field, Type, FinexClass> result = super.evaluate(e); Alias a = e.getAlias(); if (a != null) { AliasValues aliasValues = getCallstack().peek().getAliasValues(); for (RunletObject<Field, Type, FinexClass> o:result.flatten()) { aliasValues.enterAliasValue(e, o, a, o); } } return result; } public FinexNativeObject convertFractionToNativeObject(Fraction result, Type targetType) { FinexNativeObject runletResult; if (targetType.equals(MetamodelUtils.findClass(getConnection(), "Decimal"))) { // decimals are represented as Fractions, we're okay runletResult = new FinexNativeObject((FinexClass) targetType, result, getDefaultSnapshot(), this); } else { // Integers are represented as long; convert runletResult = new FinexNativeObject((FinexClass) targetType, result.asLong(), getDefaultSnapshot(), this); } return runletResult; } }