blob: 6070e2a756b9ddeee29b0abc71baaf6a3bf07b99 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013, 2019 CEA LIST and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* E.D.Willink(CEA LIST) - Initial API and implementation
*******************************************************************************/
package org.eclipse.ocl.examples.codegen.java;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.emf.codegen.ecore.genmodel.GenPackage;
import org.eclipse.emf.codegen.ecore.genmodel.GenParameter;
import org.eclipse.emf.codegen.util.CodeGenUtil;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.examples.codegen.analyzer.CodeGenAnalyzer;
import org.eclipse.ocl.examples.codegen.cgmodel.CGAssertNonNullExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGBoolean;
import org.eclipse.ocl.examples.codegen.cgmodel.CGBoxExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGBuiltInIterationCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGCachedOperation;
import org.eclipse.ocl.examples.codegen.cgmodel.CGCachedOperationCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGCastExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGCatchExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGClass;
import org.eclipse.ocl.examples.codegen.cgmodel.CGCollectionExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGCollectionPart;
import org.eclipse.ocl.examples.codegen.cgmodel.CGConstantExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGConstraint;
import org.eclipse.ocl.examples.codegen.cgmodel.CGEcoreDataTypeShadowExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGEcoreExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGEcoreOperationCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGEcorePropertyCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGElement;
import org.eclipse.ocl.examples.codegen.cgmodel.CGElementId;
import org.eclipse.ocl.examples.codegen.cgmodel.CGExecutorCompositionProperty;
import org.eclipse.ocl.examples.codegen.cgmodel.CGExecutorNavigationProperty;
import org.eclipse.ocl.examples.codegen.cgmodel.CGExecutorOperation;
import org.eclipse.ocl.examples.codegen.cgmodel.CGExecutorOperationCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGExecutorOppositeProperty;
import org.eclipse.ocl.examples.codegen.cgmodel.CGExecutorOppositePropertyCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGExecutorPropertyCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGExecutorShadowPart;
import org.eclipse.ocl.examples.codegen.cgmodel.CGExecutorType;
import org.eclipse.ocl.examples.codegen.cgmodel.CGGuardExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGIfExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGInteger;
import org.eclipse.ocl.examples.codegen.cgmodel.CGInvalid;
import org.eclipse.ocl.examples.codegen.cgmodel.CGIsEqual2Exp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGIsEqualExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGIsInvalidExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGIsKindOfExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGIsUndefinedExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGIterator;
import org.eclipse.ocl.examples.codegen.cgmodel.CGLetExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGLibraryIterateCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGLibraryIterationCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGLibraryOperation;
import org.eclipse.ocl.examples.codegen.cgmodel.CGLibraryOperationCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGLibraryPropertyCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGMapExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGMapPart;
import org.eclipse.ocl.examples.codegen.cgmodel.CGNativeOperation;
import org.eclipse.ocl.examples.codegen.cgmodel.CGNativeOperationCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGNativeProperty;
import org.eclipse.ocl.examples.codegen.cgmodel.CGNativePropertyCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGNull;
import org.eclipse.ocl.examples.codegen.cgmodel.CGOperation;
import org.eclipse.ocl.examples.codegen.cgmodel.CGPackage;
import org.eclipse.ocl.examples.codegen.cgmodel.CGParameter;
import org.eclipse.ocl.examples.codegen.cgmodel.CGProperty;
import org.eclipse.ocl.examples.codegen.cgmodel.CGReal;
import org.eclipse.ocl.examples.codegen.cgmodel.CGShadowExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGShadowPart;
import org.eclipse.ocl.examples.codegen.cgmodel.CGString;
import org.eclipse.ocl.examples.codegen.cgmodel.CGTemplateParameterExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGText;
import org.eclipse.ocl.examples.codegen.cgmodel.CGThrowExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGTupleExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGTuplePart;
import org.eclipse.ocl.examples.codegen.cgmodel.CGTuplePartCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGTypeExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGTypeId;
import org.eclipse.ocl.examples.codegen.cgmodel.CGUnboxExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGUnlimited;
import org.eclipse.ocl.examples.codegen.cgmodel.CGValuedElement;
import org.eclipse.ocl.examples.codegen.cgmodel.CGVariable;
import org.eclipse.ocl.examples.codegen.cgmodel.CGVariableExp;
import org.eclipse.ocl.examples.codegen.cgmodel.util.AbstractExtendingCGModelVisitor;
import org.eclipse.ocl.examples.codegen.generator.GenModelHelper;
import org.eclipse.ocl.examples.codegen.generator.TypeDescriptor;
import org.eclipse.ocl.examples.codegen.java.JavaStream.SubStream;
import org.eclipse.ocl.examples.codegen.java.operation.AndOperation2Handler;
import org.eclipse.ocl.examples.codegen.java.operation.AndOperationHandler;
import org.eclipse.ocl.examples.codegen.java.operation.ImpliesOperation2Handler;
import org.eclipse.ocl.examples.codegen.java.operation.ImpliesOperationHandler;
import org.eclipse.ocl.examples.codegen.java.operation.LibraryOperationHandler;
import org.eclipse.ocl.examples.codegen.java.operation.NotOperation2Handler;
import org.eclipse.ocl.examples.codegen.java.operation.NotOperationHandler;
import org.eclipse.ocl.examples.codegen.java.operation.OrOperation2Handler;
import org.eclipse.ocl.examples.codegen.java.operation.OrOperationHandler;
import org.eclipse.ocl.examples.codegen.java.operation.XorOperation2Handler;
import org.eclipse.ocl.examples.codegen.java.operation.XorOperationHandler;
import org.eclipse.ocl.examples.codegen.utilities.CGUtil;
import org.eclipse.ocl.pivot.CollectionLiteralExp;
import org.eclipse.ocl.pivot.Element;
import org.eclipse.ocl.pivot.Enumeration;
import org.eclipse.ocl.pivot.LanguageExpression;
import org.eclipse.ocl.pivot.LoopExp;
import org.eclipse.ocl.pivot.Operation;
import org.eclipse.ocl.pivot.OperationCallExp;
import org.eclipse.ocl.pivot.Parameter;
import org.eclipse.ocl.pivot.Property;
import org.eclipse.ocl.pivot.Type;
import org.eclipse.ocl.pivot.TypedElement;
import org.eclipse.ocl.pivot.Variable;
import org.eclipse.ocl.pivot.evaluation.Executor;
import org.eclipse.ocl.pivot.evaluation.IterationManager;
import org.eclipse.ocl.pivot.ids.ClassId;
import org.eclipse.ocl.pivot.ids.CollectionTypeId;
import org.eclipse.ocl.pivot.ids.ElementId;
import org.eclipse.ocl.pivot.ids.EnumerationId;
import org.eclipse.ocl.pivot.ids.EnumerationLiteralId;
import org.eclipse.ocl.pivot.ids.NestedTypeId;
import org.eclipse.ocl.pivot.ids.TuplePartId;
import org.eclipse.ocl.pivot.ids.TypeId;
import org.eclipse.ocl.pivot.internal.library.executor.AbstractDispatchOperation;
import org.eclipse.ocl.pivot.internal.library.executor.AbstractEvaluationOperation;
import org.eclipse.ocl.pivot.internal.library.executor.ExecutorMultipleIterationManager;
import org.eclipse.ocl.pivot.internal.library.executor.ExecutorMultipleMapIterationManager;
import org.eclipse.ocl.pivot.internal.library.executor.ExecutorSingleIterationManager;
import org.eclipse.ocl.pivot.internal.manager.PivotMetamodelManager;
import org.eclipse.ocl.pivot.internal.prettyprint.PrettyPrinter;
import org.eclipse.ocl.pivot.internal.utilities.EnvironmentFactoryInternal;
import org.eclipse.ocl.pivot.internal.values.IntIntegerValueImpl;
import org.eclipse.ocl.pivot.internal.values.LongIntegerValueImpl;
import org.eclipse.ocl.pivot.library.AbstractBinaryOperation;
import org.eclipse.ocl.pivot.library.AbstractSimpleOperation;
import org.eclipse.ocl.pivot.library.LibraryIteration;
import org.eclipse.ocl.pivot.library.LibraryOperation;
import org.eclipse.ocl.pivot.library.LibraryProperty;
import org.eclipse.ocl.pivot.library.LibrarySimpleOperation;
import org.eclipse.ocl.pivot.library.LibraryUntypedOperation;
import org.eclipse.ocl.pivot.library.oclany.OclElementOclContainerProperty;
import org.eclipse.ocl.pivot.oclstdlib.OCLstdlibPackage;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.ocl.pivot.utilities.ValueUtil;
import org.eclipse.ocl.pivot.values.CollectionValue;
import org.eclipse.ocl.pivot.values.InvalidValueException;
import org.eclipse.ocl.pivot.values.MapValue;
import org.eclipse.ocl.pivot.values.TemplateParameterSubstitutions;
import org.eclipse.ocl.pivot.values.TupleValue;
import com.google.common.collect.Iterables;
/**
* A CG2JavaVisitor serializes the contributions of a tree of model elements in a StringBuilder whose result may be
* obtained by toString() on completion.
*
* The individual visits contribute a complete construct, usually one or more statements to the output. However
* inlineable expressions contribute just their expression value.
*
* Visits return true if the generated flow of control flows out of the generated code,
* false if an unconditional exception is thrown.
*/
public abstract class CG2JavaVisitor<@NonNull CG extends JavaCodeGenerator> extends AbstractExtendingCGModelVisitor<@NonNull Boolean, CG>
{
protected class ArgumentSubStream implements SubStream
{
private final int argIndex;
protected ArgumentSubStream(int argIndex) {
this.argIndex = argIndex;
}
@Override
public void append() {
js.append(JavaConstants.SOURCE_AND_ARGUMENT_VALUES_NAME);
js.append("[" + argIndex);
js.append("]");
}
}
protected final @NonNull JavaGlobalContext<@NonNull ?> globalContext;
protected final @NonNull GenModelHelper genModelHelper;
protected final @NonNull CodeGenAnalyzer analyzer;
protected final @NonNull EnvironmentFactoryInternal environmentFactory;
protected final @NonNull Id2JavaInterfaceVisitor id2JavaInterfaceVisitor;
protected final @NonNull JavaStream js;
protected final @NonNull Map<@NonNull Class<? extends LibraryOperation>, @NonNull LibraryOperationHandler> libraryOperation2handler = new HashMap<>();;
/**
* The local Java context for the current operation.
*/
protected JavaLocalContext<@NonNull ?> localContext;
public CG2JavaVisitor(@NonNull CG codeGenerator) {
super(codeGenerator);
this.globalContext = codeGenerator.getGlobalContext();
this.genModelHelper = context.getGenModelHelper();
this.analyzer = context.getAnalyzer();
this.id2JavaInterfaceVisitor = createId2JavaClassVisitor();
this.environmentFactory = analyzer.getCodeGenerator().getEnvironmentFactory();
this.js = codeGenerator.createJavaStream(this);
installLibraryHandler(new AndOperationHandler(js));
installLibraryHandler(new AndOperation2Handler(js));
installLibraryHandler(new ImpliesOperationHandler(js));
installLibraryHandler(new ImpliesOperation2Handler(js));
installLibraryHandler(new NotOperationHandler(js));
installLibraryHandler(new NotOperation2Handler(js));
installLibraryHandler(new OrOperationHandler(js));
installLibraryHandler(new OrOperation2Handler(js));
installLibraryHandler(new XorOperationHandler(js));
installLibraryHandler(new XorOperation2Handler(js));
}
protected void installLibraryHandler(@NonNull LibraryOperationHandler libraryOperationHandler) {
libraryOperation2handler.put(libraryOperationHandler.getLibraryOperationClass(), libraryOperationHandler);
}
protected @NonNull String addImport(@Nullable Boolean isRequired, @NonNull String className) {
return globalContext.addImport(isRequired, className);
}
/**
* Append the code for an EcorePropertyCall. If source is null, the code for the source will also be appended.
* If source is non-null the caller has already appended it.
*/
protected @NonNull Boolean appendCGEcorePropertyCallExp(@NonNull CGEcorePropertyCallExp cgPropertyCallExp, @Nullable CGValuedElement source) {
Property asProperty = ClassUtil.nonNullState(cgPropertyCallExp.getReferredProperty());
assert getESObject(asProperty) == ClassUtil.nonNullState(cgPropertyCallExp.getEStructuralFeature());
//
if (source == null) {
source = getExpression(cgPropertyCallExp.getSource());
if (!js.appendLocalStatements(source)) {
return false;
}
}
//
Boolean ecoreIsRequired = context.isNonNull(asProperty);
boolean isPrimitive = js.isPrimitive(cgPropertyCallExp);
if (!isPrimitive) appendSuppressWarningsNull(cgPropertyCallExp, ecoreIsRequired);
// js.append("/* " + ecoreIsRequired + " " + isRequired + " */\n");
js.appendDeclaration(cgPropertyCallExp);
js.append(" = ");
appendEcoreGet(source, asProperty);
js.append(";\n");
return true;
}
protected void appendEcoreGet(@NonNull CGValuedElement cgSource, @NonNull Property asProperty) {
CGTypeId cgTypeId = analyzer.getTypeId(asProperty.getOwningClass().getTypeId());
ElementId elementId = ClassUtil.nonNullState(cgTypeId.getElementId());
TypeDescriptor requiredTypeDescriptor = context.getUnboxedDescriptor(elementId);
// EStructuralFeature eStructuralFeature = ClassUtil.nonNullState(cgPropertyCallExp.getEStructuralFeature());
EStructuralFeature eStructuralFeature = ClassUtil.nonNullState(getESObject(asProperty));
String getAccessor;
if (eStructuralFeature == OCLstdlibPackage.Literals.OCL_ELEMENT__OCL_CONTAINER) {
getAccessor = JavaConstants.E_CONTAINER_NAME;
}
else {
getAccessor = genModelHelper.getGetAccessor(eStructuralFeature);
}
Class<?> requiredJavaClass = requiredTypeDescriptor.hasJavaClass();
Method leastDerivedMethod = requiredJavaClass != null ? context.getLeastDerivedMethod(requiredJavaClass, getAccessor) : null;
Class<?> unboxedSourceClass;
if (leastDerivedMethod != null) {
unboxedSourceClass = leastDerivedMethod.getDeclaringClass();
}
else {
unboxedSourceClass = requiredJavaClass;
}
if ((unboxedSourceClass != null) && (unboxedSourceClass != Object.class)) {
js.appendAtomicReferenceTo(unboxedSourceClass, cgSource);
}
else {
js.appendAtomicReferenceTo(cgSource);
}
js.append(".");
js.append(getAccessor);
js.append("()");
}
protected void appendGlobalPrefix() {}
protected void appendGuardFailure(@NonNull CGGuardExp cgGuardExp) {
js.append("throw new ");
js.appendClassReference(null, InvalidValueException.class);
js.append("(");
js.appendString("Null " + cgGuardExp.getMessage());
js.append(");\n");
}
protected @NonNull Boolean appendLoopCall(@NonNull CGLibraryIterationCallExp cgIterationCallExp, @Nullable CGIterator iterateResult) {
final CGValuedElement source = getExpression(cgIterationCallExp.getSource());
final List<@NonNull CGIterator> iterators = CGUtil.getIteratorsList(cgIterationCallExp);
final List<@NonNull CGIterator> coIterators = CGUtil.getCoIteratorsList(cgIterationCallExp);
final CGValuedElement body = getExpression(cgIterationCallExp.getBody());
final CGTypeId resultType = cgIterationCallExp.getTypeId();
final Operation referredOperation = ((LoopExp)cgIterationCallExp.getAst()).getReferredIteration();
final int arity = iterators.size();
boolean isMap = coIterators.size() > 0;
final Class<?> managerClass; // FIXME ExecutorMultipleIterationManager
final Class<?> operationClass;
if (isMap) {
managerClass = ExecutorMultipleMapIterationManager.class;
operationClass = AbstractSimpleOperation.class;
}
else if (arity == 1) {
managerClass = ExecutorSingleIterationManager.class;
operationClass = AbstractBinaryOperation.class;
}
else {
managerClass = ExecutorMultipleIterationManager.class;
operationClass = AbstractSimpleOperation.class;
}
final LibraryIteration libraryIteration = ClassUtil.nonNullState(cgIterationCallExp.getLibraryIteration());
final Method actualMethod = getJavaMethod(libraryIteration);
final Class<?> actualReturnClass = actualMethod != null ? actualMethod.getReturnType() : null;
boolean actualIsNonNull = (actualMethod != null) && (context.getIsNonNull(actualMethod) == Boolean.TRUE);
boolean expectedIsNonNull = cgIterationCallExp.isNonNull();
final String astName = getSymbolName(null, cgIterationCallExp.getValueName());
final String bodyName = getSymbolName(null, "BODY_" + astName);
final String implementationName = getSymbolName(null, "IMPL_" + astName);
final String managerName = getSymbolName(null, "MGR_" + astName);
final String staticTypeName = getSymbolName(null, "TYPE_" + astName);
String accumulatorName;
//
// Pre-amble: hoisted assignments
//
if (!js.appendLocalStatements(source)) {
return false;
}
//
// Dispatch: Determine static type
//
js.append("final ");
js.appendClassReference(true, org.eclipse.ocl.pivot.Class.class);
js.append(" " + staticTypeName + " = ");
// js.appendReferenceTo(evaluatorParameter);
js.append(JavaConstants.EXECUTOR_NAME);
js.append(".getStaticTypeOfValue(null, ");
js.appendValueName(source);
js.append(");\n");
//
// Dispatch: Determine dynamic operation
//
js.append("final ");
js.appendClassReference(true, LibraryIteration.LibraryIterationExtension.class);
js.append(" " + implementationName + " = (");
js.appendClassReference(null, LibraryIteration.LibraryIterationExtension.class);
js.append( ")" + staticTypeName + ".lookupImplementation(");
js.appendReferenceTo(localContext.getStandardLibraryVariable(cgIterationCallExp));
js.append(", ");
js.appendQualifiedLiteralName(ClassUtil.nonNullState(referredOperation));
js.append(");\n");
//
if (iterateResult != null) {
CGValuedElement init = iterateResult.getInit();
accumulatorName = getSymbolName(null, init.getValueName());
if (!js.appendLocalStatements(init)) {
return false;
}
js.appendDeclaration(iterateResult);
js.append(" = ");
js.appendValueName(init);
js.append(";\n");
//
/* js.append("Object " + accumulatorName + " = " + implementationName + ".createAccumulatorValue(");
// js.appendValueName(evaluatorParameter);
js.append(JavaConstants.EVALUATOR_NAME);
js.append(", ");
js.appendValueName(resultType);
js.append(", ");
js.appendValueName(body.getTypeId());
js.append(");\n"); */
}
else {
accumulatorName = "ACC_" + astName;
js.append("final ");
js.appendIsRequired(true);
js.append(" Object " + accumulatorName + " = " + implementationName + ".createAccumulatorValue(");
// js.appendValueName(evaluatorParameter);
js.append(JavaConstants.EXECUTOR_NAME);
js.append(", ");
js.appendValueName(resultType);
js.append(", ");
js.appendValueName(body.getTypeId());
js.append(");\n");
}
//
js.append("/**\n");
js.append(" * Implementation of the iterator body.\n");
js.append(" */\n");
js.append("final ");
js.appendClassReference(true, operationClass);
js.append(" " + bodyName + " = new ");
js.appendClassReference(null, operationClass);
js.append("()");
js.pushClassBody(String.valueOf(operationClass));
js.appendCommentWithOCL(null, body.getAst());
js.append("@Override\n");
js.append("public ");
js.appendIsRequired(false);
js.append(" Object evaluate(");
js.append("final ");
// js.appendDeclaration(evaluatorParameter);
js.appendClassReference(true, Executor.class);
js.append(" ");
js.append(JavaConstants.EXECUTOR_NAME);
js.append(", ");
js.append("final ");
// js.appendDeclaration(localContext.getTypeIdParameter(cgIterateCallExp));
js.appendClassReference(true, TypeId.class);
js.append(" ");
js.append(JavaConstants.TYPE_ID_NAME);
if (isMap || (arity > 1)) {
js.append(", final ");
js.appendIsRequired(false);
js.append(" Object ");
js.appendIsRequired(true);
js.append(" [] ");
js.append(JavaConstants.SOURCE_AND_ARGUMENT_VALUES_NAME);
}
else {
if (iterateResult != null) {
js.append(", ");
js.appendDeclaration(iterateResult);
}
else {
js.append(", final ");
js.appendIsRequired(false);
js.append(" Object ");
js.appendValueName(source);
// js.appendDeclaration(source);
}
for (int i = 0; i < arity; i++) {
CGIterator iterator = iterators.get(i);
js.append(", final ");
js.appendDeclaration(iterator);
if (i < coIterators.size()) {
js.append(", final ");
js.appendDeclaration(coIterators.get(i));
}
}
}
js.append(") {\n");
js.pushIndentation(null);
if (isMap || (arity > 1)) {
int argIndex = 0; // Skip source
Boolean isRequired = context.isRequired(source);
if (isRequired == Boolean.TRUE) {
js.appendSuppressWarningsNull(true);
}
js.append("final ");
js.appendTypeDeclaration(source);
js.append(" ");
js.appendValueName(source);
js.append(" = ");
js.appendClassCast(source, isRequired, Object.class, new ArgumentSubStream(argIndex));
js.append(";\n");
argIndex++;
for (int i = 0; i < arity; i++) {
CGParameter iterator = iterators.get(i);
isRequired = context.isRequired(iterator);
if (isRequired == Boolean.TRUE) {
js.appendSuppressWarningsNull(true);
}
js.append("final ");
js.appendDeclaration(iterator);
js.append(" = ");
js.appendClassCast(iterator, isRequired, Object.class, new ArgumentSubStream(argIndex));
js.append(";\n");
argIndex++;
if (i < coIterators.size()) {
CGIterator coIterator = coIterators.get(i);
Variable asCoIterator = CGUtil.getAST(coIterator);
if (!asCoIterator.isIsImplicit()) {
isRequired = context.isRequired(coIterator);
if (isRequired == Boolean.TRUE) {
js.appendSuppressWarningsNull(true);
}
js.append("final ");
js.appendDeclaration(coIterator);
js.append(" = ");
js.appendClassCast(coIterator, isRequired, Object.class, new ArgumentSubStream(argIndex));
js.append(";\n");
}
argIndex++;
}
}
}
JavaLocalContext<@NonNull ?> savedLocalContext = localContext;
try {
localContext = globalContext.getLocalContext(cgIterationCallExp);
appendReturn(body);
}
finally {
localContext = savedLocalContext;
}
js.popIndentation();
js.append("}\n");
js.popClassBody(true);
//
// Dispatch: Create execution manager
//
js.append("final ");
js.appendClassReference(true, managerClass);
js.append(" " + managerName + " = new ");
js.appendClassReference(null, managerClass);
js.append("(");
// js.appendReferenceTo(evaluatorParameter);
js.append(JavaConstants.EXECUTOR_NAME);
js.append(", ");
if (isMap || (arity > 1)) {
js.append(arity + ", ");
}
js.appendValueName(resultType);
js.append(", " + bodyName + ", ");
js.appendReferenceTo(isMap ? MapValue.class : CollectionValue.class, source);
// js.appendValueName(source);
js.append(", " + accumulatorName + ");\n");
//
// Dispatch: Invoke iteration
//
boolean isRequiredNullCast = expectedIsNonNull && !actualIsNonNull;
if (isRequiredNullCast) {
js.appendSuppressWarningsNull(true);
}
js.appendDeclaration(cgIterationCallExp);
js.append(" = ");
// if (isRequiredNullCast) {
// js.appendClassReference(null, ClassUtil.class);
// js.append(".nonNullState(");
// }
SubStream castBody4 = new SubStream() {
@Override
public void append() {
js.append(implementationName + ".evaluateIteration(" + managerName + ")");
// if (isRequiredNullCast) {
// js.append(")");
// }
}
};
js.appendClassCast(cgIterationCallExp, isRequiredNullCast, actualReturnClass, castBody4);
js.append(";\n");
return true;
}
protected void appendReturn(@NonNull CGValuedElement body) {
if (js.appendLocalStatements(body)) {
if (body instanceof CGThrowExp) { // FIXME generalize
body.accept(this);
}
else {
CGInvalid cgInvalidValue = body.getInvalidValue();
if (cgInvalidValue != null) {
js.append("throw ");
js.appendValueName(cgInvalidValue);
}
else {
js.append("return ");
js.appendValueName(body);
}
js.append(";\n");
}
}
}
protected void appendSuppressWarningsNull(@NonNull CGValuedElement cgActual, Boolean isNonNull) {
boolean isRequired = cgActual.isNonNull();
boolean isPrimitive = js.isPrimitive(cgActual);
if (!isPrimitive && isRequired && (isNonNull != Boolean.TRUE)) {
js.appendSuppressWarningsNull(true);
}
}
protected @NonNull Id2JavaInterfaceVisitor createId2JavaClassVisitor() {
return new Id2JavaInterfaceVisitor();
}
protected @NonNull Id2JavaExpressionVisitor createId2JavaExpressionVisitor(@NonNull JavaStream javaStream) {
return new Id2JavaExpressionVisitor(javaStream);
}
protected boolean doClassFields(@NonNull CGClass cgClass, boolean needsBlankLine) {
if (cgClass.getProperties().size() > 0) {
if (needsBlankLine) {
js.append("\n");
}
for (CGProperty cgProperty : cgClass.getProperties()) {
cgProperty.accept(this);
}
needsBlankLine = true;
}
return needsBlankLine;
}
protected void doCachedOperationDispatchInstaller(@NonNull CGCachedOperation cgOperation) {
js.append("private ");
js.append(getNativeOperationClassName(cgOperation));
js.append("() {\n");
js.pushIndentation(null);
for (@NonNull CGCachedOperation cgFinalOperation : ClassUtil.nullFree(cgOperation.getFinalOperations())) {
Operation asFinalOperation = (Operation)cgFinalOperation.getAst();
assert asFinalOperation != null;
js.append("install(");
js.appendClassReference(null, cgFinalOperation.getParameters().get(0));
js.append(".class, ");
js.append(getNativeOperationDirectInstanceName(asFinalOperation));
js.append(");\n");
}
js.popIndentation();
js.append("}\n");
}
protected void doCachedOperationBasicEvaluate(@NonNull CGOperation cgOperation) {
List<@NonNull CGParameter> cgParameters = ClassUtil.nullFree(cgOperation.getParameters());
CGValuedElement body = getExpression(cgOperation.getBody());
js.append("@Override\n");
js.append("public ");
// boolean cgOperationIsInvalid = cgOperation.getInvalidValue() != null;
// js.appendIsCaught(!cgOperationIsInvalid, cgOperationIsInvalid);
js.appendClassReference(false, Object.class);
js.append(" basicEvaluate(");
js.appendClassReference(true, Executor.class);
js.append(" ");
js.append(JavaConstants.EXECUTOR_NAME);
js.append(", ");
js.appendClassReference(true, TypedElement.class);
js.append(" ");
js.append("caller");
js.append(", ");
js.appendClassReference(false, Object.class);
js.append(" ");
js.appendIsRequired(true);
js.append(" [] ");
js.append(JavaConstants.SOURCE_AND_ARGUMENT_VALUES_NAME);
js.append(") {\n");
js.pushIndentation(null);
int i = 0;
for (@NonNull CGParameter cgParameter : cgParameters) {
if (cgParameter.getASTypeId() instanceof CollectionTypeId) {
js.append("@SuppressWarnings(\"unchecked\") ");
}
else if (cgParameter.isRequired()) {
if (js.appendSuppressWarningsNull(false)) {
js.append(" ");
}
}
js.appendDeclaration(cgParameter);
js.append(" = (");
js.appendTypeDeclaration(cgParameter);
js.append(")");
js.append(JavaConstants.SOURCE_AND_ARGUMENT_VALUES_NAME);
js.append("[" + i++ + "];\n");
}
appendReturn(body);
js.popIndentation();
js.append("}\n");
}
protected void doCachedOperationClassDirectInstance(@NonNull CGOperation cgOperation) {
Operation asOperation = (Operation) cgOperation.getAst();
assert asOperation != null;
String name = getNativeOperationClassName(cgOperation);
js.append("protected final ");
js.appendIsRequired(true);
js.append(" ");
js.append(name);
js.append(" ");
js.append(getNativeOperationDirectInstanceName(asOperation));
js.append(" = new ");
js.append(name);
js.append("();\n");
}
protected void doCachedOperationClassInstance(@NonNull CGOperation cgOperation) {
Operation asOperation = (Operation) cgOperation.getAst();
assert asOperation != null;
String name = getNativeOperationClassName(cgOperation);
js.append("protected final ");
js.appendIsRequired(true);
js.append(" ");
js.append(name);
js.append(" ");
js.append(getNativeOperationInstanceName(asOperation));
js.append(" = new ");
js.append(name);
js.append("();\n");
}
protected void doCachedOperationEvaluate(@NonNull CGOperation cgOperation) {
List<@NonNull CGParameter> cgParameters = ClassUtil.nullFree(cgOperation.getParameters());
Boolean isRequiredReturn = cgOperation.isRequired() ? true : null;
if (cgOperation.isEcore() && (cgOperation.getASTypeId() instanceof CollectionTypeId)) {
js.append("@SuppressWarnings(\"unchecked\")\n");
}
else if ((isRequiredReturn == Boolean.TRUE)) {
js.appendSuppressWarningsNull(true);
}
js.append("public ");
// boolean cgOperationIsInvalid = cgOperation.getInvalidValue() != null;
// js.appendIsCaught(!cgOperationIsInvalid, cgOperationIsInvalid);
// js.append(" ");
js.appendClassReference(isRequiredReturn, cgOperation);
js.append(" evaluate(");
boolean isFirst = true;
for (@NonNull CGParameter cgParameter : cgParameters) {
if (!isFirst) {
js.append(", ");
}
js.appendDeclaration(cgParameter);
isFirst = false;
}
js.append(") {\n");
js.pushIndentation(null);
js.append("return (");
js.appendClassReference(isRequiredReturn, cgOperation);
js.append(")");
js.append(JavaConstants.EVALUATION_CACHE_NAME);
js.append(".getCachedEvaluationResult(this, caller, new ");
js.appendClassReference(false, Object.class);
js.append("[]{");
isFirst = true;
for (@NonNull CGParameter cgParameter : cgParameters) {
if (!isFirst) {
js.append(", ");
}
js.appendValueName(cgParameter);
isFirst = false;
}
js.append("});\n");
js.popIndentation();
js.append("}\n");
}
protected boolean doClassMethods(@NonNull CGClass cgClass, boolean needsBlankLine) {
for (CGOperation cgOperation : cgClass.getOperations()) {
if (needsBlankLine) {
js.append("\n");
}
cgOperation.accept(this);
needsBlankLine = true;
}
return needsBlankLine;
}
protected boolean doClassStatics(@NonNull CGClass cgClass, boolean needsBlankLine) {
return needsBlankLine;
}
protected boolean doNestedClasses(@NonNull CGClass cgClass, boolean needsBlankLine) {
for (CGClass cgNestedClass : cgClass.getClasses()) {
if (needsBlankLine) {
js.append("\n");
}
cgNestedClass.accept(this);
needsBlankLine = true;
}
return needsBlankLine;
}
public void generateGlobals(@NonNull Iterable<@NonNull ? extends CGValuedElement> sortedElements) {
for (@NonNull CGValuedElement cgElement : sortedElements) {
cgElement.accept(this);
}
}
@Deprecated /* deprecated use getImportManager */
public @NonNull Set<String> getAllImports() {
return getImportNameManager().getLong2ShortImportNames().keySet();
}
public @NonNull CodeGenAnalyzer getAnalyzer() {
return analyzer;
}
public @NonNull CG getCodeGenerator() {
return context;
}
protected @Nullable EStructuralFeature getESObject(@NonNull Property asProperty) {
EObject esObject = asProperty.getESObject();
if (esObject instanceof EStructuralFeature) {
return (EStructuralFeature)esObject;
}
Property oppositeProperty = asProperty.getOpposite();
if (oppositeProperty == null) {
return null;
}
if (!oppositeProperty.isIsComposite()) {
LibraryProperty libraryProperty = environmentFactory.getMetamodelManager().getImplementation(null, null, asProperty);
if (!(libraryProperty instanceof OclElementOclContainerProperty)) {
return null;
}
}
return OCLstdlibPackage.Literals.OCL_ELEMENT__OCL_CONTAINER;
}
public @NonNull CGValuedElement getExpression(@Nullable CGValuedElement cgExpression) {
return analyzer.getExpression(cgExpression);
}
public @NonNull GenModelHelper getGenModelHelper() {
return genModelHelper;
}
public @NonNull ImportNameManager getImportNameManager() {
return globalContext.getImportNameManager();
}
private Method getJavaMethod(@NonNull LibraryIteration libraryIteration) {
try {
Class<? extends LibraryIteration> implementationClass = libraryIteration.getClass();
Method method = implementationClass.getMethod("evaluateIteration", IterationManager.class);
return method;
} catch (Exception e) {
return null;
}
}
private Method getJavaMethod(@NonNull LibraryOperation libraryOperation, int argumentSize) {
try {
Class<? extends LibraryOperation> implementationClass = libraryOperation.getClass();
Class<?>[] arguments;
int i = 0;
if (libraryOperation instanceof LibrarySimpleOperation) {
arguments = new Class<?>[argumentSize+1];
}
else if (libraryOperation instanceof LibraryUntypedOperation) {
arguments = new Class<?>[argumentSize+2];
arguments[i++] = Executor.class;
}
else {
arguments = new Class<?>[argumentSize+3];
arguments[i++] = Executor.class;
arguments[i++] = TypeId.class;
}
while (i < arguments.length) {
arguments[i++] = Object.class;
}
Method method = implementationClass.getMethod("evaluate", arguments);
return method;
} catch (Exception e) {
return null;
}
}
private Method getJavaMethod(@NonNull LibraryProperty libraryProperty) {
try {
Class<? extends LibraryProperty> implementationClass = libraryProperty.getClass();
Class<?>@NonNull [] arguments = new Class<?>@NonNull [3];
arguments[0] = Executor.class;
arguments[1] = TypeId.class;
arguments[2] = Object.class;
Method method = implementationClass.getMethod("evaluate", arguments);
return method;
} catch (Exception e) {
return null;
}
}
protected @Nullable Class<?> getLeastDerivedClass(Class<?> requiredClass, @NonNull String getAccessor) {
Class<?> superClass = requiredClass.getSuperclass();
if (superClass != null) {
try {
Class<?> lessDerivedSuperClass = getLeastDerivedClass(superClass, getAccessor);
if (lessDerivedSuperClass != null) {
return lessDerivedSuperClass;
}
Method method = superClass.getMethod(getAccessor);
if (method != null) {
return superClass;
}
} catch (Exception e) {
}
}
for (Class<?> superInterface : requiredClass.getInterfaces()) {
Class<?> lessDerivedSuperInterface = getLeastDerivedClass(superInterface, getAccessor);
if (lessDerivedSuperInterface != null) {
return lessDerivedSuperInterface;
}
try {
Method method = superInterface.getMethod(getAccessor);
if (method != null) {
return superInterface;
}
} catch (Exception e) {
}
}
return null;
}
protected @NonNull String getNativeOperationClassName(@NonNull CGOperation cgOperation) { // FIXME unique
Operation asOperation = (Operation) cgOperation.getAst();
assert asOperation != null;
if (isVirtualDispatcher(cgOperation)) {
return "VCACHE_" + getNativeOperationName(asOperation);
}
else {
return "CACHE_" + getNativeOperationName(asOperation);
}
}
protected @NonNull String getNativeOperationDirectInstanceName(@NonNull Operation asOperation) { // FIXME unique
return "INST_" + getNativeOperationName(asOperation);
}
protected @NonNull String getNativeOperationInstanceName(@NonNull Operation asOperation) { // FIXME unique
return "INSTANCE_" + getNativeOperationName(asOperation);
}
protected @NonNull String getNativeOperationName(@NonNull Operation asOperation) { // FIXME unique
return ClassUtil.nonNullState(asOperation.getOwningClass()).getName() + "_" + asOperation.getName();
}
protected @NonNull String getSymbolName(@Nullable Object anObject, @Nullable String... nameHints) {
return localContext.getNameManagerContext().getSymbolName(anObject, nameHints);
}
@Deprecated /* @deprecated this is QVTi specific */
protected @NonNull String getThisName(@NonNull CGElement cgElement) {
for (EObject eObject = cgElement; eObject != null; eObject = eObject.eContainer()) {
if (eObject instanceof CGClass) {
return ClassUtil.nonNullState(((CGClass)eObject).getName());
}
}
assert false;
return "";
}
protected String getValueName(@NonNull CGValuedElement cgElement) {
String valueName = localContext != null ? localContext.getValueName(cgElement) : globalContext.getValueName(cgElement);
return valueName;
}
protected boolean isBoxedElement(@NonNull CGValuedElement cgValue) {
TypeId typeId = cgValue.getASTypeId();
if (typeId instanceof EnumerationLiteralId) {
return true;
}
if (typeId instanceof EnumerationId) {
return true;
}
if (typeId instanceof ClassId) {
return true;
}
return false;
}
protected boolean isBoxedType2(@NonNull CGValuedElement cgValue) {
TypeId typeId = cgValue.getASTypeId();
if (typeId instanceof NestedTypeId) {
return true;
}
return false;
}
protected boolean isBoxedType(@NonNull CGValuedElement cgValue) {
Element ast = cgValue.getAst();
if (!(ast instanceof TypedElement)) {
return false;
}
Type type = ((TypedElement)ast).getType();
if (type == null) {
return false;
}
if (type instanceof Enumeration) {
return false;
}
PivotMetamodelManager metamodelManager = context.getEnvironmentFactory().getMetamodelManager();
Type oclTypeType = environmentFactory.getStandardLibrary().getOclTypeType();
return metamodelManager.conformsTo(type, TemplateParameterSubstitutions.EMPTY, oclTypeType, TemplateParameterSubstitutions.EMPTY);
}
protected boolean isEnumerationLiteral(@NonNull CGValuedElement cgValue) {
Element ast = cgValue.getAst();
if (!(ast instanceof TypedElement)) {
return false;
}
Type type = ((TypedElement)ast).getType();
return type instanceof Enumeration;
}
protected boolean isVirtualDispatcher(@NonNull CGOperation cgOperation) {
return (cgOperation instanceof CGCachedOperation) && (((CGCachedOperation)cgOperation).getFinalOperations().size() > 0);
}
@Override
public @NonNull String toString() {
String string = js.toString();
return string;
}
@Override
public @NonNull Boolean visiting(@NonNull CGElement visitable) {
throw new UnsupportedOperationException(getClass().getSimpleName() + ": " + visitable.getClass().getSimpleName());
}
@Override
public @NonNull Boolean visitCGAssertNonNullExp(@NonNull CGAssertNonNullExp cgAssertNonNullExp) {
CGValuedElement cgSource = getExpression(cgAssertNonNullExp.getSource());
//
if (cgSource.isNull()) {
js.append("throw new ");
js.appendClassReference(null, InvalidValueException.class);
js.append("();\n");
}
else {
if (!js.appendLocalStatements(cgSource)) {
return false;
}
if (!cgSource.isNonNull()) {
js.append("assert ");
js.appendValueName(cgSource);
js.append(" != null;\n");
}
}
return true;
}
@Override
public @NonNull Boolean visitCGBoolean(@NonNull CGBoolean cgBoolean) {
boolean booleanValue = cgBoolean.isBooleanValue();
if (booleanValue) {
js.appendTrue();
}
else {
js.appendFalse();
}
return true;
}
@Override
public @NonNull Boolean visitCGBoxExp(@NonNull CGBoxExp cgBoxExp) {
CGValuedElement unboxedValue = getExpression(cgBoxExp.getSource());
TypeDescriptor unboxedTypeDescriptor = context.getTypeDescriptor(unboxedValue);
JavaLocalContext<@NonNull ?>localContext2 = localContext;
assert localContext2 != null;
//
if (!js.appendLocalStatements(unboxedValue)) {
return false;
}
return unboxedTypeDescriptor.appendBox(js, localContext2, cgBoxExp, unboxedValue);
}
@Override
public @NonNull Boolean visitCGBuiltInIterationCallExp(@NonNull CGBuiltInIterationCallExp cgIterationCallExp) {
CGValuedElement cgSource = getExpression(cgIterationCallExp.getSource());
CGValuedElement cgBody = getExpression(cgIterationCallExp.getBody());
CGIterator cgAccumulator = cgIterationCallExp.getAccumulator();
CGIterator cgIterator = cgIterationCallExp.getIterators().get(0);
CGIterator cgCoIterator = cgIterationCallExp.getCoIterators().size() > 0 ? cgIterationCallExp.getCoIterators().get(0) : null;
String iteratorName = getSymbolName(null, "ITERATOR_" + cgIterator.getValueName());
Iteration2Java iterationHelper = context.getIterationHelper(ClassUtil.nonNullState(cgIterationCallExp.getReferredIteration()));
assert iterationHelper != null;
boolean flowContinues = false;
//
if (!js.appendLocalStatements(cgSource)) {
return false;
}
//
// Declare and initialize accumulator
//
if (cgAccumulator != null) {
CGValuedElement cgInit = cgAccumulator.getInit();
if (cgInit != null) {
if (!js.appendLocalStatements(cgInit)) {
return false;
}
}
cgAccumulator.toString();
js.appendDeclaration(cgAccumulator);
js.append(" = ");
iterationHelper.appendAccumulatorInit(js, cgIterationCallExp);
js.append(";\n");
}
//
// Declare iterator
//
js.appendClassReference(cgIterator.isRequired(), Iterator.class, false, Object.class); //, getJavaClass(cgIterator));
js.append(" " + iteratorName + " = ");
js.appendAtomicReferenceTo(cgSource);
js.append(".iterator();\n");
//
// Declare body result
//
js.appendDeclaration(cgIterationCallExp);
js.append(";\n");
//
// Declare loop head
//
js.append("while (true) {\n");
js.pushIndentation(null);
//
// Terminate loop once done
//
js.append("if (!" + iteratorName + ".hasNext()) {\n");
js.pushIndentation(null);
if (iterationHelper.appendFinalValue(js, cgIterationCallExp)) {
js.append("break;\n");
flowContinues = true;
}
js.popIndentation();
js.append("}\n");
//
// Declare iterator advance.
//
appendSuppressWarningsNull(cgIterator, Boolean.FALSE);
js.appendDeclaration(cgIterator);
js.append(" = ");
SubStream castBody1 = new SubStream() {
@Override
public void append() {
js.append(iteratorName + ".next()");
}
};
js.appendClassCast(cgIterator, castBody1);
js.append(";\n");
//
// Declare coiterator/key access.
//
if (cgCoIterator != null) { // && !isImplicit
Variable asCoIterator = CGUtil.getAST(cgCoIterator);
if (!asCoIterator.isIsImplicit()) {
if (cgCoIterator.isRequired()) {
js.appendSuppressWarningsNull(true);
}
js.appendDeclaration(cgCoIterator);
js.append(" = ");
SubStream castBody2 = new SubStream() {
@Override
public void append() {
js.appendReferenceTo(cgSource);
js.append(".at(");
js.appendReferenceTo(cgIterator);
js.append(")");
}
};
js.appendClassCast(cgCoIterator, castBody2);
js.append(";\n");
}
}
//
// Declare iteration body.
//
js.appendCommentWithOCL(null, cgBody.getAst());
if (js.appendLocalStatements(cgBody)) {
js.append("//\n");
if (iterationHelper.appendUpdate(js, cgIterationCallExp)) {
flowContinues = true;
}
}
//
// Declare loop tail
//
js.popIndentation();
js.append("}\n");
return flowContinues;
}
@Override
public @NonNull Boolean visitCGCastExp(@NonNull CGCastExp cgCastExp) {
CGValuedElement cgSource = getExpression(cgCastExp.getSource());
CGExecutorType cgType = cgCastExp.getExecutorType();
if (cgType != null) {
TypeDescriptor typeDescriptor = context.getTypeDescriptor(cgCastExp);
js.appendDeclaration(cgCastExp);
js.append(" = ");
typeDescriptor.appendCastTerm(js, cgSource);
js.append(";\n");
}
return true;
}
@Override
public @NonNull Boolean visitCGCachedOperation(@NonNull CGCachedOperation cgOperation) {
Operation asOperation = (Operation) cgOperation.getAst();
assert asOperation != null;
JavaLocalContext<@NonNull ?> localContext2 = globalContext.getLocalContext(cgOperation);
if (localContext2 != null) {
localContext = localContext2;
boolean isVirtualDispatcher = isVirtualDispatcher(cgOperation);
try {
String operationClassName = getNativeOperationClassName(cgOperation);
if (isVirtualDispatcher) {
js.append("protected class ");
js.append(operationClassName);
js.append(" extends ");
js.appendClassReference(null, AbstractDispatchOperation.class);
js.pushClassBody(operationClassName);
doCachedOperationDispatchInstaller(cgOperation);
js.append("\n");
doCachedOperationEvaluate(cgOperation);
js.popClassBody(false);
//
js.append("\n");
doCachedOperationClassInstance(cgOperation);
}
else {
LanguageExpression expressionInOCL = asOperation.getBodyExpression();
String title = PrettyPrinter.printName(asOperation);
js.appendCommentWithOCL(title+"\n", expressionInOCL);
//
js.append("public class ");
js.append(operationClassName);
js.append(" extends ");
js.appendClassReference(null, AbstractEvaluationOperation.class);
js.pushClassBody(operationClassName);
doCachedOperationBasicEvaluate(cgOperation);
js.append("\n");
doCachedOperationEvaluate(cgOperation);
js.popClassBody(false);
//
if (cgOperation.getVirtualOperations().size() <= 0) {
js.append("\n");
doCachedOperationClassInstance(cgOperation);
}
else {
js.append("\n");
doCachedOperationClassDirectInstance(cgOperation);
}
}
}
finally {
localContext = null;
}
}
return true;
}
@Override
public @NonNull Boolean visitCGCachedOperationCallExp(@NonNull CGCachedOperationCallExp cgOperationCallExp) {
Operation pOperation = cgOperationCallExp.getReferredOperation();
boolean thisIsSelf = cgOperationCallExp.isThisIsSelf();
CGValuedElement source = getExpression(cgOperationCallExp.getSource());
List<CGValuedElement> cgArguments = cgOperationCallExp.getArguments();
List<Parameter> pParameters = pOperation.getOwnedParameters();
//
if (!js.appendLocalStatements(source)) {
return false;
}
for (@SuppressWarnings("null")@NonNull CGValuedElement cgArgument : cgArguments) {
CGValuedElement argument = getExpression(cgArgument);
if (!js.appendLocalStatements(argument)) {
return false;
}
}
//
js.appendDeclaration(cgOperationCallExp);
js.append(" = ");
// js.appendClassCast(cgOperationCallExp);
/* if (thisIsSelf) {
js.appendValueName(source);
}
else {
if (localPrefix != null) {
js.append(localPrefix);
js.append(".");
}
js.append("this");
} */
js.append(getNativeOperationInstanceName(pOperation));
js.append(".evaluate");
// js.append(cgOperationCallExp.getReferredOperation().getName());
js.append("(");
if (!thisIsSelf) {
js.appendValueName(source);
}
int iMax = Math.min(pParameters.size(), cgArguments.size());
for (int i = 0; i < iMax; i++) {
if ((i > 0) || !thisIsSelf) {
js.append(", ");
}
CGValuedElement cgArgument = cgArguments.get(i);
Parameter pParameter = pParameters.get(i);
CGTypeId cgTypeId = analyzer.getTypeId(pParameter.getTypeId());
TypeDescriptor parameterTypeDescriptor = context.getBoxedDescriptor(ClassUtil.nonNullState(cgTypeId.getElementId()));
CGValuedElement argument = getExpression(cgArgument);
js.appendReferenceTo(parameterTypeDescriptor, argument);
}
js.append(");\n");
return true;
}
@Override
public @NonNull Boolean visitCGCatchExp(@NonNull CGCatchExp cgCatchExp) {
String eName = globalContext.getEName();
CGValuedElement cgSource = getExpression(cgCatchExp.getSource());
if (cgSource.isNonInvalid()) {
if (!js.appendLocalStatements(cgSource)) {
return false;
}
js.appendDeclaration(cgCatchExp);
js.append(" = ");
js.appendValueName(cgSource);
js.append(";\n");
}
else {
js.appendDeclaration(cgCatchExp);
js.append(";\n");
js.append("try {\n");
js.pushIndentation(null);
if (!js.appendLocalStatements(cgSource)) {
return false;
}
js.appendValueName(cgCatchExp);
js.append(" = ");
js.appendValueName(cgSource);
js.append(";\n");
js.popIndentation();
js.append("}\n");
js.append("catch (");
js.appendClassReference(null, Exception.class);
js.append(" " + eName + ") {\n");
js.pushIndentation(null);
js.appendValueName(cgCatchExp);
js.append(" = ");
js.appendClassReference(null, ValueUtil.class);
js.append(".createInvalidValue(" + eName + ");\n");
js.popIndentation();
js.append("}\n");
}
return true;
}
@Override
public @NonNull Boolean visitCGClass(@NonNull CGClass cgClass) {
CGPackage containingPackage = cgClass.getContainingPackage();
if (containingPackage != null) {
js.appendClassHeader(containingPackage);
}
String className = cgClass.getName();
js.append("public");
if (containingPackage == null) {
js.append(" static");
}
js.append(" class " + className);
List<CGClass> cgSuperTypes = cgClass.getSuperTypes();
boolean isFirst = true;
for (CGClass cgSuperType : cgSuperTypes) {
if (!cgSuperType.isInterface()) {
if (isFirst) {
js.append("\n\textends ");
}
else {
js.append(", ");
}
js.appendClassReference(cgSuperType);
isFirst = false;
}
}
isFirst = true;
for (CGClass cgSuperType : cgSuperTypes) {
if (cgSuperType.isInterface()) {
if (isFirst) {
js.append("\n\timplements ");
}
else {
js.append(", ");
}
js.appendClassReference(cgSuperType);
isFirst = false;
}
}
js.append("\n");
js.append("{\n");
js.pushIndentation(null);
boolean needsBlankLine = false;
needsBlankLine = doClassStatics(cgClass, needsBlankLine);
needsBlankLine = doClassFields(cgClass, needsBlankLine);
needsBlankLine = doClassMethods(cgClass, needsBlankLine);
needsBlankLine = doNestedClasses(cgClass, needsBlankLine);
js.popIndentation();
js.append("}\n");
return true;
}
@Override
public @NonNull Boolean visitCGCollectionExp(@NonNull CGCollectionExp cgCollectionExp) {
int ranges = 0;
for (CGCollectionPart cgPart : cgCollectionExp.getParts()) {
if (cgPart.isRange()) {
ranges++;
}
if (!js.appendLocalStatements(cgPart)) {
return false;
}
}
js.appendDeclaration(cgCollectionExp);
js.append(" = ");
js.appendClassReference(null, ValueUtil.class);
String kind = ((CollectionLiteralExp)cgCollectionExp.getAst()).getKind().getName();
if (ranges > 0) {
js.append(".create" + kind + "Range(");
// CGTypeVariable typeVariable = localContext.getTypeVariable(cgCollectionExp.getTypeId());
js.appendIdReference(cgCollectionExp.getTypeId().getElementId());
for (CGCollectionPart cgPart : cgCollectionExp.getParts()) {
js.append(", ");
js.appendValueName(cgPart);
}
}
else {
js.append(".create" + kind + "OfEach(");
// CGTypeVariable typeVariable = localContext.getTypeVariable(cgCollectionExp.getTypeId());
js.appendIdReference(cgCollectionExp.getTypeId().getElementId());
for (CGCollectionPart cgPart : cgCollectionExp.getParts()) {
js.append(", ");
if (cgPart.isNull() && (cgCollectionExp.getParts().size() == 1)) {
js.append("(Object)");
}
js.appendValueName(cgPart);
}
}
js.append(");\n");
return true;
}
@Override
public @NonNull Boolean visitCGCollectionPart(@NonNull CGCollectionPart cgCollectionPart) {
CGValuedElement first = getExpression(cgCollectionPart.getFirst());
CGValuedElement last = cgCollectionPart.getLast();
if (last != null) {
if (!js.appendLocalStatements(first)) {
return false;
}
if (!js.appendLocalStatements(last)) {
return false;
}
js.appendDeclaration(cgCollectionPart);
js.append(" = ");
js.appendClassReference(null, ValueUtil.class);
js.append(".createRange(");
js.appendValueName(first);
js.append(", ");
js.appendValueName(last);
js.append(");\n");
}
else {
if (first.isInlined()) {
js.appendValueName(first);
}
else {
if (!js.appendLocalStatements(first)) {
return false;
}
}
}
return true;
}
@Override
public @NonNull Boolean visitCGConstantExp(@NonNull CGConstantExp cgConstantExp) {
CGValuedElement referredConstant = cgConstantExp.getReferredConstant();
if ((referredConstant != null) && referredConstant.isInlined()) {
referredConstant.accept(this);
}
else {
// Non-inline constants should be generated somewhere else and referenced by name in the caller
}
return true;
}
@Override
public @NonNull Boolean visitCGConstraint(@NonNull CGConstraint cgConstraint) {
localContext = globalContext.getLocalContext(cgConstraint);
try {
Boolean flowContinues = super.visitCGConstraint(cgConstraint);
assert flowContinues != null;
return flowContinues;
}
finally {
localContext = null;
}
}
@Override
public @NonNull Boolean visitCGEcoreDataTypeShadowExp(@NonNull CGEcoreDataTypeShadowExp cgShadowExp) {
//
// Availability of a GenPackage is mandatory since we must have an EFactory.createFromString method to do the construction.
//
EDataType eDataType = cgShadowExp.getEDataType();
final Class<?> javaClass = eDataType.getInstanceClass();
if (javaClass == null) {
throw new IllegalStateException("No Java class for " + cgShadowExp + " in CG2JavaVisitor.visitCGEcoreDataTypeShadowExp()");
}
final EPackage ePackage = eDataType.getEPackage();
String nsURI = ePackage.getNsURI();
if (nsURI == null) {
throw new IllegalStateException("No EPackage NsURI for " + cgShadowExp + " in CG2JavaVisitor.visitCGEcoreDataTypeShadowExp()");
}
GenPackage genPackage = environmentFactory.getMetamodelManager().getGenPackage(nsURI);
if (genPackage == null) {
throw new IllegalStateException("No GenPackage for " + cgShadowExp + " in CG2JavaVisitor.visitCGEcoreDataTypeShadowExp()");
}
final String eFactoryName = genPackage.getQualifiedFactoryInterfaceName();
final String ePackageName = genPackage.getQualifiedPackageInterfaceName();
final String dataTypeName = CodeGenUtil.upperName(eDataType.getName());
ClassLoader classLoader = eDataType.getClass().getClassLoader();
Class<?> factoryClass;
Class<?> packageClass;
try {
factoryClass = classLoader.loadClass(eFactoryName);
packageClass = eDataType.getClass().getClassLoader().loadClass(ePackageName);
}
catch (ClassNotFoundException e) {
throw new IllegalStateException("Load class failure for " + cgShadowExp + " in CG2JavaVisitor.visitCGEcoreDataTypeShadowExp()", e);
}
//
CGValuedElement init = ClassUtil.nonNullState(cgShadowExp.getParts().get(0).getInit());
if (!js.appendLocalStatements(init)) {
return false;
}
Boolean ecoreIsRequired = null; // createFromString is undeclared-nonnull -- FIXME compute rather than assume
Boolean isRequired = context.isRequired(cgShadowExp);
@SuppressWarnings("null")
boolean suppressWarnings = (isRequired == Boolean.TRUE) && (ecoreIsRequired != Boolean.TRUE);
if (suppressWarnings) {
js.appendSuppressWarningsNull(true);
}
js.appendDeclaration(cgShadowExp);
js.append(" = ");
js.append("(");
js.appendClassReference(isRequired, javaClass);
js.append(")");
js.appendClassReference(null, factoryClass);
js.append(".eINSTANCE.createFromString(");
js.appendClassReference(null, packageClass);
js.append(".Literals." + dataTypeName + ", ");
js.appendValueName(init);
js.append(");\n");
return true;
}
@Override
public @NonNull Boolean visitCGEcoreExp(@NonNull CGEcoreExp cgEcoreExp) {
CGValuedElement boxedValue = getExpression(cgEcoreExp.getSource());
TypeDescriptor boxedTypeDescriptor = context.getTypeDescriptor(boxedValue);
JavaLocalContext<@NonNull ?>localContext2 = localContext;
assert localContext2 != null;
//
if (!js.appendLocalStatements(boxedValue)) {
return false;
}
EClassifier eClassifier = cgEcoreExp.getEClassifier();
if (eClassifier != null) {
Class<?> ecoreClass = eClassifier.getInstanceClass();
if (ecoreClass != null) {
String functionName = null;
if (ecoreClass == BigDecimal.class) {
functionName = "bigDecimalValueOf";
}
else if (ecoreClass == BigInteger.class) {
functionName = "bigIntegerValueOf";
}
else if ((ecoreClass == Byte.class) || (ecoreClass == byte.class)) {
functionName = "byteValueOf";
}
else if ((ecoreClass == Character.class) || (ecoreClass == char.class)) {
functionName = "characterValueOf";
}
else if ((ecoreClass == Double.class) || (ecoreClass == double.class)) {
functionName = "doubleValueOf";
}
else if ((ecoreClass == Float.class) || (ecoreClass == float.class)) {
functionName = "floatValueOf";
}
else if ((ecoreClass == Integer.class) || (ecoreClass == int.class)) {
functionName = "intValueOf";
}
else if ((ecoreClass == Long.class) || (ecoreClass == long.class)) {
functionName = "longValueOf";
}
else if ((ecoreClass == Short.class) || (ecoreClass == short.class)) {
functionName = "shortValueOf";
}
if (functionName != null) {
js.append("final ");
js.appendClassReference(null, ecoreClass);
js.append(" ");
js.appendValueName(cgEcoreExp);
js.append(" = ");
js.appendClassReference(null, ValueUtil.class);
js.append(".");
js.append(functionName);
js.append("(");
js.appendValueName(cgEcoreExp.getSource());
js.append(");\n");
return true;
}
}
}
// return boxedTypeDescriptor.getEcoreDescriptor(context, null).appendEcore(js, localContext2, cgEcoreExp, boxedValue);
return boxedTypeDescriptor.appendEcoreStatements(js, localContext2, cgEcoreExp, boxedValue);
}
@Override
public @NonNull Boolean visitCGEcoreOperationCallExp(@NonNull CGEcoreOperationCallExp cgOperationCallExp) {
Operation pOperation = cgOperationCallExp.getReferredOperation();
CGTypeId cgTypeId = analyzer.getTypeId(pOperation.getOwningClass().getTypeId());
// TypeDescriptor requiredTypeDescriptor = context.getUnboxedDescriptor(cgTypeId.getElementId());
TypeDescriptor requiredTypeDescriptor = context.getUnboxedDescriptor(ClassUtil.nonNullState(cgTypeId.getElementId()));
CGValuedElement source = getExpression(cgOperationCallExp.getSource());
List<CGValuedElement> cgArguments = cgOperationCallExp.getArguments();
List<Parameter> pParameters = pOperation.getOwnedParameters();
//
if (!js.appendLocalStatements(source)) {
return false;
}
for (@SuppressWarnings("null")@NonNull CGValuedElement cgArgument : cgArguments) {
CGValuedElement argument = getExpression(cgArgument);
if (!js.appendLocalStatements(argument)) {
return false;
}
}
//
String operationAccessor = genModelHelper.getOperationAccessor(pOperation);
// Class<?> actualBoxedReturnClass = getBoxedReturnClass(libraryOperation, arguments.size());
// Class<?> unboxedSourceClass;
// try { // FIXME this peeking is only needed for the Pivot Domain/non-Domain levels
// unboxedSourceClass = genModelHelper.getEcoreInterfaceClass(eOperation.getEContainingClass());
// }
// catch (GenModelException e) {
// unboxedSourceClass = getJavaClass(source);
// }
Element asOperationCallExp = cgOperationCallExp.getAst();
Boolean ecoreIsRequired = asOperationCallExp instanceof OperationCallExp ? context.isNonNull((OperationCallExp) asOperationCallExp) : null;
appendSuppressWarningsNull(cgOperationCallExp, ecoreIsRequired);
js.appendDeclaration(cgOperationCallExp);
js.append(" = ");
js.appendAtomicReferenceTo(requiredTypeDescriptor, source);
js.append(".");
js.append(operationAccessor);
js.append("(");
int iMax = Math.min(pParameters.size(), cgArguments.size());
for (int i = 0; i < iMax; i++) {
if (i > 0) {
js.append(", ");
}
CGValuedElement cgArgument = cgArguments.get(i);
CGValuedElement argument = getExpression(cgArgument);
Parameter pParameter = ClassUtil.nonNullState(pParameters.get(i));
GenParameter genParameter = context.getGenModelHelper().getGenParameter(pParameter);
if (genParameter != null) {
String rawBoundType = ClassUtil.nonNullState(genParameter.getRawBoundType());
TypeDescriptor typeDescriptor = context.getTypeDescriptor(argument);
typeDescriptor.appendEcoreValue(js, rawBoundType, argument);
}
else { // ? never happens
CGTypeId cgParameterTypeId = analyzer.getTypeId(pParameter.getTypeId());
TypeDescriptor parameterTypeDescriptor = context.getUnboxedDescriptor(ClassUtil.nonNullState(cgParameterTypeId.getElementId()));
js.appendReferenceTo(parameterTypeDescriptor, argument);
}
}
js.append(");\n");
return true;
}
@Override
public @NonNull Boolean visitCGEcorePropertyCallExp(@NonNull CGEcorePropertyCallExp cgPropertyCallExp) {
return appendCGEcorePropertyCallExp(cgPropertyCallExp, null);
}
@Override
public @NonNull Boolean visitCGElementId(@NonNull CGElementId cgElementId) {
ElementId elementId = cgElementId.getElementId();
if ((elementId != null) && !CGUtil.isInlinedId(elementId)) {
js.append("public static final ");
js.appendIsCaught(true, false);
js.append(" ");
js.appendClassReference(true, elementId.accept(id2JavaInterfaceVisitor));
js.append(" ");
js.append(globalContext.getValueName(cgElementId));
js.append(" = ");
js.appendIdReference2(elementId);
js.append(";\n");
}
return true;
}
@Override
public @NonNull Boolean visitCGExecutorCompositionProperty(@NonNull CGExecutorCompositionProperty cgExecutorProperty) {
js.appendDeclaration(cgExecutorProperty);
js.append(" = new ");
js.appendClassReference(null, cgExecutorProperty);
js.append("(");
js.appendIdReference(cgExecutorProperty.getUnderlyingPropertyId().getElementId());
js.append(");\n");
return true;
}
@Override
public @NonNull Boolean visitCGExecutorShadowPart(@NonNull CGExecutorShadowPart cgExecutorShadowPart) {
js.appendDeclaration(cgExecutorShadowPart);
js.append(" = ");
js.appendValueName(localContext.getIdResolverVariable(cgExecutorShadowPart));
js.append(".getProperty(");
js.appendIdReference(cgExecutorShadowPart.getUnderlyingPropertyId().getElementId());
js.append(");\n");
return true;
}
@Override
public @NonNull Boolean visitCGExecutorNavigationProperty(@NonNull CGExecutorNavigationProperty cgExecutorProperty) {
js.appendDeclaration(cgExecutorProperty);
js.append(" = new ");
js.appendClassReference(null, cgExecutorProperty);
js.append("(");
js.appendIdReference(cgExecutorProperty.getUnderlyingPropertyId().getElementId());
js.append(");\n");
return true;
}
@Override
public @NonNull Boolean visitCGExecutorOppositeProperty(@NonNull CGExecutorOppositeProperty cgExecutorProperty) {
Property asProperty = (Property) cgExecutorProperty.getAst();
Property asOppositeProperty = asProperty.getOpposite();
js.appendDeclaration(cgExecutorProperty);
js.append(" = new ");
js.appendClassReference(null, cgExecutorProperty);
js.append("(");
js.appendIdReference(asOppositeProperty.getPropertyId());
js.append(");\n");
return true;
}
@Override
public @NonNull Boolean visitCGExecutorOperation(@NonNull CGExecutorOperation cgExecutorOperation) {
js.appendDeclaration(cgExecutorOperation);
js.append(" = ");
try {
js.appendValueName(localContext.getIdResolverVariable(cgExecutorOperation));
}
catch (Exception e) { // FIXME
js.appendString(String.valueOf(e));
}
js.append(".getOperation(");
js.appendIdReference(cgExecutorOperation.getUnderlyingOperationId().getElementId());
js.append(");\n");
return true;
}
@Override
public @NonNull Boolean visitCGExecutorOperationCallExp(@NonNull CGExecutorOperationCallExp cgOperationCallExp) {
Operation pOperation = cgOperationCallExp.getReferredOperation();
CGValuedElement source = getExpression(cgOperationCallExp.getSource());
List<CGValuedElement> cgArguments = cgOperationCallExp.getArguments();
List<Parameter> pParameters = pOperation.getOwnedParameters();
//
if (!js.appendLocalStatements(source)) {
return false;
}
for (@SuppressWarnings("null")@NonNull CGValuedElement cgArgument : cgArguments) {
CGValuedElement argument = getExpression(cgArgument);
if (!js.appendLocalStatements(argument)) {
return false;
}
}
//
js.appendDeclaration(cgOperationCallExp);
js.append(" = ");
SubStream castBody = new SubStream() {
@Override
public void append() {
js.appendReferenceTo(cgOperationCallExp.getExecutorOperation());
js.append(".evaluate(");
// js.append(getValueName(localContext.getEvaluatorParameter(cgOperationCallExp)));
js.append(JavaConstants.EXECUTOR_NAME);
js.append(", ");
js.appendIdReference(cgOperationCallExp.getASTypeId());
js.append(", ");
js.appendValueName(source);
int iMax = Math.min(pParameters.size(), cgArguments.size());
for (int i = 0; i < iMax; i++) {
js.append(", ");
CGValuedElement cgArgument = cgArguments.get(i);
Parameter pParameter = pParameters.get(i);
CGTypeId cgTypeId = analyzer.getTypeId(pParameter.getTypeId());
TypeDescriptor parameterTypeDescriptor = context.getUnboxedDescriptor(ClassUtil.nonNullState(cgTypeId.getElementId()));
CGValuedElement argument = getExpression(cgArgument);
js.appendReferenceTo(parameterTypeDescriptor, argument);
}
js.append(")");
}
};
js.appendClassCast(cgOperationCallExp, castBody);
js.append(";\n");
return true;
}
@Override
public @NonNull Boolean visitCGExecutorOppositePropertyCallExp(@NonNull CGExecutorOppositePropertyCallExp cgPropertyCallExp) {
CGValuedElement source = getExpression(cgPropertyCallExp.getSource());
//
if (!js.appendLocalStatements(source)) {
return false;
}
//
js.appendDeclaration(cgPropertyCallExp);
js.append(" = ");
SubStream castBody = new SubStream() {
@Override
public void append() {
js.appendReferenceTo(cgPropertyCallExp.getExecutorProperty());
js.append(".evaluate(");
// js.append(getValueName(localContext.getEvaluatorParameter(cgPropertyCallExp)));
js.append(JavaConstants.EXECUTOR_NAME);
js.append(", ");
js.appendIdReference(cgPropertyCallExp.getASTypeId());
js.append(", ");
js.appendValueName(source);
js.append(")");
}
};
js.appendClassCast(cgPropertyCallExp, castBody);
js.append(";\n");
return true;
}
@Override
public @NonNull Boolean visitCGExecutorPropertyCallExp(@NonNull CGExecutorPropertyCallExp cgPropertyCallExp) {
CGValuedElement source = getExpression(cgPropertyCallExp.getSource());
//
if (!js.appendLocalStatements(source)) {
return false;
}
//
// CGExecutorProperty cgExecutorProperty = ClassUtil.nonNullState(cgPropertyCallExp.getExecutorProperty());
Boolean ecoreIsRequired = Boolean.FALSE; // CP properties evaluate is nullable -- FIXME compute rather than assume
// boolean isPrimitive = js.isPrimitive(cgPropertyCallExp);
Boolean isRequired = context.isRequired(cgPropertyCallExp);
if ((isRequired == Boolean.TRUE) && (ecoreIsRequired != Boolean.TRUE)) {
js.appendSuppressWarningsNull(true);
}
js.appendDeclaration(cgPropertyCallExp);
js.append(" = ");
TypeDescriptor typeDescriptor = context.getTypeDescriptor(cgPropertyCallExp);
JavaStream.SubStream castBody = new JavaStream.SubStream() {
@Override
public void append() {
js.appendReferenceTo(cgPropertyCallExp.getExecutorProperty());
js.append(".evaluate(");
// js.append(getValueName(localContext.getEvaluatorParameter(cgPropertyCallExp)));
js.append(JavaConstants.EXECUTOR_NAME);
js.append(", ");
js.appendIdReference(cgPropertyCallExp.getASTypeId());
js.append(", ");
js.appendValueName(source);
js.append(")");
}
};
typeDescriptor.appendCast(js, isRequired, null, castBody);
js.append(";\n");
return true;
}
@Override
public @NonNull Boolean visitCGExecutorType(@NonNull CGExecutorType cgExecutorType) {
js.appendDeclaration(cgExecutorType);
js.append(" = ");
js.appendValueName(localContext.getIdResolverVariable(cgExecutorType));
js.append(".getClass(");
js.appendIdReference(cgExecutorType.getUnderlyingTypeId().getElementId());
js.append(", null);\n");
return true;
}
@Override
public @NonNull Boolean visitCGGuardExp(@NonNull CGGuardExp cgGuardExp) {
CGValuedElement cgSource = getExpression(cgGuardExp.getSource());
//
if (cgSource.isNull()) {
js.append("throw new ");
js.appendClassReference(null, InvalidValueException.class);
js.append("();\n");
}
else {
if (!js.appendLocalStatements(cgSource)) {
return false;
}
if (cgGuardExp.isSafe()) {
js.append("assert ");
js.appendValueName(cgSource);
js.append(" != null;\n");
}
else if (!cgSource.isNonNull()) {
js.append("if (");
js.appendValueName(cgSource);
js.append(" == null) {\n");
js.pushIndentation(null);
appendGuardFailure(cgGuardExp);
js.popIndentation();
js.append("}\n");
}
}
return true;
}
@Override
public @NonNull Boolean visitCGIfExp(@NonNull CGIfExp cgIfExp) {
CGValuedElement condition = getExpression(cgIfExp.getCondition());
CGValuedElement thenExpression = getExpression(cgIfExp.getThenExpression());
CGValuedElement elseExpression = getExpression(cgIfExp.getElseExpression());
// CGVariable resultVariable = localContext.getLocalVariable(cgIfExp);
boolean flowContinues = false;
//
if (!js.appendLocalStatements(condition)) {
return flowContinues;
}
js.appendDeclaration(cgIfExp);
js.append(";\n");
//
js.append("if (");
js.appendBooleanValueName(condition, true);
js.append(") {\n");
try {
js.pushIndentation(null);
if (js.appendAssignment(cgIfExp, thenExpression)) {
flowContinues = true;
}
} finally {
js.popIndentation();
}
js.append("}\n");
js.append("else {\n");
try {
js.pushIndentation(null);
if (js.appendAssignment(cgIfExp, elseExpression)) {
flowContinues = true;
}
} finally {
js.popIndentation();
}
js.append("}\n");
return flowContinues;
}
@Override
public @NonNull Boolean visitCGInteger(@NonNull CGInteger object) {
js.appendDeclaration(object);
js.append(" = ");
js.appendClassReference(null, ValueUtil.class);
js.append(".integerValueOf(");
Number integerValue = object.getNumericValue();
String valueString = integerValue.toString();
assert valueString != null;
if (integerValue instanceof IntIntegerValueImpl) {
js.append(valueString);
}
else if (integerValue instanceof LongIntegerValueImpl) {
js.append(valueString + "L");
}
else {
js.append("\"" + valueString + "\"");
}
js.append(");\n");
return true;
}
@Override
public @NonNull Boolean visitCGInvalid(@NonNull CGInvalid object) {
String message = object.getMessageTemplate();
if (message != null) {
js.append("new ");
js.appendClassReference(null, InvalidValueException.class);
js.append("(");
js.appendString(message);
for (Object binding : object.getBindings()) {
js.append(", ");
js.appendString(ClassUtil.nonNullState(String.valueOf(binding)));
}
js.append(")");
}
else {
js.appendClassReference(null, ValueUtil.class);
js.append(".INVALID_VALUE");
}
return true;
}
@Override
public @NonNull Boolean visitCGIsEqualExp(@NonNull CGIsEqualExp cgIsEqualExp) { // FIXME BUG 421738 move irregulaties to e.g. BooleanPrimitiveDescriptor
if (cgIsEqualExp.isTrue()) {
js.appendDeclaration(cgIsEqualExp);
js.append(" = ");
js.appendTrue();
js.append(";\n");
}
else if (cgIsEqualExp.isFalse()) {
js.appendDeclaration(cgIsEqualExp);
js.append(" = ");
js.appendFalse();
js.append(";\n");
}
else {
CGValuedElement cgSource = getExpression(cgIsEqualExp.getSource());
CGValuedElement cgArgument = getExpression(cgIsEqualExp.getArgument());
if (!js.appendLocalStatements(cgSource)) {
return false;
}
if (!js.appendLocalStatements(cgArgument)) {
return false;
}
//
boolean notEquals = cgIsEqualExp.isNotEquals();
js.appendDeclaration(cgIsEqualExp);
js.append(" = ");
if (cgSource.isNull()) {
if (cgArgument.isNull()) {
js.appendBooleanString(true ^ notEquals);
}
else if (cgArgument.isNonNull()) {
js.appendBooleanString(false ^ notEquals);
}
else {
js.appendValueName(cgArgument);
js.append(notEquals ? " != " : " == ");
js.append("null");
}
}
else if (cgArgument.isNull()) {
if (cgSource.isNonNull()) {
js.appendBooleanString(false ^ notEquals);
}
else {
js.appendValueName(cgSource);
js.append(notEquals ? " != " : " == ");
js.append("null");
}
}
else if (cgSource.isTrue()) {
if (cgArgument.isTrue()) {
js.appendBooleanString(true ^ notEquals);
}
else if (cgArgument.isFalse()) {
js.appendBooleanString(false ^ notEquals);
}
else {
js.appendBooleanValueName(cgArgument, true ^ notEquals);
}
}
else if (cgSource.isFalse()) {
if (cgArgument.isFalse()) {
js.appendBooleanString(true ^ notEquals);
}
else if (cgArgument.isTrue()) {
js.appendBooleanString(false ^ notEquals);
}
else {
js.appendBooleanValueName(cgArgument, false ^ notEquals);
}
}
else if (cgArgument.isTrue()) {
js.appendBooleanValueName(cgSource, true ^ notEquals);
}
else if (cgArgument.isFalse()) {
js.appendBooleanValueName(cgSource, false ^ notEquals);
}
else {
TypeDescriptor sourceTypeDescriptor = context.getTypeDescriptor(cgSource);
sourceTypeDescriptor.appendEqualsValue(js, cgSource, cgArgument, notEquals);
}
js.append(";\n");
}
return true;
}
@Override
public @NonNull Boolean visitCGIsEqual2Exp(@NonNull CGIsEqual2Exp cgIsEqualExp) { // FIXME BUG 421738 move irregulaties to e.g. BooleanPrimitiveDescriptor
if (cgIsEqualExp.isTrue()) {
js.appendDeclaration(cgIsEqualExp);
js.append(" = ");
js.appendTrue();
js.append(";\n");
}
else if (cgIsEqualExp.isFalse()) {
js.appendDeclaration(cgIsEqualExp);
js.append(" = ");
js.appendFalse();
js.append(";\n");
}
else {
CGValuedElement cgSource = getExpression(cgIsEqualExp.getSource());
CGValuedElement cgArgument = getExpression(cgIsEqualExp.getArgument());
if (!js.appendLocalStatements(cgSource)) {
return false;
}
if (!js.appendLocalStatements(cgArgument)) {
return false;
}
//
js.appendDeclaration(cgIsEqualExp);
js.append(" = ");
boolean isNull1 = cgSource.isNull();
boolean isNull2 = cgArgument.isNull();
if (isNull1 && isNull2) {
js.appendBooleanString(isNull1 == isNull2);
}
else if (isNull1 && !isNull2) {
if (cgArgument.isNonNull()) {
js.appendBooleanString(false);
}
else {
js.appendValueName(cgArgument);
js.append(" == ");
js.append("null");
}
}
else if (isNull2 && !isNull1) {
if (cgSource.isNonNull()) {
js.appendBooleanString(false);
}
else {
js.appendValueName(cgSource);
js.append(" == ");
js.append("null");
}
}
else if (cgSource.isTrue()) {
if (cgArgument.isTrue()) {
js.appendBooleanString(true);
}
else if (cgArgument.isFalse()) {
js.appendBooleanString(false);
}
else {
js.appendBooleanValueName(cgArgument, true);
}
}
else if (cgSource.isFalse()) {
if (cgArgument.isFalse()) {
js.appendBooleanString(true);
}
else if (cgArgument.isTrue()) {
js.appendBooleanString(false);
}
else {
js.appendBooleanValueName(cgArgument, false);
}
}
else if (cgArgument.isTrue()) {
js.appendBooleanValueName(cgSource, true);
}
else if (cgArgument.isFalse()) {
js.appendBooleanValueName(cgSource, false);
}
else {
TypeDescriptor sourceTypeDescriptor = context.getTypeDescriptor(cgSource);
sourceTypeDescriptor.appendEqualsValue(js, cgSource, cgArgument, false);
}
js.append(";\n");
}
return true;
}
@Override
public @NonNull Boolean visitCGIsInvalidExp(@NonNull CGIsInvalidExp cgIsInvalidExp) {
if (cgIsInvalidExp.isTrue()) {
js.appendTrue();
}
else if (cgIsInvalidExp.isFalse()) {
js.appendFalse();
}
else {
CGValuedElement cgSource = getExpression(cgIsInvalidExp.getSource());
if (!js.appendLocalStatements(cgSource)) {
return false;
}
//
js.appendDeclaration(cgIsInvalidExp);
js.append(" = ");
js.appendValueName(cgSource);
js.append(" instanceof ");
js.appendClassReference(null, InvalidValueException.class);
js.append(";\n");
}
return true;
}
@Override
public @NonNull Boolean visitCGIsKindOfExp(@NonNull CGIsKindOfExp cgIsKindOfExp) {
CGValuedElement cgSource = getExpression(cgIsKindOfExp.getSource());
CGExecutorType cgType = cgIsKindOfExp.getExecutorType();
if (cgType != null) {
TypeId asTypeId = cgType.getASTypeId();
assert asTypeId != null;
TypeDescriptor typeDescriptor = context.getBoxedDescriptor(asTypeId);
js.appendDeclaration(cgIsKindOfExp);
js.append(" = ");
js.appendValueName(cgSource);
js.append(" instanceof ");
typeDescriptor.append(js, null);
js.append(";\n");
}
return true;
}
@Override
public @NonNull Boolean visitCGIsUndefinedExp(@NonNull CGIsUndefinedExp cgIsUndefinedExp) {
if (cgIsUndefinedExp.isTrue()) {
js.appendTrue();
}
else if (cgIsUndefinedExp.isFalse()) {
js.appendFalse();
}
else {
CGValuedElement cgSource = getExpression(cgIsUndefinedExp.getSource());
boolean sourceIsNonInvalid = cgSource.isNonInvalid();
boolean sourceIsNonNull = cgSource.isNonNull();
if (!js.appendLocalStatements(cgSource)) {
return false;
}
//
js.appendDeclaration(cgIsUndefinedExp);
js.append(" = ");
if (!sourceIsNonNull && !sourceIsNonInvalid) {
js.append("(");
js.appendValueName(cgSource);
js.append(" == null) || (");
js.appendValueName(cgSource);
js.append(" instanceof ");
js.appendClassReference(null, InvalidValueException.class);
js.append(")");
}
else if (!sourceIsNonNull && sourceIsNonInvalid) {
js.appendValueName(cgSource);
js.append(" == null");
}
else if (sourceIsNonNull && !sourceIsNonInvalid) {
js.appendValueName(cgSource);
js.append(" instanceof ");
js.appendClassReference(null, InvalidValueException.class);
}
js.append(";\n");
}
return true;
}
@Override
public @NonNull Boolean visitCGLetExp(@NonNull CGLetExp cgLetExp) {
cgLetExp.getInit().accept(this);
CGValuedElement cgIn = cgLetExp.getIn();
if (cgIn != null) {
if (!js.appendLocalStatements(cgIn)) {
return false;
}
}
return true;
}
@Override
public @NonNull Boolean visitCGLibraryIterateCallExp(@NonNull CGLibraryIterateCallExp cgIterateCallExp) {
return appendLoopCall(cgIterateCallExp, cgIterateCallExp.getResult());
}
@Override
public @NonNull Boolean visitCGLibraryIterationCallExp(@NonNull CGLibraryIterationCallExp cgIterationCallExp) {
return appendLoopCall(cgIterationCallExp, null);
}
@Override
public @NonNull Boolean visitCGLibraryOperation(@NonNull CGLibraryOperation cgOperation) {
JavaLocalContext<@NonNull ?> localContext2 = globalContext.getLocalContext(cgOperation);
if (localContext2 != null) {
localContext = localContext2;
try {
List<CGParameter> cgParameters = cgOperation.getParameters();
String operationName = cgOperation.getName();
assert operationName != null;
js.append("public static class ");
js.append(operationName);
js.append(" extends ");
js.appendClassReference(null, genModelHelper.getAbstractOperationClass(cgParameters.size()-3)); // executor, typeId, self
js.pushClassBody(operationName);
js.append("public static final ");
js.appendIsRequired(true);
js.append(" ");
js.append(operationName);
js.append(" ");
js.append(globalContext.getInstanceName());
js.append(" = new ");
js.append(operationName);
js.append("();\n");
js.append("\n");
// js.append("public static final ");
// CGValuedElement evaluatorParameter = localContext2.getEvaluatorParameter(cgOperation);
// CGParameter typeIdParameter = localContext2.getTypeIdParameter(cgOperation);
CGValuedElement body = getExpression(cgOperation.getBody());
//
Element ast = cgOperation.getAst();
if (ast instanceof Operation) {
LanguageExpression expressionInOCL = ((Operation)ast).getBodyExpression();
if (ast instanceof Operation) {
String title = PrettyPrinter.printName(ast);
js.appendCommentWithOCL(title+"\n", expressionInOCL);
}
}
//
js.append("@Override\n");
js.append("public ");
boolean cgOperationIsInvalid = cgOperation.getInvalidValue() != null;
js.appendIsCaught(!cgOperationIsInvalid, cgOperationIsInvalid);
js.append(" ");
js.appendClassReference(cgOperation.isRequired() ? true : null, cgOperation);
js.append(" ");
js.append(globalContext.getEvaluateName());
js.append("(");
boolean isFirst = true;
for (@SuppressWarnings("null")@NonNull CGParameter cgParameter : cgParameters) {
if (!isFirst) {
js.append(", ");
}
js.appendDeclaration(cgParameter);
isFirst = false;
}
js.append(") {\n");
js.pushIndentation(null);
appendReturn(body);
js.popIndentation();
js.append("}\n");
js.popClassBody(false);
}
finally {
localContext = null;
}
}
return true;
}
@Override
public @NonNull Boolean visitCGLibraryOperationCallExp(@NonNull CGLibraryOperationCallExp cgOperationCallExp) {
final LibraryOperation libraryOperation = ClassUtil.nonNullState(cgOperationCallExp.getLibraryOperation());
LibraryOperationHandler libraryOperationHandler = libraryOperation2handler.get(libraryOperation.getClass());
if (libraryOperationHandler != null) {
return libraryOperationHandler.generate(cgOperationCallExp);
}
final CGValuedElement source = getExpression(cgOperationCallExp.getSource());
final List<CGValuedElement> arguments = cgOperationCallExp.getArguments();
Method actualMethod = getJavaMethod(libraryOperation, arguments.size());
Class<?> actualReturnClass = actualMethod != null ? actualMethod.getReturnType() : null;
boolean actualIsNonNull = (actualMethod != null) && (context.getIsNonNull(actualMethod) == Boolean.TRUE);
boolean expectedIsNonNull = cgOperationCallExp.isNonNull();
final CGTypeId resultType = cgOperationCallExp.getTypeId();
if (!js.appendLocalStatements(source)) {
return false;
}
for (@SuppressWarnings("null")@NonNull CGValuedElement cgArgument : arguments) {
if (!js.appendLocalStatements(cgArgument)) {
return false;
}
}
for (int i = 0; i < arguments.size(); i++) {
CGValuedElement cgArgument = arguments.get(i);
Parameter asParameter = cgOperationCallExp.getReferredOperation().getOwnedParameters().get(i);
if (asParameter.isIsRequired()) {
if (cgArgument.isNull()) {
js.append("throw new ");
js.appendClassReference(null, InvalidValueException.class);
js.append("(\"Null argument\");\n");
return false;
}
else if (cgArgument.isInvalid()) {
js.append("throw new ");
js.appendClassReference(null, InvalidValueException.class);
js.append("(\"Invalid argument\");\n");
return false;
}
else {
if (!cgArgument.isNonNull()) {
js.append("if (");
js.appendValueName(cgArgument);
js.append(" == null) {\n");
js.pushIndentation(null);
js.append("throw new ");
js.appendClassReference(null, InvalidValueException.class);
js.append("(\"Null argument\");\n");
js.popIndentation();
js.append("}\n");
}
if (!cgArgument.isNonInvalid()) {
js.append("if (");
js.appendValueName(cgArgument);
js.append(" instanceof ");
js.appendClassReference(null, InvalidValueException.class);
js.append(") {\n");
js.pushIndentation(null);
js.append("throw (");
js.appendClassReference(null, InvalidValueException.class);
js.append(")");
js.appendValueName(cgArgument);
js.append(";\n");
js.popIndentation();
js.append("}\n");
}
}
}
}
if (expectedIsNonNull && !actualIsNonNull) {
js.appendSuppressWarningsNull(true);
}
js.appendDeclaration(cgOperationCallExp);
js.append(" = ");
boolean isRequiredNullCast = expectedIsNonNull && !actualIsNonNull;
// if (expectedIsNonNull && !actualIsNonNull) {
// js.appendClassReference(null, ClassUtil.class);
// js.append(".nonNullState(");
// }
js.appendClassCast(cgOperationCallExp, isRequiredNullCast, actualReturnClass, new JavaStream.SubStream()
{
@Override
public void append() {
js.appendClassReference(null, libraryOperation.getClass());
js.append("."+ globalContext.getInstanceName() + "."+ globalContext.getEvaluateName() + "(");
if (!(libraryOperation instanceof LibrarySimpleOperation)) {
// js.append(getValueName(localContext.getEvaluatorParameter(cgOperationCallExp)));
js.append(JavaConstants.EXECUTOR_NAME);
js.append(", ");
if (!(libraryOperation instanceof LibraryUntypedOperation)) {
// CGTypeVariable typeVariable = localContext.getTypeVariable(resultType);
js.appendValueName(resultType);
js.append(", ");
}
}
if (source.isNull()) {
js.append("(Object)");
}
js.appendValueName(source);
for (@SuppressWarnings("null")@NonNull CGValuedElement cgArgument : arguments) {
js.append(", ");
if (cgArgument.isNull()) {
js.append("(Object)");
}
js.appendValueName(cgArgument); // FIXME cast
}
js.append(")");
}
});
// if (expectedIsNonNull && !actualIsNonNull) {
// js.append(")");
// }
js.append(";\n");
return true;
}
@Override
public @NonNull Boolean visitCGLibraryPropertyCallExp(@NonNull CGLibraryPropertyCallExp cgPropertyCallExp) {
CGValuedElement source = getExpression(cgPropertyCallExp.getSource());
LibraryProperty libraryProperty = ClassUtil.nonNullState(cgPropertyCallExp.getLibraryProperty());
Method actualMethod = getJavaMethod(libraryProperty);
Class<?> actualReturnClass = actualMethod != null ? actualMethod.getReturnType() : null;
boolean actualIsNonNull = (actualMethod != null) && (context.getIsNonNull(actualMethod) == Boolean.TRUE);
boolean expectedIsNonNull = cgPropertyCallExp.isNonNull();
// Class<?> actualBoxedReturnClass = getBoxedReturnClass(libraryProperty);
// CGValuedElement resultVariable = cgOperationCallExp; //.getValue();
CGTypeId resultType = cgPropertyCallExp.getTypeId();
// Class<?> requiredBoxedReturnClass = context.getBoxedClass(resultType.getElementId());
if (!js.appendLocalStatements(source)) {
return false;
}
js.appendDeclaration(cgPropertyCallExp);
js.append(" = ");
boolean isRequiredNullCast = expectedIsNonNull && !actualIsNonNull;
// if (expectedIsNonNull && !actualIsNonNull) {
// js.appendClassReference(null, ClassUtil.class);
// js.append(".nonNullState(");
// }
SubStream castBody = new SubStream() {
@Override
public void append() {
js.appendClassReference(null, libraryProperty.getClass());
// CGOperation cgOperation = ClassUtil.nonNullState(CGUtils.getContainingOperation(cgPropertyCallExp));
js.append("."+ globalContext.getInstanceName() + "."+ globalContext.getEvaluateName() + "(");
// if (!(libraryOperation instanceof LibrarySimpleOperation)) {
// js.append(getValueName(localContext.getEvaluatorParameter(cgPropertyCallExp)));
js.append(JavaConstants.EXECUTOR_NAME);
js.append(", ");
// if (!(libraryProperty instanceof LibraryUntypedOperation)) {
// CGTypeVariable typeVariable = localContext.getTypeVariable(resultType);
js.appendValueName(resultType);
js.append(", ");
// }
// }
js.appendValueName(source);
// if (expectedIsNonNull && !actualIsNonNull) {
// js.append(")");
// }
js.append(")");
}
};
js.appendClassCast(cgPropertyCallExp, isRequiredNullCast, actualReturnClass, castBody);
js.append(";\n");
return true;
}
@Override
public @NonNull Boolean visitCGMapExp(@NonNull CGMapExp cgMapExp) {
for (CGMapPart cgPart : cgMapExp.getParts()) {
if ((cgPart != null) && !js.appendLocalStatements(cgPart)) {
return false;
}
}
js.appendDeclaration(cgMapExp);
js.append(" = ");
js.appendClassReference(null, ValueUtil.class);
js.append(".createMapOfEach(");
// CGTypeVariable typeVariable = localContext.getTypeVariable(cgMapExp.getTypeId());
js.appendIdReference(cgMapExp.getTypeId().getElementId());
for (CGMapPart cgPart : cgMapExp.getParts()) {
js.append(", ");
if (cgPart.isNull() && (cgMapExp.getParts().size() == 1)) {
js.append("(Object)");
}
js.appendValueName(cgPart);
}
js.append(");\n");
return true;
}
@Override
public @NonNull Boolean visitCGMapPart(@NonNull CGMapPart cgMapPart) {
CGValuedElement key = getExpression(cgMapPart.getKey());
CGValuedElement value = getExpression(cgMapPart.getValue());
if (!js.appendLocalStatements(key)) {
return false;
}
if (!js.appendLocalStatements(value)) {
return false;
}
js.appendDeclaration(cgMapPart);
js.append(" = ");
js.appendClassReference(null, ValueUtil.class);
js.append(".createMapEntry(");
js.appendValueName(key);
js.append(", ");
js.appendValueName(value);
js.append(");\n");
return true;
}
@Override // FIXME revert to the pre-cached code
public @NonNull Boolean visitCGNativeOperation(@NonNull CGNativeOperation cgOperation) {
Operation asOperation = (Operation) cgOperation.getAst();
assert asOperation != null;
JavaLocalContext<@NonNull ?> localContext2 = globalContext.getLocalContext(cgOperation);
if (localContext2 != null) {
localContext = localContext2;
try {
String operationClassName = getNativeOperationClassName(cgOperation);
LanguageExpression expressionInOCL = asOperation.getBodyExpression();
String title = PrettyPrinter.printName(asOperation);
js.appendCommentWithOCL(title+"\n", expressionInOCL);
//
js.append("protected class ");
js.append(operationClassName);
js.append(" extends ");
js.appendClassReference(null, AbstractEvaluationOperation.class);
js.pushClassBody(operationClassName);
doCachedOperationBasicEvaluate(cgOperation);
js.append("\n");
doCachedOperationEvaluate(cgOperation);
js.popClassBody(false);
//
js.append("\n");
doCachedOperationClassInstance(cgOperation);
}
finally {
localContext = null;
}
}
return true;
}
@Override
public @NonNull Boolean visitCGNativeOperationCallExp(@NonNull CGNativeOperationCallExp cgOperationCallExp) {
Operation pOperation = cgOperationCallExp.getReferredOperation();
boolean thisIsSelf = cgOperationCallExp.isThisIsSelf();
CGValuedElement source = getExpression(cgOperationCallExp.getSource());
List<CGValuedElement> cgArguments = cgOperationCallExp.getArguments();
List<Parameter> pParameters = pOperation.getOwnedParameters();
//
if (!js.appendLocalStatements(source)) {
return false;
}
for (@SuppressWarnings("null")@NonNull CGValuedElement cgArgument : cgArguments) {
CGValuedElement argument = getExpression(cgArgument);
if (!js.appendLocalStatements(argument)) {
return false;
}
}
//
js.appendDeclaration(cgOperationCallExp);
js.append(" = ");
// js.appendClassCast(cgOperationCallExp);
/* if (thisIsSelf) {
js.appendValueName(source);
}
else {
if (localPrefix != null) {
js.append(localPrefix);
js.append(".");
}
js.append("this");
} */
js.appendThis(ClassUtil.nonNullState(cgOperationCallExp.getReferredOperation().getOwningClass().getName()));
js.append(".");
js.append(cgOperationCallExp.getReferredOperation().getName());
js.append("(");
if (!thisIsSelf) {
js.appendValueName(source);
}
int iMax = Math.min(pParameters.size(), cgArguments.size());
for (int i = 0; i < iMax; i++) {
if ((i > 0) || !thisIsSelf) {
js.append(", ");
}
CGValuedElement cgArgument = cgArguments.get(i);
Parameter pParameter = pParameters.get(i);
CGTypeId cgTypeId = analyzer.getTypeId(pParameter.getTypeId());
TypeDescriptor parameterTypeDescriptor = context.getUnboxedDescriptor(ClassUtil.nonNullState(cgTypeId.getElementId()));
CGValuedElement argument = getExpression(cgArgument);
js.appendReferenceTo(parameterTypeDescriptor, argument);
}
js.append(");\n");
return true;
}
@Override
public @NonNull Boolean visitCGNativeProperty(@NonNull CGNativeProperty cgNativeProperty) {
localContext = globalContext.getLocalContext(cgNativeProperty);
try {
js.append("protected ");
js.appendDeclaration(cgNativeProperty);
js.append(";\n");
return true;
}
finally {
localContext = null;
}
}
@Override
public @NonNull Boolean visitCGNativePropertyCallExp(@NonNull CGNativePropertyCallExp cgPropertyCallExp) {
CGValuedElement source = getExpression(cgPropertyCallExp.getSource());
//
if (!js.appendLocalStatements(source)) {
return false;
}
//
js.appendDeclaration(cgPropertyCallExp);
js.append(" = ");
SubStream castBody = new SubStream() {
@Override
public void append() {
js.appendValueName(source);
js.append(".");
js.append(cgPropertyCallExp.getReferredProperty().getName());
}
};
js.appendClassCast(cgPropertyCallExp, castBody);
js.append(";\n");
return true;
}
@Override
public @NonNull Boolean visitCGNull(@NonNull CGNull object) {
js.append("null");
return true;
}
@Override
public @NonNull Boolean visitCGOperation(@NonNull CGOperation cgOperation) {
JavaLocalContext<@NonNull ?> localContext2 = globalContext.getLocalContext(cgOperation);
if (localContext2 != null) {
localContext = localContext2;
try {
// CGValuedElement evaluatorParameter = localContext2.getEvaluatorParameter(cgOperation);
// CGParameter typeIdParameter = localContext2.getTypeIdParameter(cgOperation);
List<CGParameter> cgParameters = cgOperation.getParameters();
CGValuedElement body = getExpression(cgOperation.getBody());
//
Element ast = cgOperation.getAst();
if (ast instanceof Operation) {
LanguageExpression expressionInOCL = ((Operation)ast).getBodyExpression();
if (ast instanceof Operation) {
String title = PrettyPrinter.printName(ast);
js.appendCommentWithOCL(title+"\n", expressionInOCL);
}
}
//
js.append("@Override\n");
js.append("public ");
boolean cgOperationIsInvalid = cgOperation.getInvalidValue() != null;
js.appendIsCaught(!cgOperationIsInvalid, cgOperationIsInvalid);
js.append(" ");
js.appendClassReference(cgOperation.isRequired() ? true : null, cgOperation);
js.append(" ");
js.append(cgOperation.getName());
js.append("(");
boolean isFirst = true;
for (@SuppressWarnings("null")@NonNull CGParameter cgParameter : cgParameters) {
if (!isFirst) {
js.append(", ");
}
js.appendDeclaration(cgParameter);
isFirst = false;
}
js.append(") {\n");
js.pushIndentation(null);
appendReturn(body);
js.popIndentation();
js.append("}\n");
}
finally {
localContext = null;
}
}
return true;
}
@Override
public @NonNull Boolean visitCGPackage(@NonNull CGPackage cgPackage) {
for (CGPackage cgNestedPackage : cgPackage.getPackages()) {
cgNestedPackage.accept(this);
}
for (CGClass cgClass : cgPackage.getClasses()) {
cgClass.accept(this);
}
return true;
}
@Override
public @NonNull Boolean visitCGParameter(@NonNull CGParameter object) {
return true; // Parameters are declared by their Operation
}
@Override
public @NonNull Boolean visitCGProperty(@NonNull CGProperty cgProperty) {
localContext = globalContext.getLocalContext(cgProperty);
try {
Boolean flowContinues = super.visitCGProperty(cgProperty);
assert flowContinues != null;
return flowContinues;
}
finally {
localContext = null;
}
}
@Override
public @NonNull Boolean visitCGReal(@NonNull CGReal object) {
js.appendDeclaration(object);
js.append(" = ");
js.appendClassReference(null, ValueUtil.class);
js.append(".realValueOf(");
Number realValue = object.getNumericValue();
String valueString = realValue.toString();
if (realValue instanceof Double) {
js.append(valueString + "d");
}
else {
js.append("\"" + valueString + "\"");
}
js.append(");\n");
return true;
}
@Override
public @NonNull Boolean visitCGShadowExp(@NonNull CGShadowExp cgShadowExp) {
/*
CodeGenAnalysis analysis = context.getAnalysis(element);
if (analysis.isConstant()) {
return context.getSnippet(analysis.getConstantValue());
}
final Type type = ClassUtil.nonNullModel(element.getTypeId());
final Class<?> resultClass = Object.class; //context.getBoxedClass(element.getTypeId());
int flags = CodeGenSnippet.NON_NULL | CodeGenSnippet.UNBOXED;
if (/*isValidating* / analysis.isCatching()) {
flags |= CodeGenSnippet.CAUGHT | CodeGenSnippet.MUTABLE;
}
else { //if (/*isValidating* / analysis.isThrowing()) {
flags |= CodeGenSnippet.THROWN;
}
// else {
// flags |= CodeGenSnippet.FINAL;
// }
CodeGenSnippet snippet = new JavaSnippet("", analysis, resultClass, flags);
snippet = snippet.appendText("", new AbstractTextAppender()
{
@Override
public void appendToBody(@NonNull CodeGenText text) {
// text.append("(");
// text.appendClassReference(null, EObject.class);
// text.append(")");
// text.appendClassReference(null, ObjectValue.class);
// text.append(")");
*/
CGExecutorType cgExecutorType = cgShadowExp.getExecutorType();
//
js.appendDeclaration(cgShadowExp);
js.append(" = ");
SubStream castBody = new SubStream() {
@Override
public void append() {
js.appendValueName(cgExecutorType);
js.append(".createInstance()");
}
};
js.appendClassCast(cgShadowExp, castBody);
js.append(";\n");
for (CGShadowPart part : cgShadowExp.getParts()) {
part.accept(this);
}
return true;
}
@Override
public @NonNull Boolean visitCGShadowPart(@NonNull CGShadowPart cgShadowPart) {
/* final OCLExpression initExpression = ClassUtil.nonNullModel(element.getInitExpression());
final Property referredProperty = ClassUtil.nonNullModel(element.getReferredProperty());
ShadowExp eContainer = (ShadowExp)element.eContainer();
final CodeGenSnippet instanceSnippet = context.getSnippet(eContainer);
Class<?> resultClass = Object.class; //context.getBoxedClass(element.getTypeId());
CodeGenSnippet snippet = new JavaSnippet("", context, TypeId.OCL_INVALID, resultClass, element,
CodeGenSnippet.THROWN | CodeGenSnippet.UNASSIGNED | CodeGenSnippet.UNBOXED);
return snippet.appendText("", new AbstractTextAppender()
{
private CodeGenSnippet initSnippet;
@Override
public boolean appendAtHead(@NonNull CodeGenSnippet snippet) {
initSnippet = snippet.appendUnboxedGuardedChild(initExpression, null, DomainMessage.INVALID);
return true;
}
@Override
public void appendToBody(@NonNull CodeGenText text) { */
// appendReferenceTo(context.getSnippet(referredProperty));
CGExecutorShadowPart cgExecutorShadowPart = cgShadowPart.getExecutorPart();
CGValuedElement init = getExpression(cgShadowPart.getInit());
//
if (!js.appendLocalStatements(init)) {
return false;
}
//
js.appendValueName(cgExecutorShadowPart);
js.append(".initValue(");
js.appendValueName(cgShadowPart.getShadowExp());
js.append(", ");
js.appendValueName(init);
js.append(");\n");
return true;
}
@Override
public @NonNull Boolean visitCGString(@NonNull CGString object) {
js.appendDeclaration(object);
js.append(" = ");
js.appendString(ClassUtil.nonNullState(object.getStringValue()));
js.append(";\n");
return true;
}
@Override
public @NonNull Boolean visitCGTemplateParameterExp(@NonNull CGTemplateParameterExp cgTemplateParameterExp) {
CGValuedElement cgType = getExpression(cgTemplateParameterExp.getTemplateableElement());
js.appendDeclaration(cgTemplateParameterExp);
js.append(" = ");
js.appendReferenceTo(cgType);
js.append(".getOwnedSignature().getOwnedParameters().get(" + cgTemplateParameterExp.getIndex() + ");\n");
return true;
}
@Override
public @NonNull Boolean visitCGText(@NonNull CGText cgText) {
js.appendDeclaration(cgText);
js.append(" = ");
js.append(cgText.getTextValue());
js.append(";\n");
return true;
}
@Override
public @NonNull Boolean visitCGThrowExp(@NonNull CGThrowExp cgThrowExp) {
CGValuedElement cgSource = getExpression(cgThrowExp.getSource());
CGInvalid cgInvalidValue;
if (cgSource.isNonInvalid()) {
cgSource.accept(this);
}
else if ((cgInvalidValue = cgSource.getInvalidValue()) != null) {
js.append("throw ");
js.appendReferenceTo(InvalidValueException.class, cgInvalidValue);
js.append(";\n");
return false;
}
else {
if (!js.appendLocalStatements(cgSource)) {
return false;
}
if (cgSource.isCaught()) {
js.append("if (");
js.appendValueName(cgSource);
js.append(" instanceof ");
js.appendClassReference(null, InvalidValueException.class);
js.append(") {\n");
js.pushIndentation(null);
js.append("throw ");
js.appendReferenceTo(InvalidValueException.class, cgSource);
js.append(";\n");
js.popIndentation();
js.append("}\n");
}
}
return true;
}
@Override
public @NonNull Boolean visitCGTupleExp(@NonNull CGTupleExp cgTupleExp) {
Iterable<@NonNull CGTuplePart> parts = CGUtil.getParts(cgTupleExp);
for (@NonNull CGTuplePart cgPart : parts) {
if (!js.appendLocalStatements(CGUtil.getInit(cgPart))) {
return false;
}
}
js.appendDeclaration(cgTupleExp);
js.append(" = ");
js.appendClassReference(null, ValueUtil.class);
js.append(".createTupleOfEach(");
js.appendIdReference(cgTupleExp.getTypeId().getElementId());
int iSize = Iterables.size(parts);
for (@NonNull CGTuplePart cgPart : parts) {
CGValuedElement cgInit = CGUtil.getInit(cgPart);
js.append(", ");
if ((cgInit.isNull()) && (iSize == 1)) {
js.append("(Object)"); // Disambiguate Object... from Object[]
}
js.appendValueName(cgInit);
}
js.append(");\n");
return true;
}
// @Override
// public @NonNull Boolean visitCGTuplePart(@NonNull CGTuplePart cgTuplePart) {
// js.appendLocalStatements(cgTuplePart.getInit());
// return true;
// }
@Override
public @NonNull Boolean visitCGTuplePartCallExp(@NonNull CGTuplePartCallExp cgTuplePartCallExp) {
CGValuedElement source = getExpression(cgTuplePartCallExp.getSource());
// CGTypeId resultType = cgTuplePartCallExp.getTypeId();
// Class<?> requiredBoxedReturnClass = context.getBoxedClass(resultType.getElementId());
TuplePartId partId = cgTuplePartCallExp.getAstTuplePartId();
//
if (!js.appendLocalStatements(source)) {
return false;
}
//
boolean isRequired = cgTuplePartCallExp.isNonNull();
boolean isPrimitive = js.isPrimitive(cgTuplePartCallExp);
if (!isPrimitive && isRequired /*&& (ecoreIsRequired == Boolean.FALSE)*/) {
js.appendSuppressWarningsNull(true);
}
js.appendDeclaration(cgTuplePartCallExp);
js.append(" = ");
// js.appendClassReference(null, ClassUtil.class);
// js.append(".nonNullState(");
SubStream castBody = new SubStream() {
@Override
public void append() {
js.appendAtomicReferenceTo(TupleValue.class, source);
js.append(".getValue(" + partId.getIndex() + "/*" + partId.getName() + "*/)");
}
};
js.appendClassCast(cgTuplePartCallExp, castBody);
// js.append(")");
js.append(";\n");
return true;
}
@Override
public @NonNull Boolean visitCGTypeId(@NonNull CGTypeId cgTypeId) {
if (cgTypeId.isInlined()) {
js.appendIdReference(cgTypeId.getElementId());
}
else {
super.visitCGTypeId(cgTypeId);
}
return true;
}
@Override
public @NonNull Boolean visitCGTypeExp(@NonNull CGTypeExp cgTypeExp) {
// getTypeVariable(cgTypeExp.getReferredType());
// CGExecutorType type = cgTypeExp.getExecutorType();
// if (type != null) {
// type.accept(this);
// }
return true;
}
@Override
public @NonNull Boolean visitCGUnboxExp(@NonNull CGUnboxExp cgUnboxExp) {
CGValuedElement boxedValue = getExpression(cgUnboxExp.getSource());
TypeDescriptor boxedTypeDescriptor = context.getTypeDescriptor(boxedValue);
JavaLocalContext<@NonNull ?> localContext2 = localContext;
assert localContext2 != null;
//
if (!js.appendLocalStatements(boxedValue)) {
return false;
}
return boxedTypeDescriptor.appendUnboxStatements(js, localContext2, cgUnboxExp, boxedValue);
}
@Override
public @NonNull Boolean visitCGUnlimited(@NonNull CGUnlimited object) {
js.appendClassReference(null, ValueUtil.class);
js.append(".UNLIMITED_VALUE");
return true;
}
@Override
public @NonNull Boolean visitCGVariable(@NonNull CGVariable cgVariable) {
CGValuedElement init = cgVariable.getInit();
if (init != null) {
if (!js.appendLocalStatements(init)) {
return false;
}
}
// js.appendDeclaration(cgVariable);
// if (init != null) {
// js.append(" = ");
// js.appendValueName(init);
// }
// js.append(";\n");
return true;
}
@Override
public @NonNull Boolean visitCGVariableExp(@NonNull CGVariableExp cgVariableExp) {
// CGValuedElement variable = cgVariableExp.getReferredVariable();
// if (variable != null) {
// variable.accept(this);
// }
return true;
}
}