| /******************************************************************************* |
| * Copyright (c) 2013, 2016 Willink Transformations and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * E.D.Willink - Initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.qvtd.codegen.qvti.java; |
| |
| import java.lang.reflect.Method; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.emf.common.notify.Adapter; |
| import org.eclipse.emf.ecore.EClassifier; |
| 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.NameManager; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGAccumulator; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGClass; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGCollectionExp; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGEcorePropertyCallExp; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGExecutorProperty; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGIterator; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGLetExp; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGNavigationCallExp; |
| 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.CGShadowExp; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGShadowPart; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGTypeId; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGUnboxExp; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGValuedElement; |
| import org.eclipse.ocl.examples.codegen.generator.TypeDescriptor; |
| import org.eclipse.ocl.examples.codegen.java.CG2JavaVisitor; |
| import org.eclipse.ocl.examples.codegen.java.JavaConstants; |
| import org.eclipse.ocl.examples.codegen.java.JavaLocalContext; |
| import org.eclipse.ocl.examples.codegen.java.JavaStream; |
| import org.eclipse.ocl.examples.codegen.java.types.BoxedDescriptor; |
| import org.eclipse.ocl.examples.codegen.utilities.CGUtil; |
| import org.eclipse.ocl.pivot.Element; |
| import org.eclipse.ocl.pivot.NavigationCallExp; |
| import org.eclipse.ocl.pivot.Operation; |
| import org.eclipse.ocl.pivot.Parameter; |
| import org.eclipse.ocl.pivot.Property; |
| import org.eclipse.ocl.pivot.SetType; |
| import org.eclipse.ocl.pivot.ShadowPart; |
| import org.eclipse.ocl.pivot.VariableDeclaration; |
| import org.eclipse.ocl.pivot.evaluation.Executor; |
| 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.IdResolver; |
| import org.eclipse.ocl.pivot.ids.TypeId; |
| import org.eclipse.ocl.pivot.internal.manager.PivotMetamodelManager; |
| 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.PivotUtil; |
| import org.eclipse.ocl.pivot.utilities.ValueUtil; |
| import org.eclipse.qvtd.codegen.qvti.analyzer.QVTiAS2CGVisitor; |
| import org.eclipse.qvtd.codegen.qvti.analyzer.QVTiAnalyzer; |
| import org.eclipse.qvtd.codegen.qvticgmodel.CGConnectionAssignment; |
| import org.eclipse.qvtd.codegen.qvticgmodel.CGConnectionVariable; |
| import org.eclipse.qvtd.codegen.qvticgmodel.CGEcoreContainerAssignment; |
| import org.eclipse.qvtd.codegen.qvticgmodel.CGEcorePropertyAssignment; |
| import org.eclipse.qvtd.codegen.qvticgmodel.CGEcoreRealizedVariable; |
| import org.eclipse.qvtd.codegen.qvticgmodel.CGFunction; |
| import org.eclipse.qvtd.codegen.qvticgmodel.CGFunctionCallExp; |
| import org.eclipse.qvtd.codegen.qvticgmodel.CGFunctionParameter; |
| import org.eclipse.qvtd.codegen.qvticgmodel.CGGuardVariable; |
| import org.eclipse.qvtd.codegen.qvticgmodel.CGMapping; |
| import org.eclipse.qvtd.codegen.qvticgmodel.CGMappingCall; |
| import org.eclipse.qvtd.codegen.qvticgmodel.CGMappingCallBinding; |
| import org.eclipse.qvtd.codegen.qvticgmodel.CGMappingExp; |
| import org.eclipse.qvtd.codegen.qvticgmodel.CGMappingLoop; |
| import org.eclipse.qvtd.codegen.qvticgmodel.CGMiddlePropertyAssignment; |
| import org.eclipse.qvtd.codegen.qvticgmodel.CGMiddlePropertyCallExp; |
| import org.eclipse.qvtd.codegen.qvticgmodel.CGPropertyAssignment; |
| import org.eclipse.qvtd.codegen.qvticgmodel.CGRealizedVariable; |
| import org.eclipse.qvtd.codegen.qvticgmodel.CGSequence; |
| import org.eclipse.qvtd.codegen.qvticgmodel.CGTransformation; |
| import org.eclipse.qvtd.codegen.qvticgmodel.CGTypedModel; |
| import org.eclipse.qvtd.codegen.qvticgmodel.util.QVTiCGModelVisitor; |
| import org.eclipse.qvtd.codegen.utilities.QVTiCGUtil; |
| import org.eclipse.qvtd.pivot.qvtimperative.ConnectionVariable; |
| import org.eclipse.qvtd.pivot.qvtimperative.ImperativeTransformation; |
| import org.eclipse.qvtd.pivot.qvtimperative.ImperativeTypedModel; |
| import org.eclipse.qvtd.pivot.qvtimperative.Mapping; |
| import org.eclipse.qvtd.pivot.qvtimperative.MappingCall; |
| import org.eclipse.qvtd.pivot.qvtimperative.MappingParameterBinding; |
| import org.eclipse.qvtd.pivot.qvtimperative.ObservableStatement; |
| import org.eclipse.qvtd.pivot.qvtimperative.SetStatement; |
| import org.eclipse.qvtd.pivot.qvtimperative.evaluation.QVTiTransformationAnalysis; |
| import org.eclipse.qvtd.pivot.qvtimperative.utilities.QVTimperativeUtil; |
| import org.eclipse.qvtd.runtime.evaluation.AbstractInvocation; |
| import org.eclipse.qvtd.runtime.evaluation.AbstractTransformer; |
| import org.eclipse.qvtd.runtime.evaluation.AbstractValueOccurrence; |
| import org.eclipse.qvtd.runtime.evaluation.InvocationManager; |
| import org.eclipse.qvtd.runtime.evaluation.ObjectManager; |
| import org.eclipse.qvtd.runtime.evaluation.Transformer; |
| import org.eclipse.qvtd.runtime.internal.evaluation.AbstractComputationConstructor; |
| import org.eclipse.qvtd.runtime.internal.evaluation.AbstractInvocationConstructor; |
| import org.eclipse.qvtd.runtime.internal.evaluation.IncrementalInvocationManager; |
| import org.eclipse.qvtd.runtime.internal.evaluation.IncrementalObjectManager; |
| |
| import com.google.common.collect.Iterables; |
| |
| /** |
| * A QVTiCG2JavaVisitor supports generation of Java code from an optimized QVTi CG transformation tree. |
| */ |
| public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerator> implements QVTiCGModelVisitor<@NonNull Boolean> |
| { |
| /** |
| * The run-time API version. |
| * |
| * @noreference this is solely for development usage. |
| */ |
| public static int RUN_TIME_EVALUATOR_API_VERSION = Transformer.RUN_TIME_EVALUATOR_API_VERSION_1_1_0_2; |
| |
| protected final @NonNull QVTiAnalyzer analyzer; |
| protected final @NonNull CGPackage cgPackage; |
| protected final @Nullable Iterable<@NonNull CGValuedElement> sortedGlobals; |
| protected boolean isIncremental = false; |
| protected boolean alwaysUseClasses = false; |
| protected boolean useGot = true; |
| protected QVTiTransformationAnalysis transformationAnalysis; |
| |
| public QVTiCG2JavaVisitor(@NonNull QVTiCodeGenerator codeGenerator, @NonNull CGPackage cgPackage, |
| @Nullable Iterable<@NonNull CGValuedElement> sortedGlobals) { |
| super(codeGenerator); |
| this.analyzer = codeGenerator.getAnalyzer(); |
| this.cgPackage = cgPackage; |
| this.sortedGlobals = sortedGlobals; |
| this.isIncremental = codeGenerator.getOptions().isIncremental(); |
| this.alwaysUseClasses = isIncremental; |
| this.useGot = isIncremental; |
| } |
| |
| protected void appendEcoreSet(@NonNull CGValuedElement cgSlot, @NonNull EStructuralFeature eStructuralFeature, @NonNull CGValuedElement cgInit) { |
| if (eStructuralFeature.isMany()) { |
| String getAccessor = genModelHelper.getGetAccessor(eStructuralFeature); |
| // |
| js.appendValueName(cgSlot); |
| js.append("."); |
| js.append(getAccessor); |
| js.append("().addAll("); |
| js.appendAtomicReferenceTo(cgInit); |
| js.append(");\n"); |
| } |
| else { |
| String setAccessor = genModelHelper.getSetAccessor(eStructuralFeature); |
| // |
| js.appendValueName(cgSlot); |
| js.append("."); |
| js.append(setAccessor); |
| js.append("("); |
| js.appendAtomicReferenceTo(cgInit); |
| js.append(");\n"); |
| } |
| } |
| |
| protected void appendModelIndex(@Nullable CGTypedModel cgTypedModel) { |
| if (cgTypedModel == null) { |
| js.append("-1/*null*/"); |
| } |
| else { |
| js.append(cgTypedModel.getModelIndex() + "/*" + cgTypedModel.getName() + "*/"); |
| } |
| } |
| |
| protected void doAddRealization(@NonNull CGRealizedVariable cgRealizedVariable) { |
| CGTypedModel cgTypedModel = cgRealizedVariable.getTypedModel(); |
| // |
| js.append(QVTiGlobalContext.MODELS_NAME); |
| js.append("["); |
| appendModelIndex(cgTypedModel); |
| js.append("].add("); |
| js.appendValueName(cgRealizedVariable); |
| js.append(");\n"); |
| // |
| if (isIncremental) { |
| js.append("objectManager.created(this, "); |
| js.appendValueName(cgRealizedVariable); |
| js.append(");\n"); |
| } |
| } |
| |
| protected @NonNull String @Nullable [] doAllInstances(@NonNull QVTiTransformationAnalysis transformationAnalysis) { |
| Set<org.eclipse.ocl.pivot.@NonNull Class> allInstancesClasses = transformationAnalysis.getAllInstancesClasses(); |
| if (allInstancesClasses.size() > 0) { |
| NameManager nameManager = getGlobalContext().getNameManager(); |
| Map<org.eclipse.ocl.pivot.@NonNull Class, @Nullable List<org.eclipse.ocl.pivot.@NonNull Class>> instancesClassAnalysis = transformationAnalysis.getInstancesClassAnalysis(allInstancesClasses); |
| // |
| // Populate a mapping from instancesClass to linear index. |
| // |
| Map<org.eclipse.ocl.pivot.@NonNull Class, @NonNull Integer> instancesClass2index = new HashMap<org.eclipse.ocl.pivot.@NonNull Class, @NonNull Integer>(instancesClassAnalysis.size()); |
| List<org.eclipse.ocl.pivot.@NonNull Class> sortedList = new ArrayList<org.eclipse.ocl.pivot.@NonNull Class>(instancesClassAnalysis.keySet()); |
| Collections.sort(sortedList, NameUtil.NameableComparator.INSTANCE); |
| for (int i = 0; i < sortedList.size(); i++) { |
| instancesClass2index.put(sortedList.get(i), i); |
| } |
| // |
| // Emit the ClassId array |
| // |
| js.append("/*\n"); |
| js.append(" * Array of the ClassIds of each class for which allInstances() may be invoked. Array index is the ClassIndex.\n"); |
| js.append(" */\n"); |
| String classIndex2classIdName = nameManager.getGlobalSymbolName(null, "classIndex2classId"); |
| js.append("private static final "); |
| js.appendIsRequired(true); |
| js.append(" "); |
| js.appendClassReference(ClassId.class); |
| js.append("[] "); |
| js.append(classIndex2classIdName); |
| js.append(" = new "); |
| js.appendIsRequired(true); |
| js.append(" "); |
| js.appendClassReference(ClassId.class); |
| js.append("[]{\n"); |
| js.pushIndentation(null); |
| for (int i = 0; i < sortedList.size(); i++) { |
| org.eclipse.ocl.pivot.Class instancesClass = sortedList.get(i); |
| CGTypeId cgTypeId = getCodeGenerator().getAnalyzer().getTypeId(instancesClass.getTypeId()); |
| int startLength = js.length(); |
| js.appendValueName(cgTypeId); |
| if ((i+1) < sortedList.size()) { |
| js.append(","); |
| } |
| for (int j = js.length() - startLength; j < 40; j++) { |
| js.append(" "); |
| } |
| js.append("// " + i + " => " + instancesClass.getName() + "\n"); |
| } |
| js.popIndentation(); |
| js.append("};\n"); |
| // |
| // Emit the classIndex2allClassIndexes array of arrays |
| // |
| String classIndex2allClassIndexes = nameManager.getGlobalSymbolName(null, "classIndex2allClassIndexes"); |
| js.append("\n"); |
| js.append("/*\n"); |
| js.append(" * Mapping from each ClassIndex to all the ClassIndexes to which an object of the outer index\n"); |
| js.append(" * may contribute results to an allInstances() invocation.\n"); |
| js.append(" * Non trivial inner arrays arise when one ClassId is a derivation of another and so an\n"); |
| js.append(" * instance of the derived classId contributes to derived and inherited ClassIndexes.\n"); |
| js.append(" */\n"); |
| js.append("private final static "); |
| js.appendClassReference(int.class); |
| js.append(" "); |
| js.appendIsRequired(true); |
| js.append(" [] "); |
| js.appendIsRequired(true); |
| js.append(" [] "); |
| js.append(classIndex2allClassIndexes); |
| js.append(" = new "); |
| js.appendClassReference(int.class); |
| js.append(" "); |
| js.appendIsRequired(true); |
| js.append(" [] "); |
| js.appendIsRequired(true); |
| js.append(" [] {\n"); |
| js.pushIndentation(null); |
| for (int i = 0; i < sortedList.size(); i++) { |
| org.eclipse.ocl.pivot.Class instancesClass = sortedList.get(i); |
| List<org.eclipse.ocl.pivot.@NonNull Class> superInstancesClasses = ClassUtil.nonNullState(instancesClassAnalysis.get(instancesClass)); |
| int startLength = js.length(); |
| js.append("{"); |
| boolean isFirst = true; |
| for (org.eclipse.ocl.pivot.@NonNull Class superInstancesClass : superInstancesClasses) { |
| if (!isFirst) { |
| js.append(","); |
| } |
| js.append("" + instancesClass2index.get(superInstancesClass)); |
| isFirst = false; |
| } |
| js.append("}"); |
| if ((i+1) < sortedList.size()) { |
| js.append(","); |
| } |
| for (int j = js.length() - startLength; j < 32; j++) { |
| js.append(" "); |
| } |
| js.append("// " + i + " : "); |
| js.append(instancesClass.getName()); |
| js.append(" -> {"); |
| isFirst = true; |
| for (org.eclipse.ocl.pivot.@NonNull Class superInstancesClass : superInstancesClasses) { |
| if (!isFirst) { |
| js.append(","); |
| } |
| js.append(superInstancesClass.getName()); |
| isFirst = false; |
| } |
| js.append("}\n"); |
| } |
| js.popIndentation(); |
| js.append("};\n"); |
| return new @NonNull String[]{ classIndex2classIdName, classIndex2allClassIndexes}; |
| } |
| return null; |
| } |
| |
| protected void doAssigned(@NonNull CGEcoreContainerAssignment cgPropertyAssignment) { |
| EStructuralFeature eStructuralFeature = ClassUtil.nonNullModel(cgPropertyAssignment.getEStructuralFeature()); |
| CGValuedElement cgSlot = getExpression(cgPropertyAssignment.getSlotValue()); |
| CGValuedElement cgInit = getExpression(cgPropertyAssignment.getInitValue()); |
| EPackage ePackage = ClassUtil.nonNullModel(eStructuralFeature.getEContainingClass().getEPackage()); |
| if (isIncremental || ((SetStatement)cgPropertyAssignment.getAst()).isIsNotify()) { |
| js.append("objectManager.assigned("); |
| if (isIncremental) { |
| js.append("this, "); |
| } |
| js.appendValueName(cgInit); |
| js.append(", "); |
| js.appendClassReference(genModelHelper.getQualifiedPackageInterfaceName(ePackage)); |
| js.append(".Literals."); |
| js.append(genModelHelper.getEcoreLiteralName(eStructuralFeature)); |
| js.append(", "); |
| js.appendValueName(cgSlot); |
| js.append(", null);\n"); |
| } |
| } |
| |
| protected void doAssigned(@NonNull CGEcorePropertyAssignment cgPropertyAssignment) { |
| EStructuralFeature eStructuralFeature = ClassUtil.nonNullModel(cgPropertyAssignment.getEStructuralFeature()); |
| CGValuedElement cgSlot = getExpression(cgPropertyAssignment.getSlotValue()); |
| CGValuedElement cgInit = getExpression(cgPropertyAssignment.getInitValue()); |
| EPackage ePackage = ClassUtil.nonNullModel(eStructuralFeature.getEContainingClass().getEPackage()); |
| if (isIncremental || ((SetStatement)cgPropertyAssignment.getAst()).isIsNotify()) { |
| js.append("objectManager.assigned("); |
| if (isIncremental) { |
| js.append("this, "); |
| } |
| js.appendValueName(cgSlot); |
| js.append(", "); |
| js.appendClassReference(genModelHelper.getQualifiedPackageInterfaceName(ePackage)); |
| js.append(".Literals."); |
| js.append(genModelHelper.getEcoreLiteralName(eStructuralFeature)); |
| js.append(", "); |
| js.appendValueName(cgInit); |
| js.append(", null);\n"); |
| } |
| } |
| |
| protected void doConstructor(@NonNull CGTransformation cgTransformation, @Nullable String oppositeName, @NonNull String @Nullable [] allInstancesNames) { |
| // String evaluatorName = ((QVTiGlobalContext)globalContext).getEvaluatorParameter().getName(); |
| String evaluatorName = JavaConstants.EXECUTOR_NAME; |
| String className = cgTransformation.getName(); |
| // |
| js.append("public " + className + "(final "); |
| js.appendIsRequired(true); |
| js.append(" "); |
| js.appendClassReference(Executor.class); |
| js.append(" " + evaluatorName + ") {\n"); |
| js.pushIndentation(null); |
| js.append("super(" + evaluatorName + ", new "); |
| js.appendIsRequired(true); |
| js.append(" String[] {"); |
| boolean isFirst = true; |
| for (@NonNull CGTypedModel cgTypedModel : ClassUtil.nullFree(cgTransformation.getTypedModels())) { |
| if (!isFirst) { |
| js.append(", "); |
| } |
| String name = cgTypedModel.getName(); |
| js.appendString(name != null ? name : ""); |
| isFirst = false; |
| } |
| js.append("}"); |
| if (oppositeName != null) { |
| js.append(", "); |
| js.append(oppositeName); |
| } |
| else { |
| js.append(", null"); |
| } |
| if (allInstancesNames != null) { |
| js.append(", "); |
| js.append(allInstancesNames[0]); |
| js.append(", "); |
| js.append(allInstancesNames[1]); |
| } |
| else { |
| js.append(", null, null"); |
| } |
| js.append(");\n"); |
| // doMappingConstructorInitializers(cgTransformation); |
| // doFunctionConstructorInitializers(cgTransformation); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| |
| protected void doCreateIncrementalManagers() { |
| js.append("protected "); |
| js.appendIsRequired(true); |
| js.append(" "); |
| js.appendClassReference(InvocationManager.class); |
| js.append(" createInvocationManager() {\n"); |
| js.pushIndentation(null); |
| js.append("return new "); |
| js.appendClassReference(IncrementalInvocationManager.class); |
| js.append("();\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| js.append("\n"); |
| js.append("protected "); |
| js.appendIsRequired(true); |
| js.append(" "); |
| js.appendClassReference(ObjectManager.class); |
| js.append(" createObjectManager() {\n"); |
| js.pushIndentation(null); |
| js.append("return new "); |
| js.appendClassReference(IncrementalObjectManager.class); |
| js.append("(("); |
| js.appendClassReference(IncrementalInvocationManager.class); |
| js.append(")invocationManager);\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| |
| protected boolean doFunctionBody(@NonNull CGFunction cgFunction) { |
| CGValuedElement body = getExpression(cgFunction.getBody()); |
| ElementId elementId = cgFunction.getTypeId().getElementId(); |
| js.append(" {\n"); |
| js.pushIndentation(null); |
| // js.appendCastParameters(localContext2, cgParameters); |
| // JavaDependencyVisitor dependencyVisitor = new JavaDependencyVisitor(localContext2, null); |
| // dependencyVisitor.visit(body); |
| // dependencyVisitor.visitAll(localContext2.getLocalVariables()); |
| // Iterable<CGValuedElement> sortedDependencies = dependencyVisitor.getSortedDependencies(); |
| // for (CGValuedElement cgElement : sortedDependencies) { |
| // if (!cgElement.isInlined() && cgElement.isConstant() && !cgElement.isGlobal()) { |
| // cgElement.accept(this); |
| // } |
| // } |
| // FIXME merge locals into AST as LetExps. |
| if (cgFunction.getBody() != null) { |
| if (!js.appendLocalStatements(body)) { |
| return false; |
| } |
| js.append("return "); |
| js.appendValueName(body); |
| js.append(";\n"); |
| } |
| else { |
| TypeId asTypeId = cgFunction.getASTypeId(); |
| if (asTypeId == TypeId.STRING) { // FIXME Fudge for body-less functions |
| js.append("return \"\";\n"); |
| } |
| else if (asTypeId == TypeId.REAL) { // FIXME Fudge for body-less functions |
| js.append("return 0;\n"); |
| } |
| else if (asTypeId == TypeId.INTEGER) { // FIXME Fudge for body-less functions |
| js.append("return 0;\n"); |
| } |
| else if (asTypeId instanceof CollectionTypeId) { // FIXME Fudge for body-less functions |
| if (js.isUseNullAnnotations()) { |
| js.append("@SuppressWarnings(\"null\")"); |
| js.appendIsRequired(true); |
| js.append(" "); |
| } |
| if (elementId != null) { |
| TypeDescriptor javaTypeDescriptor = context.getUnboxedDescriptor(elementId); |
| js.appendClassReference(javaTypeDescriptor); |
| } |
| js.append(" emptyList = "); |
| js.appendClassReference(Collections.class); |
| js.append(".emptyList();\n"); |
| js.append("return emptyList;\n"); |
| } |
| else { // FIXME Fudge for body-less functions |
| js.append("return \"\";\n"); |
| } |
| } |
| js.popIndentation(); |
| js.append("}\n"); |
| return true; |
| } |
| |
| protected boolean doFunctionBody(@NonNull CGFunction cgFunction, @NonNull String instanceName) { |
| CGValuedElement body = getExpression(cgFunction.getBody()); |
| ElementId elementId = cgFunction.getTypeId().getElementId(); |
| // FIXME merge locals into AST as LetExps. |
| if (cgFunction.getBody() != null) { |
| if (!js.appendLocalStatements(body)) { |
| return false; |
| } |
| js.append("this." + instanceName + " = "); |
| js.appendValueName(body); |
| js.append(";\n"); |
| } |
| else { |
| TypeId asTypeId = cgFunction.getASTypeId(); |
| if (asTypeId == TypeId.STRING) { // FIXME Fudge for body-less functions |
| js.append("this." + instanceName + " = \"\";\n"); |
| } |
| else if (asTypeId == TypeId.REAL) { // FIXME Fudge for body-less functions |
| js.append("this." + instanceName + " = 0;\n"); |
| } |
| else if (asTypeId == TypeId.INTEGER) { // FIXME Fudge for body-less functions |
| js.append("this." + instanceName + " = 0;\n"); |
| } |
| else if (asTypeId instanceof CollectionTypeId) { // FIXME Fudge for body-less functions |
| if (js.isUseNullAnnotations()) { |
| js.append("@SuppressWarnings(\"null\")"); |
| js.appendIsRequired(true); |
| js.append(" "); |
| } |
| if (elementId != null) { |
| TypeDescriptor javaTypeDescriptor = context.getUnboxedDescriptor(elementId); |
| js.appendClassReference(javaTypeDescriptor); |
| } |
| js.append(" emptyList = "); |
| js.appendClassReference(Collections.class); |
| js.append(".emptyList();\n"); |
| js.append("this." + instanceName + " = emptyList;\n"); |
| } |
| else { // FIXME Fudge for body-less functions |
| js.append("this." + instanceName + " = \"\";\n"); |
| } |
| } |
| return true; |
| } |
| |
| protected boolean doFunctionBody2(@NonNull CGFunction cgFunction, @NonNull CGShadowExp cgShadowExp, @NonNull String instanceName) { |
| js.append(" {\n"); |
| js.pushIndentation(null); |
| EClassifier eClassifier = ClassUtil.nonNullState(cgShadowExp.getEcoreClassifier()); |
| doEcoreCreate(cgShadowExp, eClassifier); |
| int index = 0; |
| for (@NonNull CGShadowPart cgShadowPart : ClassUtil.nullFree(cgShadowExp.getParts())) { |
| Property asProperty = ClassUtil.nonNullState(((ShadowPart)cgShadowPart.getAst()).getReferredProperty()); |
| EStructuralFeature eStructuralFeature = ClassUtil.nonNullState(getESObject(asProperty)); |
| js.appendValueName(cgShadowExp); |
| js.append("."); |
| if (eStructuralFeature.isMany()) { |
| String getAccessor = genModelHelper.getGetAccessor(eStructuralFeature); |
| // |
| js.append(getAccessor); |
| js.append("().addAll"); |
| } |
| else { |
| String setAccessor = genModelHelper.getSetAccessor(eStructuralFeature); |
| // |
| js.append(setAccessor); |
| } |
| js.append("("); |
| js.appendClassCast(cgShadowPart); |
| js.append("boundValues[" + index++ + "]);\n"); |
| } |
| // |
| js.append("this."); |
| js.append(instanceName); |
| js.append(" = "); |
| js.appendValueName(cgShadowExp); |
| js.append(";\n"); |
| // |
| EPackage ePackage = eClassifier.getEPackage(); |
| ImperativeTypedModel bestOutputTypedModel = null; |
| ImperativeTypedModel bestMiddleTypedModel = null; |
| ImperativeTypedModel bestInputTypedModel = null; |
| for (@NonNull ImperativeTypedModel typedModel : QVTimperativeUtil.getOwnedTypedModels(transformationAnalysis.getTransformation())) { |
| ImperativeTypedModel imperativeTypedModel = null; |
| for (org.eclipse.ocl.pivot.Package usedPackage : typedModel.getUsedPackage()) { |
| if (usedPackage.getESObject() == ePackage) { |
| imperativeTypedModel = typedModel; |
| } |
| } |
| if (imperativeTypedModel != null) { |
| if (imperativeTypedModel.isIsEnforced()) { |
| bestOutputTypedModel = imperativeTypedModel; |
| } |
| else if (!imperativeTypedModel.isIsChecked()) { |
| bestMiddleTypedModel = imperativeTypedModel; |
| } |
| else { |
| bestInputTypedModel = imperativeTypedModel; |
| } |
| } |
| } |
| ImperativeTypedModel asTypedModel = null; |
| if (bestOutputTypedModel != null) { |
| asTypedModel = bestOutputTypedModel; |
| } |
| else if (bestMiddleTypedModel != null) { |
| asTypedModel = bestMiddleTypedModel; |
| } |
| else if (bestInputTypedModel != null) { |
| asTypedModel = bestInputTypedModel; |
| } |
| if (asTypedModel != null) { // FIXME Why are shadow objects put in a model at all -- testQVTrCompiler_SeqToStm_CG requires it |
| CGTypedModel cgTypedModel = context.getAnalyzer().getTypedModel(asTypedModel); |
| js.append(QVTiGlobalContext.MODELS_NAME); |
| js.append("["); |
| appendModelIndex(cgTypedModel); |
| js.append("].add("); |
| js.appendValueName(cgShadowExp); |
| js.append(");\n"); |
| } |
| // |
| js.popIndentation(); |
| js.append("}\n"); |
| return true; |
| } |
| |
| protected void doFunctionConstructor(@NonNull CGFunction cgFunction, @NonNull String instanceName) { |
| CGClass cgClass = ClassUtil.nonNullState(CGUtil.getContainingClass(cgFunction)); |
| List<@NonNull CGParameter> cgParameters = ClassUtil.nullFree(cgFunction.getParameters()); |
| CGValuedElement cgBody = cgFunction.getBody(); |
| if (cgBody != null) { |
| js.appendCommentWithOCL(null, cgBody.getAst()); |
| } |
| // if (js.isUseNullAnnotations()) { |
| // js.append("@SuppressWarnings(\"null\")\n"); // Accurate casts are too hard |
| // } |
| js.append("public "); |
| js.append(getFunctionName(cgFunction)); |
| js.append("(/*Nullable*/ Object "); |
| js.appendIsRequired(true); |
| js.append(" [] boundValues) {\n"); |
| js.pushIndentation(null); |
| js.append("this.self = ("); |
| js.appendClassReference(cgClass); |
| js.append(")boundValues[0];\n"); |
| int i = 1; |
| for (@NonNull CGParameter cgParameter : cgParameters) { |
| String valueName = getValueName(cgParameter); |
| js.append("this."); |
| js.append(valueName); |
| js.append(" = "); |
| js.appendClassCast(cgParameter); |
| js.append("boundValues[" + i++ + "];\n"); |
| } |
| doFunctionBody(cgFunction, instanceName); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| |
| protected void doFunctionConstructor(@NonNull CGFunction cgFunction, @NonNull CGShadowExp cgShadowExp, @NonNull String instanceName) { |
| // List<@NonNull CGParameter> cgParameters = ClassUtil.nullFree(cgFunction.getParameters()); |
| if (js.isUseNullAnnotations()) { |
| js.append("@SuppressWarnings(\"null\")\n"); // Accurate casts are too hard |
| } |
| js.append("public "); |
| js.append(getFunctionName(cgFunction)); |
| js.append("(/*Nullable*/ Object "); |
| js.appendIsRequired(true); |
| js.append(" [] boundValues) "); |
| /* int i = 0; |
| for (@NonNull CGParameter cgParameter : cgParameters) { |
| String valueName = getValueName(cgParameter); |
| js.append(valueName); |
| js.append(" = "); |
| // js.appendClassCast(cgFreeVariable); |
| if (cgParameter instanceof CGConnectionVariable) { |
| js.append("("); |
| js.appendClassReference(null, cgParameter); |
| js.append(".Accumulator)"); // FIXME Embed properly as a nested typeid |
| } |
| else{ |
| js.appendClassCast(cgParameter); |
| } |
| js.append("boundValues[" + i++); |
| js.append("];\n"); |
| } */ |
| doFunctionBody2(cgFunction, cgShadowExp, instanceName); |
| } |
| |
| protected void doFunctionConstructorConstants(/*@NonNull*/ List<@NonNull CGOperation> cgOperations) { |
| for (@NonNull CGOperation cgOperation : cgOperations) { |
| if (cgOperation instanceof CGFunction) { |
| CGFunction cgFunction = (CGFunction)cgOperation; |
| if ((useClass(cgFunction) != null) || useCache(cgFunction)) { |
| js.append("protected final "); |
| js.appendIsRequired(true); |
| js.append(" "); |
| js.appendClassReference(AbstractComputationConstructor.class); |
| js.append(" " + getFunctionCtorName(cgFunction) + " = new "); |
| js.appendClassReference(AbstractComputationConstructor.class); |
| js.append("(idResolver)\n"); |
| js.append("{\n"); |
| js.pushIndentation(null); |
| js.append("@Override\n"); |
| js.append("public "); |
| js.appendIsRequired(true); |
| js.append(" " + getFunctionName(cgFunction) + " newInstance("); |
| js.appendIsRequired(false); |
| js.append(" "); |
| js.appendClassReference(Object.class); |
| js.append(" "); |
| js.appendIsRequired(true); |
| js.append(" [] values) {\n"); |
| js.pushIndentation(null); |
| js.append("return new " + getFunctionName(cgFunction) + "(values);\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| js.popIndentation(); |
| js.append("};\n\n"); |
| } |
| } |
| } |
| } |
| |
| /* protected void doFunctionConstructorInitializers(@NonNull CGTransformation cgTransformation) { |
| String className = cgTransformation.getName(); |
| for (@NonNull CGOperation cgOperation : ClassUtil.nullFree(cgTransformation.getOperations())) { |
| if (cgOperation instanceof CGFunction) { |
| CGFunction cgFunction = (CGFunction) cgOperation; |
| if ((useClass(cgFunction) != null) || useCache(cgFunction)) { |
| js.append(getFunctionCtorName(cgFunction) + " = "); |
| js.appendClassReference(ClassUtil.class); |
| js.append(".nonNullState(" + getFunctionName(cgFunction) + ".class.getConstructor(" + className + ".class, " + "Object[].class));\n"); |
| } |
| } |
| } |
| } */ |
| |
| protected void doFunctionGetInstance(@NonNull CGFunction cgFunction, @NonNull String instanceName) { |
| js.append("@Override\n"); |
| js.append("public "); |
| js.appendIsRequired(false); |
| js.append(" Object"); |
| // js.appendTypeDeclaration(ClassUtil.nonNullState(cgFunction.getBody())); |
| js.append(" getResult() {\n"); |
| js.pushIndentation(null); |
| js.append("return " + instanceName + ";\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| |
| protected void doFunctionIsEqual(@NonNull CGFunction cgFunction, @NonNull String instanceName) { |
| js.append("@Override\n"); |
| js.append("public boolean isEqual("); |
| js.appendIsRequired(true); |
| js.append(" "); |
| js.appendClassReference(IdResolver.class); |
| js.append(" idResolver, "); |
| js.appendIsRequired(false); |
| js.append(" Object "); |
| js.appendIsRequired(true); |
| js.append(" [] thoseValues) {\n"); |
| js.pushIndentation(null); |
| js.append("return this.self == thoseValues[0]"); |
| int index = 1; |
| for (@NonNull CGParameter cgParameter : ClassUtil.nullFree(cgFunction.getParameters())) { |
| js.append("\n && "); |
| js.append("idResolver.oclEquals(this."); // FIXME oclEquals / == |
| js.appendValueName(cgParameter); |
| js.append(", thoseValues[" + index++ + "])"); |
| } |
| js.append(";\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| |
| protected void doFunctionIsEqual(@NonNull CGShadowExp cgShadowExp, @NonNull String instanceName) { |
| js.append("public boolean isEqual("); |
| js.appendIsRequired(true); |
| js.append(" "); |
| js.appendClassReference(IdResolver.class); |
| js.append(" idResolver, "); |
| js.appendIsRequired(false); |
| js.append(" Object "); |
| js.appendIsRequired(true); |
| js.append(" [] thoseValues) {\n"); |
| js.pushIndentation(null); |
| js.append("return "); |
| int index = 0; |
| for (@NonNull CGShadowPart cgShadowPart : ClassUtil.nullFree(cgShadowExp.getParts())) { |
| if (index > 0) { |
| js.append("\n && "); |
| } |
| js.append("idResolver.oclEquals("); // FIXME oclEquals / == |
| js.append(instanceName); |
| js.append("."); |
| Property asProperty = ClassUtil.nonNullState(((ShadowPart)cgShadowPart.getAst()).getReferredProperty()); |
| EStructuralFeature eStructuralFeature = ClassUtil.nonNullState(getESObject(asProperty)); |
| String getAccessor; |
| if (eStructuralFeature == OCLstdlibPackage.Literals.OCL_ELEMENT__OCL_CONTAINER) { |
| getAccessor = "eContainer"; |
| } |
| else { |
| getAccessor = genModelHelper.getGetAccessor(eStructuralFeature); |
| } |
| js.append(getAccessor); |
| js.append("(), thoseValues[" + index++ + "])"); |
| } |
| js.append(";\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| |
| protected void doGetting(@NonNull CGNavigationCallExp cgPropertyCallExp, @NonNull EStructuralFeature eStructuralFeature, boolean isOpposite) { |
| Element asPropertyCallExp = cgPropertyCallExp.getAst(); |
| CGMapping cgMapping = QVTiCGUtil.getContainingCGMapping(cgPropertyCallExp); |
| Mapping asMapping = cgMapping != null ? (Mapping) cgMapping.getAst() : null; |
| CGValuedElement source = getExpression(cgPropertyCallExp.getSource()); |
| boolean isHazardous = false; |
| if ((asMapping != null) && (asPropertyCallExp instanceof NavigationCallExp)) { |
| isHazardous = isHazardous2((NavigationCallExp) asPropertyCallExp); |
| } |
| if (isHazardous) { |
| EPackage ePackage = ClassUtil.nonNullModel(eStructuralFeature.getEContainingClass().getEPackage()); |
| // |
| js.append("objectManager.getting("); |
| js.appendValueName(source); |
| js.append(", "); |
| js.appendClassReference(genModelHelper.getQualifiedPackageInterfaceName(ePackage)); |
| js.append(".Literals."); |
| js.append(genModelHelper.getEcoreLiteralName(eStructuralFeature)); |
| js.append(", "); |
| js.appendBooleanString(isOpposite); |
| js.append(");\n"); |
| } |
| } |
| |
| private boolean isHazardous2(@NonNull NavigationCallExp asNavigationCallExp) { |
| for (EObject eObject = asNavigationCallExp; eObject != null; eObject = getContainer(eObject)) { |
| if (eObject instanceof ObservableStatement) { |
| List<Property> observedProperties = ((ObservableStatement)eObject).getObservedProperties(); |
| Property navigatedProperty = PivotUtil.getReferredProperty(asNavigationCallExp); |
| return observedProperties.contains(navigatedProperty); |
| } |
| } |
| return false; |
| } |
| |
| private EObject getContainer(EObject eObject) { |
| EObject eContainer = eObject.eContainer(); |
| if (eContainer != null) { |
| return eContainer; |
| } |
| for (Adapter eAdapter : eObject.eAdapters()) { |
| if (eAdapter instanceof QVTiAS2CGVisitor.InlinedBodyAdapter) { |
| return ((QVTiAS2CGVisitor.InlinedBodyAdapter)eAdapter).getOperationCallExp(); |
| } |
| } |
| return null; |
| } |
| |
| protected void doGot(@NonNull CGNavigationCallExp cgPropertyCallExp, @NonNull CGValuedElement source, @NonNull EStructuralFeature eStructuralFeature) { |
| if (useGot) { |
| EPackage ePackage = ClassUtil.nonNullModel(eStructuralFeature.getEContainingClass().getEPackage()); |
| // |
| js.append("objectManager.got(this, "); |
| js.appendValueName(source); |
| js.append(", "); |
| js.appendClassReference(genModelHelper.getQualifiedPackageInterfaceName(ePackage)); |
| js.append(".Literals."); |
| js.append(genModelHelper.getEcoreLiteralName(eStructuralFeature)); |
| js.append(", "); |
| js.appendValueName(cgPropertyCallExp); |
| js.append(");\n"); |
| } |
| } |
| |
| protected void doIsEqual(@NonNull List<@NonNull ? extends CGParameter> cgFreeVariables) { |
| js.append("public boolean isEqual("); |
| js.appendIsRequired(true); |
| js.append(" "); |
| js.appendClassReference(IdResolver.class); |
| js.append(" idResolver, "); |
| js.appendIsRequired(true); |
| js.append(" Object "); |
| js.appendIsRequired(true); |
| js.append(" [] thoseValues) {\n"); |
| js.pushIndentation(null); |
| js.append("return "); |
| int index = 0; |
| for (@NonNull CGParameter cgFreeVariable : cgFreeVariables) { |
| if (index > 0) { |
| js.append("\n && "); |
| } |
| js.append("idResolver.oclEquals("); |
| js.append(cgFreeVariable.getValueName()); |
| js.append(", thoseValues[" + index++ + "])"); |
| } |
| js.append(";\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| |
| protected void doMappingBody(@NonNull CGMapping cgMapping, boolean hasMappingClass) { |
| CGValuedElement cgBody = cgMapping.getBody(); |
| js.append(" {\n"); |
| js.pushIndentation(null); |
| if (cgBody.isInvalid()) { |
| js.append("return handleExecutionFailure(\"" + getMappingName(cgMapping) + "\", "); |
| js.appendValueName(cgBody); |
| js.append(");\n"); |
| } |
| else { |
| js.append("try {\n"); |
| js.pushIndentation(null); |
| String savedLocalPrefix = localPrefix; |
| try { |
| localPrefix = hasMappingClass ? cgMapping.getTransformation().getName() : localPrefix; |
| if (!cgBody.isInlined()) { |
| cgBody.accept(this); |
| } |
| js.append("return "); |
| js.appendValueName(cgBody); |
| js.append(";\n"); |
| } |
| finally { |
| localPrefix = savedLocalPrefix; |
| } |
| js.popIndentation(); |
| js.append("} catch (Throwable e) {\n"); |
| js.pushIndentation(null); |
| js.append("return handleExecutionFailure(\"" + getMappingName(cgMapping) + "\", e);\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| |
| protected void doMappingConnectionVariable(@NonNull CGGuardVariable cgFreeVariable) { |
| if (cgFreeVariable instanceof CGConnectionVariable) { |
| js.append("final "); |
| js.appendClassReference(null, cgFreeVariable); |
| js.append("."); |
| js.appendIsRequired(true); |
| js.append(" Accumulator "); // FIXME Embed properly as a nested typeid |
| js.append(getValueName(cgFreeVariable)); |
| } |
| else{ |
| js.appendDeclaration(cgFreeVariable); |
| } |
| } |
| |
| protected void doMappingConstructor(@NonNull CGMapping cgMapping) { |
| List<@NonNull CGGuardVariable> cgFreeVariables = ClassUtil.nullFree(cgMapping.getFreeVariables()); |
| // if (js.isUseNullAnnotations()) { |
| // js.append("@SuppressWarnings(\"null\")\n"); // Accurate casts are too hard |
| // } |
| js.append("public "); |
| js.append(getMappingName(cgMapping)); |
| js.append("("); |
| js.appendIsRequired(true); |
| js.append(" Object "); |
| js.appendIsRequired(true); |
| js.append(" [] boundValues) {\n"); |
| js.pushIndentation(null); |
| int i = 0; |
| for (@NonNull CGGuardVariable cgFreeVariable : cgFreeVariables) { |
| String valueName = getValueName(cgFreeVariable); |
| js.append(valueName); |
| js.append(" = "); |
| // js.appendClassCast(cgFreeVariable); |
| if (cgFreeVariable instanceof CGConnectionVariable) { |
| js.append("("); |
| js.appendClassReference(null, cgFreeVariable); |
| js.append(".Accumulator)"); // FIXME Embed properly as a nested typeid |
| } |
| else{ |
| js.appendClassCast(cgFreeVariable); |
| } |
| js.append("boundValues[" + i++); |
| js.append("];\n"); |
| } |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| |
| protected void doMappingConstructorConstants(/*@NonNull*/ List<@NonNull CGMapping> cgMappings) { |
| for (@NonNull CGMapping cgMapping : cgMappings) { |
| if (useClass(cgMapping) && (cgMapping.getFreeVariables().size() > 0)) { |
| js.append("protected final "); |
| js.appendIsRequired(true); |
| js.append(" "); |
| js.appendClassReference(AbstractInvocationConstructor.class); |
| js.append(" " + getMappingCtorName(cgMapping) + " = new "); |
| js.appendClassReference(AbstractInvocationConstructor.class); |
| js.append("(idResolver)\n"); |
| js.append("{\n"); |
| js.pushIndentation(null); |
| js.append("@Override\n"); |
| js.append("public "); |
| js.appendIsRequired(true); |
| js.append(" " + getMappingName(cgMapping) + " newInstance("); |
| js.appendIsRequired(true); |
| js.append(" "); |
| js.appendClassReference(Object.class); |
| js.append(" "); |
| js.appendIsRequired(true); |
| js.append(" [] values) {\n"); |
| js.pushIndentation(null); |
| js.append("return new " + getMappingName(cgMapping) + "(values);\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| js.popIndentation(); |
| js.append("};\n\n"); |
| } |
| } |
| } |
| |
| /* protected void doMappingConstructorInitializers(@NonNull CGTransformation cgTransformation) { |
| String className = cgTransformation.getName(); |
| for (@NonNull CGMapping cgMapping : ClassUtil.nullFree(cgTransformation.getMappings())) { |
| if (useClass(cgMapping) && (cgMapping.getFreeVariables().size() > 0)) { |
| js.append(getMappingCtorName(cgMapping) + " = "); |
| js.appendClassReference(ClassUtil.class); |
| js.append(".nonNullState(" + getMappingName(cgMapping) + ".class.getConstructor(" + className + ".class, Object[].class));\n"); |
| } |
| } |
| } */ |
| |
| protected void doOppositeCaches(@NonNull QVTiTransformationAnalysis transformationAnalysis) { |
| Map<@NonNull Property, @NonNull Integer> opposites = transformationAnalysis.getCaches(); |
| if (opposites.size() <= 0) { |
| return; |
| } |
| js.append("\n/*\n * Property-source to Property-target unnavigable navigation caches\n */\n"); |
| Map<@NonNull String, @NonNull Property> key2property = new HashMap<@NonNull String, @NonNull Property>(); |
| for (Map.Entry<@NonNull Property, @NonNull Integer> entry : opposites.entrySet()) { |
| Property property = entry.getKey(); |
| String name = getGlobalContext().addOppositeProperty(property); |
| |
| key2property.put(name, property); |
| } |
| List<String> sortedKeys = new ArrayList<String>(key2property.keySet()); |
| Collections.sort(sortedKeys); |
| for (String key : sortedKeys) { |
| Property property = key2property.get(key); |
| assert property != null; |
| TypeDescriptor outerTypeDescriptor = context.getBoxedDescriptor(property.getOwningClass().getTypeId()); |
| TypeDescriptor middleTypeDescriptor = context.getBoxedDescriptor(property.getType().getTypeId()); |
| js.append("protected final "); |
| js.appendIsRequired(true); |
| js.append(" "); |
| js.appendClassReference(null, Map.class, false, middleTypeDescriptor, outerTypeDescriptor); |
| js.append(" "); |
| js.append(key); |
| js.append(" = new "); |
| js.appendClassReference(null, HashMap.class, false, middleTypeDescriptor, outerTypeDescriptor); |
| js.append("();\n"); |
| } |
| } |
| |
| protected @Nullable String doOppositePropertyIds(@NonNull QVTiTransformationAnalysis transformationAnalysis) { |
| return null; |
| // This code is no longer used, and since it is not used it generates undefined references |
| // It appears to have 'worked' only because a duplicate incomplete TransformationAnalysis was in use. |
| /* Map<Property, Integer> opposites = transformationAnalysis.getSourceCaches(); |
| if (opposites.size() <= 0) { |
| return null; |
| } |
| NameManager nameManager = getGlobalContext().getNameManager(); |
| List<Property> sortedList = new ArrayList<Property>(); |
| for (int i = 0; i < opposites.size();i++) { |
| sortedList.add(null); |
| } |
| for (Map.Entry<Property, Integer> entry : opposites.entrySet()) { |
| sortedList.set(entry.getValue().intValue(), entry.getKey()); |
| } |
| // |
| // Emit the ClassId array |
| // |
| js.append("/*\n"); |
| js.append(" * Array of the source PropertyIds of each Property for which unnavigable opposite property navigation may occur.\n"); |
| js.append(" * /\n"); |
| String oppositeIndex2propertyIdName = nameManager.getGlobalSymbolName(null, "oppositeIndex2propertyId"); |
| js.append("private static final "); |
| js.appendIsRequired(true); |
| js.append(" "); |
| js.appendClassReference(PropertyId.class); |
| js.append("[] "); |
| js.append(oppositeIndex2propertyIdName); |
| js.append(" = new "); |
| js.appendClassReference(PropertyId.class); |
| js.append("[]{\n"); |
| js.pushIndentation(null); |
| for (int i = 0; i < sortedList.size(); i++) { |
| Property property = sortedList.get(i); |
| CGElementId cgPropertyId = getCodeGenerator().getAnalyzer().getElementId(property.getPropertyId()); |
| js.appendValueName(cgPropertyId); |
| if ((i+1) < sortedList.size()) { |
| js.append(","); |
| } |
| js.append("\t\t// " + i + " => " + property.getName() + "\n"); |
| } |
| js.popIndentation(); |
| js.append("};\n"); |
| return oppositeIndex2propertyIdName; */ |
| } |
| |
| protected void doRun(@NonNull CGTransformation cgTransformation) { |
| CGMapping cgRootMapping = NameUtil.getNameable(cgTransformation.getMappings(), QVTimperativeUtil.ROOT_MAPPING_NAME); |
| if (cgRootMapping == null) { |
| throw new IllegalStateException("Transformation " + cgTransformation.getName() + " has no root mapping"); |
| } |
| js.append("@Override\n"); |
| js.append("public boolean run() {\n"); |
| js.pushIndentation(null); |
| js.append("return "); |
| js.append(getMappingName(cgRootMapping)); |
| js.append("() && invocationManager.flush();\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| |
| protected @NonNull Class<? extends AbstractTransformer> getAbstractTransformationExecutorClass() { |
| return AbstractTransformer.class; |
| } |
| |
| @Override |
| public @NonNull Set<String> getAllImports() { |
| Set<String> allImports = new HashSet<String>(); |
| for (String anImport : super.getAllImports()) { |
| allImports.add(anImport); |
| if (anImport.endsWith(".Model")) { |
| allImports.add(org.eclipse.qvtd.runtime.evaluation.AbstractTransformer.class.getName() + ".Model"); |
| } |
| } |
| return allImports; |
| } |
| |
| @Override |
| 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()) { |
| PivotMetamodelManager metamodelManager = analyzer.getCodeGenerator().getEnvironmentFactory().getMetamodelManager(); |
| LibraryProperty libraryProperty = metamodelManager.getImplementation(null, null, asProperty); |
| if (!(libraryProperty instanceof OclElementOclContainerProperty)) { |
| return null; |
| } |
| } |
| return OCLstdlibPackage.Literals.OCL_ELEMENT__OCL_CONTAINER; |
| } |
| |
| protected String getFunctionCtorName(@NonNull CGFunction cgFunction) { |
| return JavaStream.convertToJavaIdentifier("FTOR_" + cgFunction.getName()); |
| } |
| |
| protected @NonNull String getFunctionName(@NonNull CGFunction cgFunction) { |
| return JavaStream.convertToJavaIdentifier("FUN_" + cgFunction.getName()); |
| } |
| |
| protected @NonNull QVTiGlobalContext getGlobalContext() { |
| return (QVTiGlobalContext) globalContext; |
| } |
| |
| protected String getMappingCtorName(@NonNull CGMapping cgMapping) { |
| return JavaStream.convertToJavaIdentifier("CTOR_" + cgMapping.getName()); |
| } |
| |
| protected @NonNull String getMappingName(@NonNull CGMapping cgMapping) { |
| return JavaStream.convertToJavaIdentifier("MAP_" + cgMapping.getName()); |
| } |
| |
| protected @Nullable TypeDescriptor needsTypeCheck(@NonNull CGMappingCallBinding cgMappingCallBinding) { |
| MappingParameterBinding mappingParameterBinding = (MappingParameterBinding)cgMappingCallBinding.getAst(); |
| VariableDeclaration boundVariable = mappingParameterBinding.getBoundVariable(); |
| assert boundVariable != null; |
| if (boundVariable instanceof ConnectionVariable) { |
| return null; |
| } |
| CGValuedElement value = cgMappingCallBinding.getValue(); |
| TypeDescriptor argumentTypeDescriptor = context.getTypeDescriptor(cgMappingCallBinding); |
| TypeId pivotTypeId = value.getASTypeId(); |
| if (pivotTypeId instanceof CollectionTypeId) { |
| pivotTypeId = ((CollectionTypeId)pivotTypeId).getElementTypeId(); |
| } |
| TypeDescriptor iteratorTypeDescriptor = context.getBoxedDescriptor(ClassUtil.nonNullState(pivotTypeId)); |
| if (argumentTypeDescriptor.isAssignableFrom(iteratorTypeDescriptor)) { |
| return null; |
| } |
| else { |
| return argumentTypeDescriptor; |
| } |
| } |
| |
| protected boolean useCache(@NonNull CGFunction cgFunction) { |
| Element ast = cgFunction.getAst(); |
| return !(ast instanceof Operation) || !((Operation)ast).isIsTransient(); |
| } |
| |
| protected @Nullable CGShadowExp useClass(@NonNull CGFunction cgFunction) { |
| CGValuedElement cgBody = cgFunction.getBody(); |
| while (cgBody instanceof CGLetExp) { |
| cgBody = ((CGLetExp)cgBody).getIn(); |
| } |
| if (cgBody instanceof CGShadowExp) { |
| return (CGShadowExp)cgBody; // FIXME replace with clearer strategy |
| } |
| return null; |
| } |
| |
| protected boolean useClass(@NonNull CGMapping cgMapping) { |
| if (alwaysUseClasses) { |
| return true; |
| } |
| Mapping asMapping = ClassUtil.nonNullState((Mapping) cgMapping.getAst()); |
| return QVTimperativeUtil.isObserver(asMapping); |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGConnectionAssignment(@NonNull CGConnectionAssignment cgConnectionAssignment) { |
| CGValuedElement initValue = cgConnectionAssignment.getInitValue(); |
| assert initValue != null; |
| if (!js.appendLocalStatements(initValue)) { |
| return false; |
| } |
| final String iteratorName = getSymbolName(null, "iterator"); |
| // CollectionTypeId abstractCollectionTypeId = (CollectionTypeId)initValue.getASTypeId(); |
| // assert abstractCollectionTypeId != null; |
| // TypeId abstractElementTypeId = abstractCollectionTypeId.getElementTypeId(); |
| // BoxedDescriptor abstractBoxedDescriptor = context.getBoxedDescriptor(abstractElementTypeId); |
| CollectionTypeId concreteCollectionTypeId = (CollectionTypeId)cgConnectionAssignment.getConnectionVariable().getASTypeId(); |
| assert concreteCollectionTypeId != null; |
| TypeId concreteElementTypeId = concreteCollectionTypeId.getElementTypeId(); |
| BoxedDescriptor concreteBoxedDescriptor = context.getBoxedDescriptor(concreteElementTypeId); |
| BoxedDescriptor abstractBoxedDescriptor = concreteBoxedDescriptor; |
| if (!(initValue.getASTypeId() instanceof CollectionTypeId)) { |
| js.appendReferenceTo(cgConnectionAssignment.getConnectionVariable()); |
| js.append(".add("); |
| js.appendValueName(initValue); |
| js.append(");\n"); |
| } |
| else { |
| js.append("for ("); |
| js.appendClassReference(Boolean.TRUE, abstractBoxedDescriptor); |
| js.append(" "); |
| js.append(iteratorName); |
| js.append(" : "); |
| if (initValue.isBoxed()) { |
| js.appendClassReference(ValueUtil.class); |
| js.append(".typedIterable("); |
| js.appendClassReference(abstractBoxedDescriptor); |
| js.append(".class, "); |
| js.appendValueName(initValue); |
| js.append(")"); |
| } |
| else { |
| js.appendValueName(initValue); |
| } |
| js.append(") {\n"); |
| js.pushIndentation(null); |
| if (concreteBoxedDescriptor != abstractBoxedDescriptor) { |
| js.append("if ("); |
| js.append(iteratorName); |
| js.append(" instanceof "); |
| js.appendClassReference(concreteBoxedDescriptor); |
| js.append(") {\n"); |
| js.pushIndentation(null); |
| } |
| js.appendReferenceTo(cgConnectionAssignment.getConnectionVariable()); |
| js.append(".add("); |
| js.append(iteratorName); |
| js.append(");\n"); |
| if (concreteBoxedDescriptor != abstractBoxedDescriptor) { |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGConnectionVariable(@NonNull CGConnectionVariable object) { |
| return visitCGGuardVariable(object); |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGEcoreContainerAssignment(@NonNull CGEcoreContainerAssignment cgPropertyAssignment) { |
| // Property referredProperty = cgPropertyAssignment.getReferredProperty(); |
| // Property pivotProperty = cgPropertyCallExp.getReferredProperty(); |
| // CGTypeId cgTypeId = analyzer.getTypeId(pivotProperty.getOwningType().getTypeId()); |
| // JavaTypeDescriptor requiredTypeDescriptor = context.getJavaTypeDescriptor(cgTypeId, false); |
| EStructuralFeature eStructuralFeature = ClassUtil.nonNullModel(cgPropertyAssignment.getEStructuralFeature()); |
| CGValuedElement cgSlot = getExpression(cgPropertyAssignment.getSlotValue()); |
| CGValuedElement cgInit = getExpression(cgPropertyAssignment.getInitValue()); |
| // Class<?> requiredJavaClass = requiredTypeDescriptor.getJavaClass(); |
| // Method leastDerivedMethod = requiredJavaClass != null ? getLeastDerivedMethod(requiredJavaClass, getAccessor) : null; |
| // Class<?> unboxedSourceClass = leastDerivedMethod != null ? leastDerivedMethod.getDeclaringClass() : requiredJavaClass; |
| // |
| if (!js.appendLocalStatements(cgSlot)) { |
| return false; |
| } |
| if (!js.appendLocalStatements(cgInit)) { |
| return false; |
| } |
| if (eStructuralFeature.isMany()) { |
| String getAccessor = genModelHelper.getGetAccessor(eStructuralFeature); |
| // |
| js.appendValueName(cgInit); |
| js.append("."); |
| js.append(getAccessor); |
| js.append("().add("); |
| js.appendValueName(cgSlot); |
| js.append(");\n"); |
| } |
| else { |
| String setAccessor = genModelHelper.getSetAccessor(eStructuralFeature); |
| // |
| js.appendValueName(cgInit); |
| js.append("."); |
| js.append(setAccessor); |
| js.append("("); |
| js.appendValueName(cgSlot); |
| js.append(");\n"); |
| } |
| doAssigned(cgPropertyAssignment); |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGEcorePropertyAssignment(@NonNull CGEcorePropertyAssignment cgPropertyAssignment) { |
| // Property referredProperty = cgPropertyAssignment.getReferredProperty(); |
| // Property pivotProperty = cgPropertyCallExp.getReferredProperty(); |
| // CGTypeId cgTypeId = analyzer.getTypeId(pivotProperty.getOwningType().getTypeId()); |
| // JavaTypeDescriptor requiredTypeDescriptor = context.getJavaTypeDescriptor(cgTypeId, false); |
| EStructuralFeature eStructuralFeature = ClassUtil.nonNullModel(cgPropertyAssignment.getEStructuralFeature()); |
| CGValuedElement cgSlot = getExpression(cgPropertyAssignment.getSlotValue()); |
| CGValuedElement cgInit = getExpression(cgPropertyAssignment.getInitValue()); |
| // Class<?> requiredJavaClass = requiredTypeDescriptor.getJavaClass(); |
| // Method leastDerivedMethod = requiredJavaClass != null ? getLeastDerivedMethod(requiredJavaClass, getAccessor) : null; |
| // Class<?> unboxedSourceClass = leastDerivedMethod != null ? leastDerivedMethod.getDeclaringClass() : requiredJavaClass; |
| // |
| if (!js.appendLocalStatements(cgSlot)) { |
| return false; |
| } |
| if (!js.appendLocalStatements(cgInit)) { |
| return false; |
| } |
| appendEcoreSet(cgSlot, eStructuralFeature, cgInit); |
| doAssigned(cgPropertyAssignment); |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGEcorePropertyCallExp(@NonNull CGEcorePropertyCallExp cgPropertyCallExp) { |
| CGValuedElement source = getExpression(cgPropertyCallExp.getSource()); |
| // |
| if (!js.appendLocalStatements(source)) { |
| return false; |
| } |
| EStructuralFeature eStructuralFeature = ClassUtil.nonNullState(cgPropertyCallExp.getEStructuralFeature()); |
| doGetting(cgPropertyCallExp, eStructuralFeature, false); |
| Boolean status = appendCGEcorePropertyCallExp(cgPropertyCallExp, source); |
| if (status != ValueUtil.TRUE_VALUE) { |
| return status; |
| } |
| doGot(cgPropertyCallExp, source, eStructuralFeature); |
| return status; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGEcoreRealizedVariable(@NonNull CGEcoreRealizedVariable cgRealizedVariable) { |
| EClassifier eClassifier = ClassUtil.nonNullState(cgRealizedVariable.getEClassifier()); |
| if (doEcoreCreate(cgRealizedVariable, eClassifier)) { |
| cgRealizedVariable.setNonNull(); |
| } |
| // |
| js.append("assert "); |
| js.appendValueName(cgRealizedVariable); |
| js.append(" != null;\n"); |
| // |
| doAddRealization(cgRealizedVariable); |
| return true; |
| } |
| |
| protected boolean doEcoreCreate(@NonNull CGValuedElement cgElement, @NonNull EClassifier eClassifier) { |
| boolean doSetNonNull = false; |
| EPackage ePackage = eClassifier.getEPackage(); |
| String createMethodName = "create" + eClassifier.getName(); |
| String javaClass; |
| if (ePackage != null) { |
| Class<?> factoryClass = genModelHelper.getEcoreFactoryClass(ePackage); |
| if (factoryClass != null) { |
| javaClass = factoryClass.getName(); |
| Method factoryMethod = context.getLeastDerivedMethod(factoryClass, createMethodName); |
| if (factoryMethod != null) { |
| if (context.getIsNonNull(factoryMethod) == Boolean.TRUE) { |
| doSetNonNull = true; |
| }; |
| } |
| } |
| else { |
| javaClass = genModelHelper.getQualifiedFactoryInterfaceName(ePackage); |
| } |
| } |
| else { |
| javaClass = null; |
| } |
| // |
| js.appendDeclaration(cgElement); |
| js.append(" = "); |
| js.appendClassReference(javaClass); |
| // js.appendReferenceTo(localContext.getExecutorType(cgRealizedVariable.getPivotTypeId())); |
| js.append(".eINSTANCE."); |
| js.append(createMethodName); |
| js.append("();\n"); |
| // |
| return doSetNonNull; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGFunction(@NonNull CGFunction cgFunction) { |
| JavaLocalContext<@NonNull ?> localContext2 = globalContext.getLocalContext(cgFunction); |
| if (localContext2 != null) { |
| localContext = localContext2; |
| // localContext. |
| try { |
| List<CGParameter> cgParameters = cgFunction.getParameters(); |
| // |
| js.appendCommentWithOCL(null, cgFunction.getAst()); |
| CGShadowExp cgShadowExp = useClass(cgFunction); |
| if (cgShadowExp != null) { |
| JavaLocalContext<@NonNull ?> functionContext = ClassUtil.nonNullState(globalContext.getLocalContext(cgFunction)); |
| String instanceName = functionContext.getNameManagerContext().getSymbolName(cgFunction.getBody(), "instance"); |
| // Type |
| js.append("protected class "); |
| js.append(getFunctionName(cgFunction)); |
| js.append(" extends "); |
| js.appendClassReference(/*isIncremental ? AbstractIdentification.Incremental.class :*/ AbstractValueOccurrence.class); |
| js.append("\n"); |
| js.append("{\n"); |
| js.pushIndentation(null); |
| js.append("protected final "); |
| js.appendTypeDeclaration(cgFunction); |
| js.append(" " + instanceName + ";\n"); |
| js.append("\n"); |
| doFunctionConstructor(cgFunction, cgShadowExp, instanceName); |
| js.append("\n"); |
| doFunctionGetInstance(cgFunction, instanceName); |
| js.append("\n"); |
| doFunctionIsEqual(cgShadowExp, instanceName); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| else if (useCache(cgFunction)) { |
| JavaLocalContext<@NonNull ?> functionContext = ClassUtil.nonNullState(globalContext.getLocalContext(cgFunction)); |
| String instanceName = functionContext.getNameManagerContext().getSymbolName(cgFunction.getBody(), "instance"); |
| CGClass cgClass = ClassUtil.nonNullState(CGUtil.getContainingClass(cgFunction)); |
| js.append("protected class "); |
| js.append(getFunctionName(cgFunction)); |
| js.append(" extends "); |
| js.appendClassReference(/*isIncremental ? AbstractIdentification.Incremental.class :*/ AbstractValueOccurrence.class); |
| js.append("\n"); |
| js.append("{\n"); |
| js.pushIndentation(null); |
| js.append("protected final "); |
| js.appendIsRequired(true); |
| js.append(" "); |
| js.appendClassReference(cgClass); |
| js.append(" self;\n"); |
| for (@NonNull CGParameter cgParameter : ClassUtil.nullFree(cgFunction.getParameters())) { |
| js.append("protected "); |
| // js.appendDeclaration(cgParameter); |
| // js.appendTypeDeclaration(cgParameter); |
| boolean isPrimitive = js.isPrimitive(cgParameter); |
| boolean isRequired = !isPrimitive && !cgParameter.isAssertedNonNull() && cgParameter.isNonNull() && !(cgParameter instanceof CGUnboxExp)/*|| cgElement.isRequired()*/; // FIXME Ugh! |
| js.appendIsCaught(cgParameter.isNonInvalid(), cgParameter.isCaught()); |
| js.append(" "); |
| js.appendClassReference(isPrimitive ? null : isRequired ? true : null, cgParameter); |
| js.append(" "); |
| js.appendValueName(cgParameter); |
| js.append(";\n"); |
| } |
| // CGValuedElement body = getExpression(cgFunction.getBody()); |
| //ElementId elementId = cgFunction.getTypeId().getElementId(); |
| |
| js.append("protected final "); |
| CGValuedElement cgBody = cgFunction.getBody(); |
| js.appendTypeDeclaration(cgBody != null ? cgBody : cgFunction); |
| js.append(" " + instanceName + ";\n"); |
| js.append("\n"); |
| doFunctionConstructor(cgFunction, instanceName); |
| js.append("\n"); |
| doFunctionGetInstance(cgFunction, instanceName); |
| js.append("\n"); |
| doFunctionIsEqual(cgFunction, instanceName); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| else { |
| // |
| js.append("protected "); |
| js.appendIsRequired(cgFunction.isRequired()); |
| // js.append(" "); |
| // js.appendIsCaught(!cgOperation.isInvalid(), cgOperation.isInvalid()); |
| js.append(" "); |
| ElementId elementId = cgFunction.getTypeId().getElementId(); |
| if (elementId != null) { |
| TypeDescriptor javaTypeDescriptor = context.getUnboxedDescriptor(elementId); |
| js.appendClassReference(javaTypeDescriptor); |
| } |
| js.append(" "); |
| js.append(cgFunction.getName()); |
| js.append("("); |
| boolean isFirst = true; |
| for (@SuppressWarnings("null")@NonNull CGParameter cgParameter : cgParameters) { |
| if (!isFirst) { |
| js.append(", "); |
| } |
| js.appendDeclaration(cgParameter); |
| isFirst = false; |
| } |
| js.append(")"); |
| return doFunctionBody(cgFunction); |
| } |
| } |
| finally { |
| localContext = null; |
| } |
| } |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGFunctionCallExp(@NonNull CGFunctionCallExp cgFunctionCallExp) { |
| Operation pOperation = cgFunctionCallExp.getReferredOperation(); |
| CGFunction cgFunction = ClassUtil.nonNullState(cgFunctionCallExp.getFunction()); |
| CGShadowExp cgShadowExp = useClass(cgFunction); |
| boolean useCache = useCache(cgFunction); |
| boolean isIdentifiedInstance = (cgShadowExp != null) || useCache; |
| List<CGValuedElement> cgArguments = cgFunctionCallExp.getArguments(); |
| List<Parameter> pParameters = pOperation.getOwnedParameters(); |
| // |
| for (@SuppressWarnings("null")@NonNull CGValuedElement cgArgument : cgArguments) { |
| CGValuedElement argument = getExpression(cgArgument); |
| if (!js.appendLocalStatements(argument)) { |
| return false; |
| } |
| } |
| // |
| js.appendDeclaration(cgFunctionCallExp); |
| js.append(" = "); |
| boolean needComma = false; |
| if (isIdentifiedInstance) { |
| js.append("(("); |
| js.append(getFunctionName(cgFunction)); |
| js.append(")"); |
| js.append(getFunctionCtorName(cgFunction)); |
| js.append(".getUniqueComputation("); |
| if (useCache && (cgShadowExp == null)) { |
| CGClass cgClass = ClassUtil.nonNullState(cgFunction.getContainingClass()); |
| js.appendClassReference(cgClass); |
| js.append(".this"); |
| needComma = true; |
| } |
| } |
| else { |
| js.append(pOperation.getName()); |
| js.append("("); |
| } |
| int iMax = Math.min(pParameters.size(), cgArguments.size()); |
| for (int i = 0; i < iMax; i++) { |
| if (needComma) { |
| js.append(", "); |
| } |
| CGValuedElement cgArgument = cgArguments.get(i); |
| CGValuedElement argument = getExpression(cgArgument); |
| Parameter pParameter = pParameters.get(i); |
| // CGTypeId cgParameterTypeId = analyzer.getTypeId(pParameter.getTypeId()); |
| TypeDescriptor parameterTypeDescriptor = context.getUnboxedDescriptor(pParameter.getTypeId()); |
| js.appendReferenceTo(parameterTypeDescriptor, argument); |
| needComma = true; |
| } |
| js.append(")"); |
| if (isIdentifiedInstance) { |
| js.append(")"); |
| JavaLocalContext<@NonNull ?> functionContext = ClassUtil.nonNullState(globalContext.getLocalContext(cgFunction)); |
| String instanceName = functionContext.getNameManagerContext().getSymbolName(cgFunction.getBody(), "instance"); |
| // js.append(".getInstance()"); |
| js.append("."); |
| js.append(instanceName); |
| } |
| js.append(";\n"); |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGFunctionParameter(@NonNull CGFunctionParameter object) { |
| return visitCGParameter(object); |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGGuardVariable(@NonNull CGGuardVariable object) { |
| return visitCGParameter(object); |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGMapping(@NonNull CGMapping cgMapping) { |
| JavaLocalContext<@NonNull ?> localContext2 = globalContext.getLocalContext(cgMapping); |
| if (localContext2 != null) { |
| localContext = localContext2; |
| try { |
| List<@NonNull CGGuardVariable> cgFreeVariables = ClassUtil.nullFree(cgMapping.getFreeVariables()); |
| // |
| js.appendCommentWithOCL(null, cgMapping.getAst()); |
| if (useClass(cgMapping) && (cgFreeVariables.size() > 0)) { |
| js.append("protected class "); |
| js.append(getMappingName(cgMapping)); |
| js.append(" extends "); |
| js.appendClassReference(isIncremental ? AbstractInvocation.Incremental.class : AbstractInvocation.class); |
| js.append("\n"); |
| js.append("{\n"); |
| js.pushIndentation(null); |
| for (@NonNull CGGuardVariable cgFreeVariable : cgFreeVariables) { |
| js.append("protected "); |
| doMappingConnectionVariable(cgFreeVariable); |
| js.append(";\n"); |
| } |
| js.append("\n"); |
| doMappingConstructor(cgMapping); |
| js.append("\n"); |
| js.append("public boolean execute() "); |
| doMappingBody(cgMapping, true); |
| js.append("\n"); |
| doIsEqual(cgFreeVariables); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| else { |
| js.append("protected boolean " + getMappingName(cgMapping) + "("); |
| boolean isFirst = true; |
| for (@NonNull CGGuardVariable cgFreeVariable : cgFreeVariables) { |
| if (!isFirst) { |
| js.append(", "); |
| } |
| doMappingConnectionVariable(cgFreeVariable); |
| isFirst = false; |
| } |
| js.append(") "); |
| |
| doMappingBody(cgMapping, false); |
| |
| } |
| } |
| finally { |
| localContext = null; |
| } |
| } |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGMappingCall(@NonNull CGMappingCall cgMappingCall) { |
| MappingCall pMappingCall = (MappingCall) cgMappingCall.getAst(); |
| Mapping pReferredMapping = pMappingCall.getReferredMapping(); |
| if (pReferredMapping == null) { |
| return true; |
| } |
| CGMapping cgReferredMapping = analyzer.getMapping(pReferredMapping); |
| if (cgReferredMapping == null) { |
| return true; |
| } |
| List<CGMappingCallBinding> cgMappingCallBindings = cgMappingCall.getMappingCallBindings(); |
| for (@SuppressWarnings("null")@NonNull CGMappingCallBinding cgMappingCallBinding : cgMappingCallBindings) { |
| CGValuedElement value = cgMappingCallBinding.getValue(); |
| if (value != null) { |
| if (!js.appendLocalStatements(value)) { |
| return false; |
| } |
| } |
| } |
| // |
| // Set loopVariable non-null if it needs to be type-checked and cast to a narrower type. |
| // |
| for (@SuppressWarnings("null")@NonNull CGMappingCallBinding cgMappingCallBinding : cgMappingCallBindings) { |
| TypeDescriptor checkedType = needsTypeCheck(cgMappingCallBinding); |
| if (checkedType != null) { |
| js.append("if ("); |
| js.appendValueName(cgMappingCallBinding.getValue()); |
| js.append(" instanceof "); |
| js.appendClassReference(checkedType); |
| js.append(") {\n"); |
| js.pushIndentation(null); |
| } |
| else if (!cgMappingCallBinding.isNonNull()) { |
| js.append("if ("); |
| js.appendValueName(cgMappingCallBinding.getValue()); |
| js.append(" != null) {\n"); |
| js.pushIndentation(null); |
| } |
| } |
| // |
| // Emit the mapping call. |
| // |
| if (useClass(cgReferredMapping)) { |
| if (pMappingCall.isIsInfinite()) { |
| js.append("invokeOnce(" + getMappingCtorName(cgReferredMapping) + ", "); |
| } |
| else { |
| js.append("invoke(" + getMappingCtorName(cgReferredMapping) + ", "); |
| } |
| } |
| else { |
| js.append(getMappingName(cgReferredMapping) + "("); |
| } |
| boolean isFirst = true; |
| for (@SuppressWarnings("null")@NonNull CGMappingCallBinding cgMappingCallBinding : cgMappingCallBindings) { |
| if (!isFirst) { |
| js.append(", "); |
| } |
| TypeDescriptor checkedType = needsTypeCheck(cgMappingCallBinding); |
| if (checkedType != null) { |
| js.append("("); |
| js.appendClassReference(checkedType); |
| js.append(")"); |
| } |
| js.appendValueName(cgMappingCallBinding.getValue()); |
| isFirst = false; |
| } |
| js.append(");\n"); |
| // |
| // End the type check. |
| // |
| for (@SuppressWarnings("null")@NonNull CGMappingCallBinding cgMappingCallBinding : cgMappingCallBindings) { |
| TypeDescriptor checkedType = needsTypeCheck(cgMappingCallBinding); |
| if (checkedType != null) { |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| else if (!cgMappingCallBinding.isNonNull()) { |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| } |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGMappingCallBinding(@NonNull CGMappingCallBinding object) { |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGMappingExp(@NonNull CGMappingExp cgMappingExp) { |
| // assert cgMappingExp.getPredicates().isEmpty(); // Get rewritten during JavaPre pass |
| List<@NonNull CGAccumulator> cgAccumulators = ClassUtil.nullFree(cgMappingExp.getOwnedAccumulators()); |
| if (cgAccumulators.size() > 0) { |
| js.append("// connection variables\n"); |
| for (@NonNull CGAccumulator cgAccumulator : cgAccumulators) { |
| Element ast = cgAccumulator.getAst(); |
| js.append("final "); |
| js.appendClassReference(null, cgAccumulator); |
| js.append("."); |
| js.appendIsRequired(true); |
| js.append(" Accumulator "); |
| js.appendValueName(cgAccumulator); |
| js.append(" = "); |
| if ((ast instanceof ConnectionVariable) && (((ConnectionVariable)ast).getType() instanceof SetType)) { |
| js.append("createUnenforcedSetAccumulatorValue("); |
| } |
| else { |
| js.append("("); |
| js.appendClassReference(null, cgAccumulator); |
| js.append(".Accumulator)"); |
| js.appendClassReference(ValueUtil.class); |
| js.append(".createCollectionAccumulatorValue("); |
| } |
| js.appendValueName(cgAccumulator.getTypeId()); |
| js.append(");\n"); |
| // |
| CGValuedElement cgInit = cgAccumulator.getInit(); |
| if ((cgInit != null) && (!(cgInit instanceof CGCollectionExp) || !Iterables.isEmpty(((CGCollectionExp)cgInit).getParts()))) { |
| if (!js.appendLocalStatements(cgInit)) { |
| return false; |
| } |
| final String iteratorName = getSymbolName(null, "iterator"); |
| CollectionTypeId collectionTypeId = (CollectionTypeId)cgInit.getASTypeId(); |
| assert collectionTypeId != null; |
| TypeId elementTypeId = collectionTypeId.getElementTypeId(); |
| BoxedDescriptor boxedDescriptor = context.getBoxedDescriptor(elementTypeId); |
| js.append("for ("); |
| js.appendClassReference(Boolean.TRUE, boxedDescriptor); |
| js.append(" "); |
| js.append(iteratorName); |
| js.append(" : "); |
| js.appendClassReference(ValueUtil.class); |
| js.append(".typedIterable("); |
| js.appendClassReference(boxedDescriptor); |
| js.append(".class, "); |
| js.appendValueName(cgInit); |
| js.append(")"); |
| // js.appendReferenceTo(cgAccumulator.getInit()); |
| js.append(") {\n"); |
| js.pushIndentation(null); |
| js.appendReferenceTo(cgAccumulator); |
| js.append(".add("); |
| js.append(iteratorName); |
| js.append(");\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| // js.appendClassReference(cgAccumulator); |
| // _m_join_m_PackageCS_m_0_0 = (SetValue.Accumulator)ValueUtil.createCollectionAccumulatorValue(SET_CLSSid_OclElement); |
| // cgAccumulator.accept(this); |
| } |
| } |
| } |
| List<@NonNull CGValuedElement> cgRealizedVariables = ClassUtil.nullFree(cgMappingExp.getRealizedVariables()); |
| if (cgRealizedVariables.size() > 0) { |
| js.append("// creations\n"); |
| for (@NonNull CGValuedElement cgRealizedVariable : cgRealizedVariables) { |
| cgRealizedVariable.accept(this); |
| } |
| } |
| List<@NonNull CGPropertyAssignment> cgPropertyAssignments = ClassUtil.nullFree(cgMappingExp.getAssignments()); |
| if (cgPropertyAssignments.size() > 0) { |
| js.append("// property assignments\n"); |
| for (@NonNull CGPropertyAssignment cgAssignment : cgPropertyAssignments) { |
| cgAssignment.accept(this); |
| } |
| } |
| List<@NonNull CGConnectionAssignment> cgConnectionAssignments = ClassUtil.nullFree(cgMappingExp.getConnectionAssignments()); |
| if (cgConnectionAssignments.size() > 0) { |
| js.append("// connection assignments\n"); |
| for (@NonNull CGConnectionAssignment cgConnectionAssignment : cgConnectionAssignments) { |
| cgConnectionAssignment.accept(this); |
| } |
| } |
| CGValuedElement body = cgMappingExp.getBody(); |
| if (body != null) { |
| js.append("// mapping statements\n"); |
| body.accept(this); |
| } |
| js.appendDeclaration(cgMappingExp); |
| js.append(" = "); |
| js.appendClassReference(ValueUtil.class); |
| js.append(".TRUE_VALUE;\n"); |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGMappingLoop(@NonNull CGMappingLoop cgMappingLoop) { |
| CGValuedElement source = getExpression(cgMappingLoop.getSource()); |
| CGIterator iterator = cgMappingLoop.getIterators().get(0); |
| if (!js.appendLocalStatements(source)) { |
| return false; |
| } |
| js.append("for ("); |
| js.appendClassReference(Boolean.TRUE, iterator); |
| js.append(" "); |
| js.appendValueName(iterator); |
| js.append(" : "); |
| if (source.isBoxed()) { |
| js.appendClassReference(ValueUtil.class); |
| js.append(".typedIterable("); |
| js.appendClassReference(null, iterator); |
| js.append(".class, "); |
| js.appendValueName(source); |
| js.append(")"); |
| } |
| else { |
| js.appendValueName(source); |
| } |
| js.append(") {\n"); |
| js.pushIndentation(null); |
| if (!iterator.isNonNull()) { |
| js.append("if ("); |
| js.appendValueName(iterator); |
| js.append(" != null) {\n"); |
| js.pushIndentation(null); |
| } |
| cgMappingLoop.getBody().accept(this); |
| if (!iterator.isNonNull()) { |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| js.popIndentation(); |
| js.append("}\n"); |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGMiddlePropertyAssignment(@NonNull CGMiddlePropertyAssignment cgMiddlePropertyAssignment) { |
| Property pReferredProperty = ClassUtil.nonNullModel(cgMiddlePropertyAssignment.getReferredProperty()); |
| assert !pReferredProperty.isIsImplicit(); |
| CGValuedElement slotValue = cgMiddlePropertyAssignment.getSlotValue(); |
| CGValuedElement initValue = cgMiddlePropertyAssignment.getInitValue(); |
| if ((slotValue != null) && (initValue != null)) { |
| Map<@NonNull Property, @NonNull String> oppositeProperties = getGlobalContext().getOppositeProperties(); |
| if (oppositeProperties != null) { |
| String cacheName = oppositeProperties.get(pReferredProperty); |
| if (cacheName != null) { |
| js.append(cacheName); |
| js.append(".put("); |
| js.appendValueName(initValue); |
| js.append(", "); |
| js.appendValueName(slotValue); |
| js.append(");\n"); |
| } |
| } |
| } |
| return visitCGEcorePropertyAssignment(cgMiddlePropertyAssignment); |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGMiddlePropertyCallExp(@NonNull CGMiddlePropertyCallExp cgPropertyCallExp) { |
| Property asOppositeProperty = ClassUtil.nonNullModel(cgPropertyCallExp.getReferredProperty()); |
| Property asProperty = ClassUtil.nonNullModel(asOppositeProperty.getOpposite()); |
| assert !asProperty.isIsImplicit(); |
| CGValuedElement source = getExpression(cgPropertyCallExp.getSource()); |
| // |
| if (!js.appendLocalStatements(source)) { |
| return false; |
| } |
| // |
| EStructuralFeature eStructuralFeature = ClassUtil.nonNullState((EStructuralFeature) asProperty.getESObject()); |
| doGetting(cgPropertyCallExp, eStructuralFeature, true); |
| js.appendDeclaration(cgPropertyCallExp); |
| js.append(" = "); |
| Map<Property, String> oppositeProperties = getGlobalContext().getOppositeProperties(); |
| if (oppositeProperties != null) { |
| boolean isRequired = cgPropertyCallExp.isRequired(); |
| String cacheName = oppositeProperties.get(asProperty); |
| if (cacheName != null) { |
| if (isRequired) { |
| js.appendClassReference(ClassUtil.class); |
| js.append(".nonNullState ("); |
| } |
| js.append(cacheName); |
| js.append(".get("); |
| js.appendValueName(source); |
| js.append(")"); |
| if (isRequired) { |
| js.append(")"); |
| } |
| } |
| js.append(";\n"); |
| } |
| doGot(cgPropertyCallExp, source, eStructuralFeature); |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGPropertyAssignment(@NonNull CGPropertyAssignment cgPropertyAssignment) { |
| CGExecutorProperty cgExecutorProperty = cgPropertyAssignment.getExecutorProperty(); |
| CGValuedElement slotValue = cgPropertyAssignment.getSlotValue(); |
| CGValuedElement initValue = cgPropertyAssignment.getInitValue(); |
| if ((slotValue != null) && (initValue != null)) { |
| if (!js.appendLocalStatements(slotValue)) { |
| return false; |
| } |
| if (!js.appendLocalStatements(initValue)) { |
| return false; |
| } |
| js.appendReferenceTo(cgExecutorProperty); |
| js.append(".initValue("); |
| js.appendValueName(slotValue); |
| js.append(", "); |
| js.appendValueName(initValue); |
| js.append(");\n"); |
| } |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGRealizedVariable(@NonNull CGRealizedVariable cgRealizedVariable) { |
| TypeId typeId = cgRealizedVariable.getASTypeId(); |
| if (typeId != null) { |
| js.appendDeclaration(cgRealizedVariable); |
| js.append(" = "); |
| js.appendReferenceTo(cgRealizedVariable.getExecutorType()); |
| js.append(".createInstance();\n"); |
| } |
| // |
| doAddRealization(cgRealizedVariable); |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGSequence(@NonNull CGSequence cgSequence) { |
| for (@NonNull CGValuedElement cgStatement : ClassUtil.nullFree(cgSequence.getStatements())) { |
| cgStatement.accept(this); |
| } |
| return true; |
| } |
| |
| /* @Override |
| public @NonNull Boolean visitCGShadowExp(@NonNull CGShadowExp cgShadowExp) { |
| super.visitCGShadowExp(cgShadowExp); |
| ShadowExp asShadowExp = (ShadowExp)ClassUtil.nonNullState(cgShadowExp.getAst()); |
| DomainUsage usage = transformationAnalysis.getDomainUsageAnalysis().getUsage(asShadowExp); |
| TypedModel asTypedModel = ClassUtil.nonNullState(usage.getTypedModel(asShadowExp)); |
| CGTypedModel cgTypedModel = context.getAnalyzer().getTypedModel(asTypedModel); |
| js.append(QVTiGlobalContext.MODELS_NAME); |
| js.append("["); |
| appendModelIndex(cgTypedModel); |
| js.append("].add("); |
| js.appendValueName(cgShadowExp); |
| js.append(");\n"); |
| return true; |
| } */ |
| |
| @Override |
| public @NonNull Boolean visitCGTransformation(@NonNull CGTransformation cgTransformation) { |
| js.appendClassHeader(cgTransformation.getContainingPackage()); |
| @SuppressWarnings("null")@NonNull ImperativeTransformation transformation = (ImperativeTransformation) cgTransformation.getAst(); |
| QVTiTransformationAnalysis transformationAnalysis = context.getTransformationAnalysis(transformation); |
| this.transformationAnalysis = transformationAnalysis; |
| String className = cgTransformation.getName(); |
| js.append("/**\n"); |
| js.append(" * The " + className + " transformation:\n"); |
| js.append(" * <p>\n"); |
| js.append(" * Construct with an evaluator\n"); |
| js.append(" * <br>\n"); |
| js.append(" * Populate each input model with {@link addRootObjects(String,List)}\n"); |
| js.append(" * <br>\n"); |
| js.append(" * {@link run()}\n"); |
| js.append(" * <br>\n"); |
| js.append(" * Extract each output model with {@link getRootObjects(String)}\n"); |
| js.append(" */\n"); |
| js.append("@SuppressWarnings(\"nls\")\n"); |
| js.append("public class " + className + " extends "); |
| js.appendClassReference(getAbstractTransformationExecutorClass()); |
| js.append("\n"); |
| js.append("{\n"); |
| js.pushIndentation(null); |
| if (sortedGlobals != null) { |
| for (CGValuedElement cgElement : sortedGlobals) { |
| assert cgElement.isGlobal(); |
| cgElement.accept(this); |
| } |
| } |
| doOppositeCaches(transformationAnalysis); |
| js.append("\n"); |
| String oppositeIndex2propertyIdName = doOppositePropertyIds(transformationAnalysis); |
| if (oppositeIndex2propertyIdName != null) { |
| js.append("\n"); |
| } |
| @NonNull String @Nullable [] allInstancesNames = doAllInstances(transformationAnalysis); |
| js.append("\n"); |
| List<@NonNull CGMapping> cgMappings = ClassUtil.nullFree(cgTransformation.getMappings()); |
| List<CGOperation> cgOperations = cgTransformation.getOperations(); |
| doMappingConstructorConstants(cgMappings); |
| doFunctionConstructorConstants(ClassUtil.nullFree(cgOperations)); |
| // js.append("\n"); |
| doConstructor(cgTransformation, oppositeIndex2propertyIdName, allInstancesNames); |
| js.append("\n"); |
| if (isIncremental) { |
| doCreateIncrementalManagers(); |
| js.append("\n"); |
| } |
| doRun(cgTransformation); |
| for (@NonNull CGOperation cgOperation : ClassUtil.nullFree(cgOperations)) { |
| js.append("\n"); |
| cgOperation.accept(this); |
| } |
| for (@NonNull CGMapping cgMapping : ClassUtil.nullFree(cgTransformation.getMappings())) { |
| js.append("\n"); |
| cgMapping.accept(this); |
| } |
| js.popIndentation(); |
| js.append("}\n"); |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGTypedModel(@NonNull CGTypedModel object) { |
| return true; |
| } |
| } |