blob: 1641d6815c2a5a184ffda6f9ea7a601c79456e56 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013, 2022 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.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.codegen.ecore.genmodel.GenPackage;
import org.eclipse.emf.codegen.util.CodeGenUtil;
import org.eclipse.emf.ecore.EClass;
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.calling.ClassCallingConvention;
import org.eclipse.ocl.examples.codegen.calling.IterationCallingConvention;
import org.eclipse.ocl.examples.codegen.calling.OperationCallingConvention;
import org.eclipse.ocl.examples.codegen.calling.PropertyCallingConvention;
import org.eclipse.ocl.examples.codegen.cgmodel.CGAssertNonNullExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGBodiedProperty;
import org.eclipse.ocl.examples.codegen.cgmodel.CGBoolean;
import org.eclipse.ocl.examples.codegen.cgmodel.CGBoxExp;
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.CGElement;
import org.eclipse.ocl.examples.codegen.cgmodel.CGElementId;
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.CGIndexExp;
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.CGIterationCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGLetExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGMapExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGMapPart;
import org.eclipse.ocl.examples.codegen.cgmodel.CGNamedElement;
import org.eclipse.ocl.examples.codegen.cgmodel.CGNavigationCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGNull;
import org.eclipse.ocl.examples.codegen.cgmodel.CGOperation;
import org.eclipse.ocl.examples.codegen.cgmodel.CGOperationCallExp;
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.CGPropertyAssignment;
import org.eclipse.ocl.examples.codegen.cgmodel.CGReal;
import org.eclipse.ocl.examples.codegen.cgmodel.CGSequence;
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.CGThrowExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGTupleExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGTuplePart;
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.naming.ExecutableNameManager;
import org.eclipse.ocl.examples.codegen.naming.GlobalNameManager;
import org.eclipse.ocl.examples.codegen.naming.GlobalNameManager.NameVariant;
import org.eclipse.ocl.examples.codegen.naming.NameManager;
import org.eclipse.ocl.examples.codegen.naming.NameResolution;
import org.eclipse.ocl.examples.codegen.naming.NestedNameManager;
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.Property;
import org.eclipse.ocl.pivot.Type;
import org.eclipse.ocl.pivot.TypedElement;
import org.eclipse.ocl.pivot.ids.ClassId;
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.TypeId;
import org.eclipse.ocl.pivot.internal.manager.PivotMetamodelManager;
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.LibraryOperation;
import org.eclipse.ocl.pivot.library.LibraryProperty;
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.NameUtil;
import org.eclipse.ocl.pivot.utilities.ValueUtil;
import org.eclipse.ocl.pivot.values.InvalidValueException;
import org.eclipse.ocl.pivot.values.TemplateParameterSubstitutions;
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 extends AbstractExtendingCGModelVisitor<@NonNull Boolean, @NonNull JavaCodeGenerator>
{
protected final @NonNull GlobalNameManager globalNameManager;
// protected final @NonNull ImportNameManager importNameManager;
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<>();;
public CG2JavaVisitor(@NonNull JavaCodeGenerator codeGenerator) {
super(codeGenerator);
this.globalNameManager = codeGenerator.getGlobalNameManager();
this.genModelHelper = context.getGenModelHelper();
this.analyzer = context.getAnalyzer();
this.id2JavaInterfaceVisitor = createId2JavaClassVisitor();
this.environmentFactory = analyzer.getCodeGenerator().getEnvironmentFactory();
this.js = codeGenerator.createJavaStream(this, createImportNameManager());
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 importNameManager.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 Boolean.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 Boolean.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 appendGuardFailure(@NonNull CGGuardExp cgGuardExp) {
js.append("throw new ");
js.appendClassReference(null, InvalidValueException.class);
js.append("(");
js.appendString("Null " + cgGuardExp.getMessage());
js.append(");\n");
}
public void appendQualifiedLiteralName(@NonNull EStructuralFeature eStructuralFeature) {
EClass eContainingClass = ClassUtil.nonNullState(eStructuralFeature.getEContainingClass());
EPackage ePackage = ClassUtil.nonNullState(eContainingClass.getEPackage());
js.appendClassReference(null, genModelHelper.getQualifiedPackageInterfaceName(ePackage));
js.append(".Literals.");
js.append(genModelHelper.getEcoreLiteralName(eStructuralFeature));
}
protected void appendSupportPrefix() {}
protected void appendTablesPrefix() {}
public @Nullable LibraryOperationHandler basicGetLibraryOperationHandler(@NonNull Class<? extends LibraryOperation> libraryOperation) {
return libraryOperation2handler.get(libraryOperation);
}
public String getBodyPrefixedName() {
return "BODY_";
}
public void appendReturn(@NonNull CGValuedElement body) {
if (body instanceof CGLetExp) {
CGLetExp cgLetExp = (CGLetExp)body;
cgLetExp.getInit().accept(this);
CGValuedElement cgIn = CGUtil.getIn(cgLetExp);
appendReturn(cgIn);
}
else if (js.appendLocalStatements(body)) {
CGInvalid cgInvalidValue = body.getInvalidValue();
if (cgInvalidValue != null) {
js.append("throw ");
js.appendValueName(cgInvalidValue);
}
else {
js.append("return ");
js.appendValueName(body);
}
js.append(";\n");
}
}
public void appendSuppressWarningsNull(@NonNull CGValuedElement cgActual, Boolean isNonNull) {
boolean isRequired = cgActual.isRequiredOrNonNull();
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 @NonNull ImportNameManager createImportNameManager() {
return context.createImportNameManager();
}
protected boolean doClassFields(@NonNull CGClass cgClass, boolean needsBlankLine) {
if (cgClass.getProperties().size() > 0) {
if (needsBlankLine) {
js.appendOptionalBlankLine();
}
List<CGProperty> cgProperties = new ArrayList<>(cgClass.getProperties());
Collections.sort(cgProperties, NameUtil.NAMEABLE_COMPARATOR);
for (CGProperty cgProperty : cgProperties) {
cgProperty.accept(this);
}
needsBlankLine = true;
}
return needsBlankLine;
}
protected boolean doClassMethods(@NonNull CGClass cgClass, boolean needsBlankLine) {
List<CGOperation> cgOperations = new ArrayList<>(cgClass.getOperations());
Collections.sort(cgOperations, NameUtil.NAMEABLE_COMPARATOR);
for (CGOperation cgOperation : cgOperations) {
js.appendOptionalBlankLine();
cgOperation.accept(this);
needsBlankLine = true;
}
return needsBlankLine;
}
protected boolean doNestedClasses(@NonNull CGClass cgClass, boolean needsBlankLine) {
List<CGClass> cgClasses = new ArrayList<>(cgClass.getClasses());
Collections.sort(cgClasses, NameUtil.NAMEABLE_COMPARATOR);
for (CGClass cgNestedClass : cgClasses) {
if (needsBlankLine) {
js.appendOptionalBlankLine();
}
cgNestedClass.accept(this);
needsBlankLine = true;
}
return needsBlankLine;
}
public void generateGlobals(@NonNull Iterable<@NonNull ? extends CGValuedElement> sortedElements) {
for (@NonNull CGValuedElement cgElement : sortedElements) {
assert cgElement.isGlobal();
cgElement.accept(this);
}
}
public @NonNull CodeGenAnalyzer getAnalyzer() {
return analyzer;
}
public @NonNull JavaCodeGenerator getCodeGenerator() {
return context;
}
public @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.getCGExpression(cgExpression);
}
public @NonNull GenModelHelper getGenModelHelper() {
return genModelHelper;
}
public @Nullable GenPackage getGenPackage() {
return null;
}
public @NonNull GlobalNameManager getGlobalNameManager() {
return globalNameManager;
}
public @NonNull ImportNameManager getImportNameManager() {
return js.getImportNameManager();
}
public @NonNull JavaStream getJavaStream() {
return js;
}
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;
}
public @NonNull String getVariantResolvedName(@NonNull CGNamedElement cgElement, @NonNull NameVariant nameVariant) {
NestedNameManager nameManager = globalNameManager.useRootExecutableNameManager(cgElement);
String variantResolvedName = nameManager.basicGetVariantResolvedName(cgElement, nameVariant);
if (variantResolvedName == null) {
NameManager basicUseSelfNameManager = globalNameManager.basicUseSelfNameManager(cgElement);
if (basicUseSelfNameManager == null) {
basicUseSelfNameManager = globalNameManager.basicUseSelfNameManager(cgElement);
}
// nameManager = basicUseSelfNameManager;
nameManager = globalNameManager.useSelfNestedNameManager(cgElement);
variantResolvedName = nameManager.basicGetVariantResolvedName(cgElement, nameVariant);
assert variantResolvedName != null;
}
return variantResolvedName;
}
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;
}
@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 Boolean.FALSE;
}
if (!cgSource.isRequiredOrNonNull()) {
js.append("assert ");
js.appendValueName(cgSource);
js.append(" != null;\n");
}
}
return Boolean.TRUE;
}
@Override
public @NonNull Boolean visitCGBodiedProperty(@NonNull CGBodiedProperty cgProperty) {
return cgProperty.getCallingConvention().generateJavaDeclaration(this, cgProperty);
}
@Override
public @NonNull Boolean visitCGBoolean(@NonNull CGBoolean cgBoolean) {
boolean booleanValue = cgBoolean.isBooleanValue();
if (booleanValue) {
js.appendTrue();
}
else {
js.appendFalse();
}
return Boolean.TRUE;
}
@Override
public @NonNull Boolean visitCGBoxExp(@NonNull CGBoxExp cgBoxExp) {
CGValuedElement unboxedValue = getExpression(cgBoxExp.getSource());
TypeDescriptor unboxedTypeDescriptor = context.getTypeDescriptor(unboxedValue);
ExecutableNameManager currentNameManager = globalNameManager.useRootExecutableNameManager(cgBoxExp);
//
if (!js.appendLocalStatements(unboxedValue)) {
return Boolean.FALSE;
}
return unboxedTypeDescriptor.appendBox(js, currentNameManager, cgBoxExp, unboxedValue);
}
@Override
public @NonNull Boolean visitCGCastExp(@NonNull CGCastExp cgCastExp) {
CGValuedElement cgSource = getExpression(cgCastExp.getSource());
if (!js.appendLocalStatements(cgSource)) {
return Boolean.FALSE;
}
js.appendAssignWithCast(cgCastExp, cgSource);
return Boolean.TRUE;
}
@Override
public @NonNull Boolean visitCGCatchExp(@NonNull CGCatchExp cgCatchExp) {
// XXX System.out.println("cg " + NameUtil.debugSimpleName(cgCatchExp) + " in " + NameUtil.debugSimpleName(currentNameManager) + " : " + currentNameManager); // XXX
CGValuedElement cgSource = getExpression(cgCatchExp.getSource());
final String thrownName = getVariantResolvedName(cgCatchExp, context.getTHROWN_NameVariant());
if (cgSource.isNonInvalid()) {
if (!js.appendLocalStatements(cgSource)) {
return Boolean.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)) {
js.popIndentation();
js.append("} catch ("); // FIXME it would be nice to tidy this - occurs for overt invalid return but e.g. testBooleanNot lacks not invalid synthesis
js.appendClassReference(null, Throwable.class);
js.append(" ");
js.append(thrownName);
js.append(") {\n");
js.pushIndentation(null);
js.appendValueName(cgCatchExp);
js.append(" = ");
js.append(thrownName);
js.append(";\n");
// js.append("throw ");
// js.append(thrownName);
// js.append(";\n");
js.popIndentation();
js.append("}\n");
return Boolean.TRUE;
}
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(" ");
js.append(thrownName);
js.append(") {\n");
js.pushIndentation(null);
js.appendValueName(cgCatchExp);
js.append(" = ");
js.appendClassReference(null, ValueUtil.class);
js.append(".createInvalidValue(");
js.append(thrownName);
js.append(");\n");
js.popIndentation();
js.append("}\n");
}
return Boolean.TRUE;
}
@Override
public @NonNull Boolean visitCGClass(@NonNull CGClass cgClass) {
ClassCallingConvention callingConvention = cgClass.getCallingConvention();
callingConvention.generateJavaDeclaration(this, cgClass);
return Boolean.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 Boolean.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 = currentNameManager.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 = currentNameManager.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 Boolean.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 Boolean.FALSE;
}
if (!js.appendLocalStatements(last)) {
return Boolean.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 Boolean.FALSE;
}
}
}
return Boolean.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 Boolean.TRUE;
}
@Override
public @NonNull Boolean visitCGConstraint(@NonNull CGConstraint cgConstraint) {
Boolean flowContinues = super.visitCGConstraint(cgConstraint);
assert flowContinues != null;
return flowContinues;
}
@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 Boolean.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 Boolean.TRUE;
}
@Override
public @NonNull Boolean visitCGEcoreExp(@NonNull CGEcoreExp cgEcoreExp) {
CGValuedElement boxedValue = getExpression(cgEcoreExp.getSource());
TypeDescriptor boxedTypeDescriptor = context.getTypeDescriptor(boxedValue);
ExecutableNameManager currentNameManager = globalNameManager.useRootExecutableNameManager(cgEcoreExp);
//
if (!js.appendLocalStatements(boxedValue)) {
return Boolean.FALSE;
}
/* EClassifier eClassifier = cgEcoreExp.getEClassifier();
if (eClassifier != null) { // FIXME ignores Collections
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 Boolean.TRUE;
}
}
} */
// return boxedTypeDescriptor.getEcoreDescriptor(context, null).appendEcore(js, currentNameManager2, cgEcoreExp, boxedValue);
return boxedTypeDescriptor.appendEcoreStatements(js, currentNameManager, cgEcoreExp, boxedValue);
}
@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(cgElementId.getResolvedName());
js.append(" = ");
js.appendIdReference2(elementId);
js.append(";\n");
}
return Boolean.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 Boolean.TRUE;
} */
/* @Override
public @NonNull Boolean visitCGExecutorShadowPart(@NonNull CGExecutorShadowPart cgExecutorShadowPart) {
js.appendDeclaration(cgExecutorShadowPart);
js.append(" = ");
js.appendValueName(currentNameManager.getIdResolverVariable());
js.append(".getProperty(");
js.appendIdReference(cgExecutorShadowPart.getUnderlyingPropertyId().getElementId());
js.append(");\n");
return Boolean.TRUE;
} */
/* @Override
public @NonNull Boolean visitCGExecutorOperation(@NonNull CGExecutorOperation cgExecutorOperation) {
js.appendDeclaration(cgExecutorOperation);
js.append(" = ");
try {
js.appendValueName(currentNameManager.getIdResolverVariable());
}
catch (Exception e) { // FIXME
js.appendString(String.valueOf(e));
}
js.append(".getOperation(");
js.appendIdReference(cgExecutorOperation.getUnderlyingOperationId().getElementId());
js.append(");\n");
SubStream castBody = new SubStream() {
@Override
public void append() {
try {
js.appendValueName(currentNameManager.getIdResolverVariable());
}
catch (Exception e) { // FIXME
js.appendString(String.valueOf(e));
}
js.append(".getOperation(");
js.appendIdReference(cgExecutorOperation.getUnderlyingOperationId().getElementId());
js.append(")");
}
};
js.appendClassCast(cgExecutorOperation, castBody);
js.append(";\n");
return Boolean.TRUE;
} */
/* @Override
public @NonNull Boolean visitCGExecutorOperationCallExp(@NonNull CGExecutorOperationCallExp cgOperationCallExp) {
Operation pOperation = cgOperationCallExp.getReferredOperation();
CGValuedElement cgThis = cgOperationCallExp.getCgThis();
CGValuedElement cgSource = cgThis != null ? getExpression(cgThis) : null;
List<CGValuedElement> cgArguments = cgOperationCallExp.getCgArguments();
List<Parameter> pParameters = pOperation.getOwnedParameters();
//
if ((cgSource != null) && !js.appendLocalStatements(cgSource)) {
return Boolean.FALSE;
}
for (@SuppressWarnings("null")@NonNull CGValuedElement cgArgument : cgArguments) {
CGValuedElement argument = getExpression(cgArgument);
if (!js.appendLocalStatements(argument)) {
return Boolean.FALSE;
}
}
//
js.appendDeclaration(cgOperationCallExp);
js.append(" = ");
SubStream castBody = new SubStream() {
@Override
public void append() {
js.appendReferenceTo(cgOperationCallExp.getExecutorOperation());
js.append(".");
js.append(context.getEvaluateName());
js.append("(");
// js.append(getValueName(currentNameManager.getEvaluatorParameter(cgOperationCallExp)));
js.append(context.getExecutorName());
js.append(", ");
js.appendIdReference(cgOperationCallExp.getASTypeId());
if (cgSource != null) {
js.append(", ");
js.appendValueName(cgSource);
}
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 Boolean.TRUE;
} */
/* @Override
public @NonNull Boolean visitCGExecutorProperty(@NonNull CGExecutorProperty cgExecutorProperty) {
return cgExecutorProperty.getCallingConvention().generateJavaDeclaration(this, js, cgExecutorProperty);
} */
@Override
public @NonNull Boolean visitCGExecutorType(@NonNull CGExecutorType cgExecutorType) {
js.appendDeclaration(cgExecutorType);
js.append(" = ");
SubStream castBody1 = new SubStream() {
@Override
public void append() {
js.appendValueName(globalNameManager.useRootExecutableNameManager(cgExecutorType).lazyGetIdResolverVariable());
js.append(".getClass(");
js.appendIdReference(CGUtil.getAST(cgExecutorType).getTypeId());
js.append(", null)");
}
};
js.appendClassCast(cgExecutorType, null, org.eclipse.ocl.pivot.Class.class, castBody1);
js.append(";\n");
return Boolean.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("(\"Unconditionally null\")");
// js.append("();\n");
}
else {
if (!js.appendLocalStatements(cgSource)) {
return Boolean.FALSE;
}
if (cgGuardExp.isSafe()) {
js.append("assert ");
js.appendValueName(cgSource);
js.append(" != null;\n");
}
else if (!cgSource.isRequiredOrNonNull()) {
js.append("if (");
js.appendValueName(cgSource);
js.append(" == null) {\n");
js.pushIndentation(null);
appendGuardFailure(cgGuardExp);
js.popIndentation();
js.append("}\n");
}
}
return Boolean.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 = currentNameManager.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 visitCGIndexExp(@NonNull CGIndexExp cgIndexExp) {
CGValuedElement cgSource = getExpression(cgIndexExp.getSource());
if (!js.appendLocalStatements(cgSource)) {
return Boolean.FALSE;
}
SubStream castBody = new SubStream() {
@Override
public void append() {
js.appendValueName(cgSource);
js.append("[" + cgIndexExp.getIndex() + "]");
}
};
boolean sourceRequired = cgSource.isRequired();
TypeDescriptor sourceTypeDescriptor = context.getTypeDescriptor(cgSource);
Class<?> sourceClass = sourceTypeDescriptor.getJavaClass().getComponentType();
assert sourceClass != null;
js.appendAssignWithCast(cgIndexExp, sourceRequired, sourceClass, castBody);
return Boolean.TRUE;
}
@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 Boolean.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 Boolean.TRUE;
}
@Override
public @NonNull Boolean visitCGIsEqualExp(@NonNull CGIsEqualExp cgIsEqualExp) { // FIXME BUG 421738 move irregulaties to e.g. BooleanPrimitiveDescriptor
if (cgIsEqualExp.isTrue()) {
js.appendAssignBooleanLiteral(false, cgIsEqualExp, true);
}
else if (cgIsEqualExp.isFalse()) {
js.appendAssignBooleanLiteral(false, cgIsEqualExp, false);
}
else {
CGValuedElement cgSource = getExpression(cgIsEqualExp.getSource());
CGValuedElement cgArgument = getExpression(cgIsEqualExp.getArgument());
if (!js.appendLocalStatements(cgSource)) {
return Boolean.FALSE;
}
if (!js.appendLocalStatements(cgArgument)) {
return Boolean.FALSE;
}
//
boolean notEquals = cgIsEqualExp.isNotEquals();
js.appendDeclaration(cgIsEqualExp);
js.append(" = ");
if (cgSource.isNull()) {
if (cgArgument.isNull()) {
js.appendBooleanString(true ^ notEquals);
}
else if (cgArgument.isRequiredOrNonNull()) {
js.appendBooleanString(false ^ notEquals);
}
else {
js.appendValueName(cgArgument);
js.append(notEquals ? " != " : " == ");
js.append("null");
}
}
else if (cgArgument.isNull()) {
if (cgSource.isRequiredOrNonNull()) {
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 Boolean.TRUE;
}
@Override
public @NonNull Boolean visitCGIsEqual2Exp(@NonNull CGIsEqual2Exp cgIsEqualExp) { // FIXME BUG 421738 move irregulaties to e.g. BooleanPrimitiveDescriptor
if (cgIsEqualExp.isTrue()) {
js.appendAssignBooleanLiteral(false, cgIsEqualExp, true);
}
else if (cgIsEqualExp.isFalse()) {
js.appendAssignBooleanLiteral(false, cgIsEqualExp, false);
}
else {
CGValuedElement cgSource = getExpression(cgIsEqualExp.getSource());
CGValuedElement cgArgument = getExpression(cgIsEqualExp.getArgument());
if (!js.appendLocalStatements(cgSource)) {
return Boolean.FALSE;
}
if (!js.appendLocalStatements(cgArgument)) {
return Boolean.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.isRequiredOrNonNull()) {
js.appendBooleanString(false);
}
else {
js.appendValueName(cgArgument);
js.append(" == ");
js.append("null");
}
}
else if (isNull2 && !isNull1) {
if (cgSource.isRequiredOrNonNull()) {
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 Boolean.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 Boolean.FALSE;
}
//
js.appendDeclaration(cgIsInvalidExp);
js.append(" = ");
js.appendValueName(cgSource);
js.append(" instanceof ");
js.appendClassReference(null, InvalidValueException.class);
js.append(";\n");
}
return Boolean.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 Boolean.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.isRequiredOrNonNull();
if (!js.appendLocalStatements(cgSource)) {
return Boolean.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 Boolean.TRUE;
}
@Override
public @NonNull Boolean visitCGLetExp(@NonNull CGLetExp cgLetExp) {
cgLetExp.getInit().accept(this);
CGValuedElement cgIn = CGUtil.getIn(cgLetExp);
if (!js.appendLocalStatements(cgIn)) {
return Boolean.FALSE;
}
if (cgIn.isInlined()) {
return cgIn.accept(this);
}
// System.out.println("Fallback for " + NameUtil.debugSimpleName(cgLetExp) + " : " + NameUtil.debugSimpleName(cgLetExp.basicGetNameResolution()));
// System.out.println(" in " + NameUtil.debugSimpleName(cgIn) + " : " + NameUtil.debugSimpleName(cgIn.basicGetNameResolution()));
// The following fallback would not be required if the inner name propagated better, see testBug458724
// (a rewrite of an in might fail to re-down-propagate the let name).
if (!cgIn.isInlined()) {
NameResolution inNameResolution = cgIn.getNameResolution();
NameResolution letNameResolution = cgLetExp.getNameResolution();
if (inNameResolution != letNameResolution) {
js.appendDeclaration(cgLetExp);
js.append(" = ");
js.appendValueName(cgIn);
js.append(";\n");
}
}
return Boolean.TRUE;
}
@Override
public @NonNull Boolean visitCGIterationCallExp(@NonNull CGIterationCallExp cgIterationCallExp) {
CGOperation cgIteration = CGUtil.getReferredIteration(cgIterationCallExp);
IterationCallingConvention callingConvention = (IterationCallingConvention)cgIteration.getCallingConvention();
return callingConvention.generateJavaCall(this, cgIterationCallExp);
}
/* @Override
public @NonNull Boolean visitCGLibraryOperation(@NonNull CGLibraryOperation cgOperation) {
currentNameManager = context.getLocalContext(cgOperation);
try {
List<CGParameter> cgParameters = cgOperation.getParameters();
String operationName = JavaConstants.FOREIGN_OPERATION_PREFIX + cgOperation.getName();
assert operationName != null;
js.appendCommentWithOCL(null, cgOperation.getAst());
// assert false; // XXX
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(context.getInstanceName());
js.append(" = new ");
js.append(operationName);
js.append("();\n");
js.appendOptionalBlankLine();
// js.append("public static final ");
// CGValuedElement evaluatorParameter = currentNameManager2.getEvaluatorParameter(cgOperation);
// CGParameter typeIdParameter = currentNameManager2.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(null/ *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 {
popNameManager();
}
return Boolean.TRUE;
} */
@Override
public @NonNull Boolean visitCGMapExp(@NonNull CGMapExp cgMapExp) {
for (CGMapPart cgPart : cgMapExp.getParts()) {
if ((cgPart != null) && !js.appendLocalStatements(cgPart)) {
return Boolean.FALSE;
}
}
js.appendDeclaration(cgMapExp);
js.append(" = ");
js.appendClassReference(null, ValueUtil.class);
js.append(".createMapOfEach(");
// CGTypeVariable typeVariable = currentNameManager.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 Boolean.TRUE;
}
@Override
public @NonNull Boolean visitCGMapPart(@NonNull CGMapPart cgMapPart) {
CGValuedElement key = getExpression(cgMapPart.getKey());
CGValuedElement value = getExpression(cgMapPart.getValue());
if (!js.appendLocalStatements(key)) {
return Boolean.FALSE;
}
if (!js.appendLocalStatements(value)) {
return Boolean.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 Boolean.TRUE;
}
/* @Override // FIXME revert to the pre-cached code
public @NonNull Boolean visitCGNativeOperation(@NonNull CGNativeOperation cgOperation) {
Operation asOperation = (Operation) cgOperation.getAst();
assert asOperation != null;
currentNameManager = globalContext.findLocalContext(cgOperation);
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.appendOptionalBlankLine();
doCachedOperationEvaluate(cgOperation);
js.popClassBody(false);
//
js.appendOptionalBlankLine();
doCachedOperationClassInstance(cgOperation);
}
finally {
popNameManager();
}
return Boolean.TRUE;
} */
@Override
public @NonNull Boolean visitCGNavigationCallExp(@NonNull CGNavigationCallExp cgNavigationCallExp) {
CGProperty cgProperty = cgNavigationCallExp.getReferredProperty();
PropertyCallingConvention callingConvention = cgProperty.getCallingConvention();
return callingConvention.generateJavaCall(this, cgNavigationCallExp);
}
@Override
public @NonNull Boolean visitCGNull(@NonNull CGNull object) {
js.append("null");
return Boolean.TRUE;
}
@Override
public @NonNull Boolean visitCGOperation(@NonNull CGOperation cgOperation) {
// System.out.println("visitCGOperation " + NameUtil.debugSimpleName(cgOperation) + " : " + cgOperation.getAst());
OperationCallingConvention callingConvention = cgOperation.getCallingConvention();
callingConvention.generateJavaDeclaration(this, cgOperation);
return Boolean.TRUE;
}
@Override
public @NonNull Boolean visitCGOperationCallExp(@NonNull CGOperationCallExp cgOperationCallExp) {
CGOperation cgOperation = cgOperationCallExp.getReferredOperation();
OperationCallingConvention callingConvention = cgOperation.getCallingConvention();
return callingConvention.generateJavaCall(this, cgOperationCallExp);
}
@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 Boolean.TRUE;
}
@Override
public @NonNull Boolean visitCGParameter(@NonNull CGParameter object) {
return Boolean.TRUE; // Parameters are declared by their Operation
}
@Override
public @NonNull Boolean visitCGProperty(@NonNull CGProperty cgProperty) {
return cgProperty.getCallingConvention().generateJavaDeclaration(this, cgProperty);
}
@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 Boolean.TRUE;
}
@Override
public @NonNull Boolean visitCGPropertyAssignment(@NonNull CGPropertyAssignment cgPropertyAssignment) {
CGProperty cgProperty = cgPropertyAssignment.getReferredProperty();
CGValuedElement slotValue = CGUtil.getOwnedSlotValue(cgPropertyAssignment);
CGValuedElement initValue = CGUtil.getOwnedInitValue(cgPropertyAssignment);
if (initValue.isInvalid()) {
js.appendValueName(initValue);
return Boolean.FALSE;
}
if (!js.appendLocalStatements(slotValue)) {
return Boolean.FALSE;
}
if (!js.appendLocalStatements(initValue)) {
return Boolean.FALSE;
}
cgProperty.getCallingConvention().generateJavaAssignment(this, cgPropertyAssignment);
return Boolean.TRUE;
}
@Override
public @NonNull Boolean visitCGSequence(@NonNull CGSequence cgSequence) {
for (@NonNull CGValuedElement cgStatement : ClassUtil.nullFree(cgSequence.getOwnedStatements())) {
cgStatement.accept(this);
}
return Boolean.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 = CGUtil.getExecutorType(cgShadowExp);
//
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 Boolean.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 Boolean.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 Boolean.FALSE;
}
//
js.appendValueName(cgExecutorShadowPart); // XXX use super
js.append(".initValue(");
js.appendValueName(cgShadowPart.getShadowExp());
js.append(", ");
js.appendValueName(init);
js.append(");\n");
return Boolean.TRUE;
}
@Override
public @NonNull Boolean visitCGString(@NonNull CGString object) {
js.appendDeclaration(object);
js.append(" = ");
js.appendString(ClassUtil.nonNullState(object.getStringValue()));
js.append(";\n");
return Boolean.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 Boolean.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 Boolean.FALSE;
}
else {
if (!js.appendLocalStatements(cgSource)) {
return Boolean.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");
js.appendDeclaration(cgThrowExp);
js.append(" = ");
js.appendClassCast(cgThrowExp, new SubStream() {
@Override
public void append() {
js.appendValueName(cgSource);
}
});
js.append(";\n");
}
}
return Boolean.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 Boolean.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 Boolean.TRUE;
}
// @Override
// public @NonNull Boolean visitCGTuplePart(@NonNull CGTuplePart cgTuplePart) {
// js.appendLocalStatements(cgTuplePart.getInit());
// return Boolean.TRUE;
// }
@Override
public @NonNull Boolean visitCGTypeId(@NonNull CGTypeId cgTypeId) {
if (cgTypeId.isInlined()) {
js.appendIdReference(cgTypeId.getElementId());
}
else {
super.visitCGTypeId(cgTypeId);
}
return Boolean.TRUE;
}
@Override
public @NonNull Boolean visitCGTypeExp(@NonNull CGTypeExp cgTypeExp) {
// getTypeVariable(cgTypeExp.getReferredType());
// CGExecutorType type = cgTypeExp.getExecutorType();
// if (type != null) {
// type.accept(this);
// }
return Boolean.TRUE;
}
@Override
public @NonNull Boolean visitCGUnboxExp(@NonNull CGUnboxExp cgUnboxExp) {
CGValuedElement boxedValue = getExpression(cgUnboxExp.getSource());
TypeDescriptor boxedTypeDescriptor = context.getTypeDescriptor(boxedValue);
ExecutableNameManager currentNameManager = globalNameManager.useRootExecutableNameManager(cgUnboxExp);
//
if (!js.appendLocalStatements(boxedValue)) {
return Boolean.FALSE;
}
return boxedTypeDescriptor.appendUnboxStatements(js, currentNameManager, cgUnboxExp, boxedValue);
}
@Override
public @NonNull Boolean visitCGUnlimited(@NonNull CGUnlimited object) {
js.appendClassReference(null, ValueUtil.class);
js.append(".UNLIMITED_VALUE");
return Boolean.TRUE;
}
@Override
public @NonNull Boolean visitCGVariable(@NonNull CGVariable cgVariable) {
CGValuedElement cgInit = cgVariable.getInit();
if (cgInit != null) {
if (!js.appendLocalStatements(cgInit)) {
return Boolean.FALSE;
}
if (!cgInit.isGlobal()) {
// The following fallback would not be required if the init name propagated better, see testSysML_QUDV
// (a rewrite of an init might fail to re-down-propagate the variable name).
NameResolution varNameResolution = cgVariable.getNameResolution();
// if (varNameResolution == varNameResolution.getNameResolution()) { // A variant did not need propagating.
NameResolution initNameResolution = cgInit.getNameResolution();//.getNameResolution();
if (varNameResolution != initNameResolution) {
boolean hasAccess = false;
assert false;
Iterable<@NonNull CGValuedElement> cgElements = null; // XXX varNameResolution.getCGElements();
if (cgElements != null) {
for (CGValuedElement cgElement : cgElements) {
if (cgElement instanceof CGVariableExp) {
CGPackage cgPackage = CGUtil.basicGetContainingPackage(cgElement);
if (cgPackage != null) {
hasAccess = true;
break;
}
}
}
}
if (hasAccess) {
js.appendDeclaration(cgVariable);
js.append(" = ");
js.appendValueName(cgInit);
js.append(";\n");
}
}
// }
}
}
return Boolean.TRUE;
}
@Override
public @NonNull Boolean visitCGVariableExp(@NonNull CGVariableExp cgVariableExp) {
// CGValuedElement variable = cgVariableExp.getReferredVariable();
// if (variable != null) {
// variable.accept(this);
// }
return Boolean.TRUE;
}
}