| /******************************************************************************* |
| * Copyright (c) 2013, 2020 Willink Transformations 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 - 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.Comparator; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.emf.codegen.ecore.genmodel.GenPackage; |
| import org.eclipse.emf.codegen.util.CodeGenUtil; |
| import org.eclipse.emf.common.notify.Adapter; |
| import org.eclipse.emf.ecore.EAttribute; |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.emf.ecore.EClassifier; |
| import org.eclipse.emf.ecore.EDataType; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EPackage; |
| import org.eclipse.emf.ecore.EReference; |
| import org.eclipse.emf.ecore.EStructuralFeature; |
| import org.eclipse.jdt.annotation.NonNull; |
| import org.eclipse.jdt.annotation.Nullable; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGAccumulator; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGCachedOperation; |
| 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.CGElement; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGElementId; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGExecutorProperty; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGExecutorType; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGGuardExp; |
| 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.CGOppositePropertyCallExp; |
| 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.cgmodel.CGVariable; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGVariableExp; |
| 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.JavaStream.SubStream; |
| import org.eclipse.ocl.examples.codegen.java.types.BoxedDescriptor; |
| import org.eclipse.ocl.examples.codegen.utilities.CGUtil; |
| import org.eclipse.ocl.pivot.CompleteClass; |
| import org.eclipse.ocl.pivot.DataType; |
| import org.eclipse.ocl.pivot.Element; |
| import org.eclipse.ocl.pivot.NamedElement; |
| 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.ShadowPart; |
| import org.eclipse.ocl.pivot.TypedElement; |
| import org.eclipse.ocl.pivot.Type; |
| import org.eclipse.ocl.pivot.VariableDeclaration; |
| import org.eclipse.ocl.pivot.VariableExp; |
| 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.PropertyId; |
| import org.eclipse.ocl.pivot.ids.TypeId; |
| import org.eclipse.ocl.pivot.internal.complete.CompleteModelInternal; |
| import org.eclipse.ocl.pivot.internal.library.executor.AbstractEvaluationOperation; |
| 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.LabelUtil; |
| import org.eclipse.ocl.pivot.utilities.NameUtil; |
| import org.eclipse.ocl.pivot.utilities.PivotUtil; |
| import org.eclipse.ocl.pivot.utilities.TreeIterable; |
| 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.CGRealizedVariablePart; |
| import org.eclipse.qvtd.codegen.qvticgmodel.CGSequence; |
| import org.eclipse.qvtd.codegen.qvticgmodel.CGSpeculateExp; |
| import org.eclipse.qvtd.codegen.qvticgmodel.CGSpeculatePart; |
| 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.qvtbase.Function; |
| import org.eclipse.qvtd.pivot.qvtbase.Transformation; |
| import org.eclipse.qvtd.pivot.qvtbase.TypedModel; |
| import org.eclipse.qvtd.pivot.qvtimperative.AppendParameterBinding; |
| import org.eclipse.qvtd.pivot.qvtimperative.BufferStatement; |
| import org.eclipse.qvtd.pivot.qvtimperative.ConnectionVariable; |
| import org.eclipse.qvtd.pivot.qvtimperative.EntryPoint; |
| import org.eclipse.qvtd.pivot.qvtimperative.GuardParameter; |
| import org.eclipse.qvtd.pivot.qvtimperative.GuardParameterBinding; |
| import org.eclipse.qvtd.pivot.qvtimperative.ImperativeTransformation; |
| import org.eclipse.qvtd.pivot.qvtimperative.LoopParameterBinding; |
| 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.NewStatement; |
| import org.eclipse.qvtd.pivot.qvtimperative.NewStatementPart; |
| import org.eclipse.qvtd.pivot.qvtimperative.ObservableStatement; |
| import org.eclipse.qvtd.pivot.qvtimperative.SetStatement; |
| import org.eclipse.qvtd.pivot.qvtimperative.evaluation.QVTiModelsManager; |
| import org.eclipse.qvtd.pivot.qvtimperative.evaluation.EntryPointAnalysis; |
| import org.eclipse.qvtd.pivot.qvtimperative.evaluation.EntryPointsAnalysis; |
| import org.eclipse.qvtd.pivot.qvtimperative.evaluation.TypedModelAnalysis; |
| import org.eclipse.qvtd.pivot.qvtimperative.utilities.QVTimperativeUtil; |
| import org.eclipse.qvtd.runtime.evaluation.AbstractComputation; |
| import org.eclipse.qvtd.runtime.evaluation.AbstractInvocation; |
| import org.eclipse.qvtd.runtime.evaluation.AbstractSimpleInvocation; |
| import org.eclipse.qvtd.runtime.evaluation.AbstractTransformer; |
| import org.eclipse.qvtd.runtime.evaluation.Connection; |
| import org.eclipse.qvtd.runtime.evaluation.Interval; |
| import org.eclipse.qvtd.runtime.evaluation.InvalidEvaluationException; |
| import org.eclipse.qvtd.runtime.evaluation.InvocationConstructor; |
| import org.eclipse.qvtd.runtime.evaluation.InvocationFailedException; |
| import org.eclipse.qvtd.runtime.evaluation.ModeFactory; |
| import org.eclipse.qvtd.runtime.evaluation.SlotState; |
| import org.eclipse.qvtd.runtime.evaluation.TransformationExecutor; |
| 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.RuntimeModelsManager; |
| |
| 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> |
| { |
| protected /*static*/ class AllInstancesAnalysis extends TypedModelAnalysis |
| { |
| private @NonNull String @Nullable [] names = null; |
| private @Nullable String extentOppositesName = null; |
| |
| public AllInstancesAnalysis(@NonNull EntryPointsAnalysis entryPointsAnalysis, @NonNull TypedModel typedModel, @NonNull Set<@NonNull CompleteClass> allInstancesCompleteClasses) { |
| super(entryPointsAnalysis, typedModel, allInstancesCompleteClasses); |
| ClassId extentClassId = QVTiModelsManager.EXTENT_CLASSID; |
| Map<@NonNull Property, @NonNull Integer> opposites = entryPointsAnalysis.getCaches(); |
| for (@NonNull Property property : opposites.keySet()) { |
| org.eclipse.ocl.pivot.Class owningClass = PivotUtil.getOwningClass(property); |
| TypeId typeId = owningClass.getTypeId(); |
| if (typeId == extentClassId) { |
| Integer index = opposites.get(property); |
| assert index != null; |
| Map<@NonNull Property, @NonNull String> oppositeProperties = qvtiGlobalContext.getOppositeProperties(); |
| assert oppositeProperties != null; |
| extentOppositesName = oppositeProperties.get(property); |
| // extentOppositesName = "xyzzy"; |
| } |
| } |
| } |
| |
| public @Nullable String getExtentOppositesName() { |
| return extentOppositesName; |
| } |
| |
| protected @NonNull Map<@NonNull CompleteClass, @NonNull Integer> getInstancesCompleteClass2index() { |
| return instancesCompleteClass2index; |
| } |
| |
| protected @NonNull Map<@NonNull CompleteClass, @Nullable List<@NonNull CompleteClass>> getInstancesCompleteClassAnalysis() { |
| return instancesCompleteClassAnalysis; |
| } |
| |
| protected @NonNull String @NonNull [] getNames() { |
| return ClassUtil.nonNullState(names); |
| } |
| |
| protected @NonNull List<@NonNull CompleteClass> getSortedCompleteClasses() { |
| return sortedCompleteClasses; |
| } |
| |
| public void setNames(@NonNull String[] names) { |
| this.names = names; |
| } |
| } |
| |
| /** |
| * A CachedInstance identifies the characteristics of a shared mapping invocation. |
| */ |
| private class CachedInstance |
| { |
| private org.eclipse.ocl.pivot.@NonNull Class asClass; |
| private @NonNull CGExecutorType cgExecutorType; |
| private @NonNull List<@NonNull CGExecutorProperty> cgProperties; |
| private int modelIndex; |
| |
| protected CachedInstance(org.eclipse.ocl.pivot.@NonNull Class asClass, @NonNull CGExecutorType cgExecutorType, |
| @NonNull List<@NonNull CGExecutorProperty> cgProperties, int modelIndex) { |
| this.asClass = asClass; |
| this.cgExecutorType = cgExecutorType; |
| this.cgProperties = cgProperties; |
| this.modelIndex = modelIndex; |
| } |
| |
| public @NonNull Boolean doCachedInstance() { |
| String instanceClassName = getNativeInstanceClassName(cgExecutorType); |
| js.append("public class "); |
| js.append(instanceClassName); |
| js.append(" extends "); |
| js.appendClassReference(null, AbstractEvaluationOperation.class); |
| js.pushClassBody(instanceClassName); |
| doCachedInstanceBasicEvaluate(); |
| js.append("\n"); |
| doCachedInstanceEvaluate(); |
| js.popClassBody(false); |
| // |
| js.append("\n"); |
| doCachedInstanceClassInstance(); |
| return true; |
| } |
| |
| protected void doCachedInstanceBasicEvaluate() { |
| js.append("@Override\n"); |
| js.append("public "); |
| js.appendClassReference(false, Object.class); |
| js.append(" basicEvaluate("); |
| js.appendClassReference(true, Executor.class); |
| js.append(" "); |
| js.append(qvtiGlobalContext.getExecutorName()); |
| js.append(", "); |
| js.appendClassReference(true, TypedElement.class); |
| js.append(" "); |
| js.append("caller"); |
| js.append(", "); |
| js.appendClassReference(false, Object.class); |
| js.append(" "); |
| js.appendIsRequired(true); |
| js.append(" [] "); |
| js.append(JavaConstants.SOURCE_AND_ARGUMENT_VALUES_NAME); |
| js.append(") {\n"); |
| js.pushIndentation(null); |
| |
| EClass eClass = (EClass)asClass.getESObject(); |
| assert eClass != null; |
| String createMethodName = "create" + eClass.getName(); |
| boolean canSetNonNull = false; |
| EPackage ePackage = eClass.getEPackage(); |
| 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) { |
| canSetNonNull = true; |
| } |
| } |
| } |
| else { |
| javaClass = genModelHelper.getQualifiedFactoryInterfaceName(ePackage); |
| } |
| } |
| else { |
| javaClass = null; |
| } |
| // |
| String instanceName = "instance"; |
| js.appendTypeDeclaration(cgExecutorType); |
| js.append(" " + instanceName + " = "); |
| js.appendClassReference(null, javaClass); |
| js.append(".eINSTANCE."); |
| js.append(createMethodName); |
| js.append("();\n"); |
| |
| |
| |
| Map<@NonNull Property, @NonNull String> oppositeProperties = qvtiGlobalContext.getOppositeProperties(); |
| int i = 0; |
| for (@NonNull CGExecutorProperty cgProperty : cgProperties) { |
| Property asProperty = QVTiCGUtil.getAST(cgProperty); |
| String setAccessor = genModelHelper.getSetAccessor((EStructuralFeature)asProperty.getESObject()); |
| if (cgProperty.getASTypeId() instanceof CollectionTypeId) { |
| js.append("@SuppressWarnings(\"unchecked\") "); |
| } |
| else if (cgProperty.isRequired()) { |
| if (js.appendSuppressWarningsNull(false)) { |
| js.append(" "); |
| } |
| } |
| js.appendTypeDeclaration(cgProperty); |
| js.append(" value" + i + " = ("); |
| js.appendTypeDeclaration(cgProperty); |
| js.append(")"); |
| js.append(JavaConstants.SOURCE_AND_ARGUMENT_VALUES_NAME); |
| js.append("[" + i + "];\n"); |
| |
| js.append(instanceName + "." + setAccessor + "(value" + i); |
| js.append(");\n"); |
| |
| if (oppositeProperties != null) { |
| Property iProperty = QVTiCGUtil.getAST(cgProperty); |
| String cacheName = oppositeProperties.get(iProperty); |
| if (cacheName != null) { |
| js.append(cacheName); |
| js.append(".put(value" + i); |
| js.append(", "); |
| // js.appendReferenceTo(outerTypeDescriptor, slotValue); |
| js.append(instanceName); |
| js.append(");\n"); |
| } |
| } |
| |
| |
| i++; |
| |
| |
| } |
| |
| |
| js.append(qvtiGlobalContext.getModelsName()); |
| js.append("[" + modelIndex + "].add("); |
| js.append(instanceName); |
| js.append(", false);\n"); |
| |
| |
| |
| js.append("return " + instanceName + ";\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| |
| protected void doCachedInstanceEvaluate() { |
| js.append("public "); |
| js.appendClassReference(true, cgExecutorType); |
| js.append(" "); |
| js.append(globalContext.getEvaluateName()); |
| js.append("("); |
| boolean isFirst = true; |
| for (@NonNull CGExecutorProperty cgProperty : cgProperties) { |
| if (!isFirst) { |
| js.append(", "); |
| } |
| js.appendDeclaration(cgProperty); |
| isFirst = false; |
| } |
| js.append(") {\n"); |
| js.pushIndentation(null); |
| js.append("return ("); |
| js.appendClassReference(true, cgExecutorType); |
| js.append(")"); |
| js.append(qvtiGlobalContext.getEvaluationCacheName()); |
| js.append("."); |
| js.append(globalContext.getGetCachedEvaluationResultName()); |
| js.append("(this, caller, new "); |
| js.appendClassReference(false, Object.class); |
| js.append("[]{"); |
| isFirst = true; |
| for (@NonNull CGExecutorProperty cgProperty : cgProperties) { |
| if (!isFirst) { |
| js.append(", "); |
| } |
| js.appendValueName(cgProperty); |
| isFirst = false; |
| } |
| js.append("});\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| |
| protected void doCachedInstanceClassInstance() { |
| String instanceClassName = getNativeInstanceClassName(cgExecutorType); |
| js.append("protected final "); |
| js.appendIsRequired(true); |
| js.append(" "); |
| js.append(instanceClassName); |
| js.append(" "); |
| js.append(getNativeInstanceInstanceName(cgExecutorType)); |
| js.append(" = new "); |
| js.append(instanceClassName); |
| js.append("();\n"); |
| } |
| |
| public void check(@NonNull List<@NonNull CGExecutorProperty> cgProperties, int modelIndex) { |
| // TODO Auto-generated method stub |
| // List<@NonNull CGExecutorProperty> oldProperties = cachedInstances.put(cgType, cgProperties); |
| // if (oldProperties != null) { |
| // assert oldProperties.equals(cgProperties); |
| // } |
| |
| } |
| } |
| |
| /** |
| * 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 QVTiGlobalContext qvtiGlobalContext; |
| protected final @NonNull CGPackage cgPackage; |
| protected final @Nullable Iterable<@NonNull CGValuedElement> sortedGlobals; |
| protected boolean isGeneratedDebug = false; |
| protected boolean isIncremental = false; |
| protected boolean alwaysUseClasses = false; |
| protected boolean useGot = true; |
| |
| /* Non-null while wrapping a function-implemented mapping in a SimpleInvocation */ |
| private @Nullable Mapping invocationWrapper = null; |
| |
| public QVTiCG2JavaVisitor(@NonNull QVTiCodeGenerator codeGenerator, @NonNull CGPackage cgPackage, |
| @Nullable Iterable<@NonNull CGValuedElement> sortedGlobals) { |
| super(codeGenerator); |
| this.analyzer = codeGenerator.getAnalyzer(); |
| this.qvtiGlobalContext = getGlobalContext(); |
| this.cgPackage = cgPackage; |
| this.sortedGlobals = sortedGlobals; |
| this.isGeneratedDebug = codeGenerator.getOptions().isGeneratedDebug(); |
| this.isIncremental = codeGenerator.getOptions().isIncremental(); |
| this.alwaysUseClasses = isIncremental; |
| this.useGot = isIncremental; |
| } |
| |
| protected void appendConnectionBinding(@NonNull CGMappingCallBinding cgMappingCallBinding) { |
| TypeDescriptor checkedType = needsTypeCheck(cgMappingCallBinding); |
| if (checkedType != null) { |
| needsTypeCheck(cgMappingCallBinding); |
| js.append("("); |
| js.appendClassReference(null, checkedType); |
| js.append(")"); |
| } |
| js.appendValueName(cgMappingCallBinding.getOwnedValue()); |
| } |
| |
| protected void appendEcoreSet(@NonNull CGValuedElement cgSlot, @NonNull EStructuralFeature eStructuralFeature, @NonNull CGValuedElement cgInit, boolean isPartial) { |
| EClassifier eType = eStructuralFeature.getEType(); |
| String instanceClassName = eType.getInstanceClassName(); |
| if (eStructuralFeature.isMany()) { |
| String getAccessor = genModelHelper.getGetAccessor(eStructuralFeature); |
| // |
| js.appendValueName(cgSlot); |
| js.append("."); |
| js.append(getAccessor); |
| js.append("()."); |
| if (isPartial) { |
| js.append("add("); |
| if (instanceClassName != null) { |
| js.appendEcoreValue(instanceClassName, cgInit); |
| } |
| else { |
| js.appendAtomicReferenceTo(cgInit); |
| } |
| } |
| else { |
| js.append( "addAll("); // FIXME may need to loop addAll manually |
| js.appendAtomicReferenceTo(cgInit); |
| } |
| js.append(");\n"); |
| } |
| else { |
| String setAccessor = genModelHelper.getSetAccessor(eStructuralFeature); |
| // |
| js.appendValueName(cgSlot); |
| js.append("."); |
| js.append(setAccessor); |
| js.append("("); |
| if (instanceClassName != null) { |
| js.appendEcoreValue(instanceClassName, cgInit); |
| } |
| else { |
| js.appendAtomicReferenceTo(cgInit); |
| } |
| js.append(");\n"); |
| } |
| } |
| |
| @Override // FIXME promote to OCL |
| protected void appendGuardFailure(@NonNull CGGuardExp cgGuardExp) { |
| js.append("throw new "); |
| js.appendClassReference(null, InvalidEvaluationException.class); |
| js.append("("); |
| js.appendString("Null " + cgGuardExp.getMessage()); |
| 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 appendModelReference(@Nullable CGTypedModel cgTypedModel) { |
| js.append(qvtiGlobalContext.getModelsName()); |
| js.append("["); |
| appendModelIndex(cgTypedModel); |
| js.append("]"); |
| } |
| |
| protected 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 appendThis(@NonNull CGElement cgElement) { |
| for (EObject eObject = cgElement; eObject != null; eObject = eObject.eContainer()) { |
| if (eObject instanceof CGMapping) { |
| js.appendThis(getMappingName((CGMapping)eObject)); // + ".this" |
| return; |
| } |
| if (eObject instanceof CGFunction) { |
| js.appendThis(getFunctionName((CGFunction)eObject)); // + ".this" |
| return; |
| } |
| if (eObject instanceof CGClass) { |
| js.appendThis(ClassUtil.nonNullState(((CGClass)eObject).getName())); // + ".this" |
| return; |
| } |
| } |
| assert false; |
| js.appendThis(""); // "this" |
| return; |
| } |
| |
| protected void doAddRealization(@NonNull CGRealizedVariable cgRealizedVariable) { |
| boolean isShared = cgRealizedVariable.getOwnedParts().size() > 0; |
| CGTypedModel cgTypedModel = cgRealizedVariable.getTypedModel(); |
| NewStatement asNewStatement = QVTiCGUtil.getAST(cgRealizedVariable); |
| // |
| if (!isShared) { |
| appendModelReference(cgTypedModel); |
| js.append(".add("); |
| js.appendValueName(cgRealizedVariable); |
| js.append(", "); |
| js.appendBooleanString(asNewStatement.isIsContained()); |
| js.append(");\n"); |
| } |
| // |
| if (isGeneratedDebug) { |
| js.append("if (debugCreations) {\n"); |
| js.pushIndentation(null); |
| js.appendClassReference(null, AbstractTransformer.class); |
| js.append(".CREATIONS.println(\"created \""); |
| js.append(" + toDebugString("); |
| js.append(getResolvedName(cgRealizedVariable)); |
| js.append(")"); |
| js.append(");\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| // |
| if (isIncremental) { |
| js.append(qvtiGlobalContext.getObjectManagerName()); |
| js.append(".created("); |
| appendThis(cgRealizedVariable); |
| js.append(", "); |
| js.appendValueName(cgRealizedVariable); |
| js.append(");\n"); |
| } |
| } |
| |
| protected @Nullable List<@Nullable AllInstancesAnalysis> doAllInstances(@NonNull EntryPointsAnalysis entryPointsAnalysis) { |
| CompleteModelInternal completeModel = environmentFactory.getCompleteModel(); |
| Set<@NonNull CompleteClass> allInstancesCompleteClasses = new HashSet<>(); |
| for (@NonNull CompleteClass allInstancesCompleteClass : entryPointsAnalysis.getAllInstancesCompleteClasses()) { |
| allInstancesCompleteClasses.add(allInstancesCompleteClass); |
| } |
| if (allInstancesCompleteClasses.size() <= 0) { |
| return null; |
| } |
| List<@Nullable AllInstancesAnalysis> allInstancesAnalyses = new ArrayList<>(); |
| int typedModelNumber = 0; |
| for (@NonNull TypedModel typedModel : QVTimperativeUtil.getModelParameters(entryPointsAnalysis.getTransformation())) { |
| Set<@NonNull CompleteClass> allInstancesCompleteClasses2 = new HashSet<>(); |
| for (org.eclipse.ocl.pivot.@NonNull Class usedClass : QVTimperativeUtil.getUsedClasses(typedModel)) { |
| allInstancesCompleteClasses2.add(completeModel.getCompleteClass(usedClass)); |
| } |
| allInstancesCompleteClasses2.retainAll(allInstancesCompleteClasses); |
| if (!allInstancesCompleteClasses2.isEmpty()) { |
| AllInstancesAnalysis allInstancesAnalysis = new AllInstancesAnalysis(entryPointsAnalysis, typedModel, allInstancesCompleteClasses2); |
| Map<@NonNull CompleteClass, @NonNull Integer> instancesClass2index = allInstancesAnalysis.getInstancesCompleteClass2index(); |
| List<@NonNull CompleteClass> sortedCompleteClasses = allInstancesAnalysis.getSortedCompleteClasses(); |
| Map<@NonNull CompleteClass, @Nullable List<@NonNull CompleteClass>> instancesClassAnalysis = allInstancesAnalysis.getInstancesCompleteClassAnalysis(); |
| // |
| // 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 for TypedModel " + typedModelNumber + ".\n"); |
| js.append(" */\n"); |
| String classIndex2classIdName = qvtiGlobalContext.getClassIndex2classId(typedModelNumber); |
| js.append("private static final "); |
| js.appendClassReference(true, ClassId.class); |
| js.append(" "); |
| js.appendIsRequired(true); |
| js.append(" [] "); |
| js.append(classIndex2classIdName); |
| js.append(" = new "); |
| js.appendClassReference(true, ClassId.class); |
| js.append("[]{\n"); |
| js.pushIndentation(null); |
| for (int i = 0; i < sortedCompleteClasses.size(); i++) { |
| CompleteClass instancesClass = sortedCompleteClasses.get(i); |
| CGTypeId cgTypeId = getCodeGenerator().getAnalyzer().getTypeId(instancesClass.getPrimaryClass().getTypeId()); |
| int startLength = js.length(); |
| js.appendValueName(cgTypeId); |
| if ((i+1) < sortedCompleteClasses.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 = qvtiGlobalContext.getClassIndex2allClassIndexes(typedModelNumber); |
| js.append("\n"); |
| js.append("/*\n"); |
| js.append(" * Mapping from each TypedModel " + typedModelNumber + " ClassIndex to all the ClassIndexes\n"); |
| js.append(" * to which an object of the outer index 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 int "); |
| js.appendIsRequired(true); |
| js.append(" [] "); |
| js.appendIsRequired(true); |
| js.append(" [] "); |
| js.append(classIndex2allClassIndexes); |
| js.append(" = new int "); |
| js.appendIsRequired(true); |
| js.append(" [] "); |
| js.appendIsRequired(true); |
| js.append(" [] {\n"); |
| js.pushIndentation(null); |
| for (int i = 0; i < sortedCompleteClasses.size(); i++) { |
| CompleteClass instancesClass = sortedCompleteClasses.get(i); |
| List<@NonNull CompleteClass> superInstancesClasses = ClassUtil.nonNullState(instancesClassAnalysis.get(instancesClass)); |
| int startLength = js.length(); |
| js.append("{"); |
| boolean isFirst = true; |
| for (@NonNull CompleteClass superInstancesClass : superInstancesClasses) { |
| if (!isFirst) { |
| js.append(","); |
| } |
| js.append("" + instancesClass2index.get(superInstancesClass)); |
| isFirst = false; |
| } |
| js.append("}"); |
| if ((i+1) < sortedCompleteClasses.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 (@NonNull CompleteClass superInstancesClass : superInstancesClasses) { |
| if (!isFirst) { |
| js.append(","); |
| } |
| js.append(superInstancesClass.getName()); |
| isFirst = false; |
| } |
| js.append("}\n"); |
| } |
| js.popIndentation(); |
| js.append("};\n"); |
| allInstancesAnalysis.setNames(new @NonNull String[]{ classIndex2classIdName, classIndex2allClassIndexes}); |
| allInstancesAnalyses.add(allInstancesAnalysis); |
| } |
| else { |
| allInstancesAnalyses.add(null); |
| } |
| typedModelNumber++; |
| } |
| return allInstancesAnalyses; |
| } |
| |
| protected void doAssigned(@NonNull CGEcoreContainerAssignment cgPropertyAssignment) { |
| EStructuralFeature eStructuralFeature = QVTiCGUtil.getEStructuralFeature(cgPropertyAssignment); |
| CGValuedElement cgSlot = getExpression(QVTiCGUtil.getOwnedSlotValue(cgPropertyAssignment)); |
| CGValuedElement cgInit = getExpression(QVTiCGUtil.getOwnedInitValue(cgPropertyAssignment)); |
| if (isIncremental || ((SetStatement)cgPropertyAssignment.getAst()).isIsNotify()) { |
| js.append(qvtiGlobalContext.getObjectManagerName()); |
| js.append(".assigned("); |
| if (isIncremental) { |
| appendThis(cgPropertyAssignment); |
| js.append(", "); |
| } |
| js.appendValueName(cgInit); |
| js.append(", "); |
| appendQualifiedLiteralName(eStructuralFeature); |
| js.append(", "); |
| js.appendValueName(cgSlot); |
| js.append(", false);\n"); |
| } |
| } |
| |
| protected void doAssigned(@NonNull CGEcorePropertyAssignment cgPropertyAssignment, boolean isPartial) { |
| EStructuralFeature eStructuralFeature = QVTiCGUtil.getEStructuralFeature(cgPropertyAssignment); |
| CGValuedElement cgSlot = getExpression(QVTiCGUtil.getOwnedSlotValue(cgPropertyAssignment)); |
| CGValuedElement cgInit = getExpression(QVTiCGUtil.getOwnedInitValue(cgPropertyAssignment)); |
| if (isIncremental || ((SetStatement)cgPropertyAssignment.getAst()).isIsNotify()) { |
| js.append(qvtiGlobalContext.getObjectManagerName()); |
| js.append(".assigned("); |
| if (isIncremental) { |
| appendThis(cgPropertyAssignment); |
| js.append(", "); |
| } |
| js.appendValueName(cgSlot); |
| js.append(", "); |
| appendQualifiedLiteralName(eStructuralFeature); |
| js.append(", "); |
| js.appendValueName(cgInit); |
| js.append(", "); |
| js.appendBooleanString(eStructuralFeature.isMany() && isPartial); |
| js.append(");\n"); |
| } |
| } |
| |
| private void doAssigned(@NonNull CGGuardVariable cgGuardVariable, @NonNull EStructuralFeature eStructuralFeature, CGValuedElement cgInit) { |
| CGValuedElement cgSlot = cgGuardVariable; |
| // CGValuedElement cgInit = getExpression(QVTiCGUtil.getOwnedInitValue(cgPropertyAssignment)); |
| // if (isIncremental || ((SetStatement)cgGuardVariable.getAst()).isIsNotify()) { |
| js.append(qvtiGlobalContext.getObjectManagerName()); |
| js.append(".assigned("); |
| if (isIncremental) { |
| appendThis(cgGuardVariable); |
| js.append(", "); |
| } |
| js.appendValueName(cgSlot); |
| js.append(", "); |
| appendQualifiedLiteralName(eStructuralFeature); |
| js.append(", "); |
| js.appendValueName(cgInit); |
| js.append(", false);\n"); |
| // } |
| } |
| |
| protected void doConstructor(@NonNull CGTransformation cgTransformation, @Nullable String oppositeName, @Nullable List<@Nullable AllInstancesAnalysis> allInstancesAnalyses) { |
| // String evaluatorName = ((QVTiGlobalContext)globalContext).getEvaluatorParameter().getName(); |
| String evaluatorName = qvtiGlobalContext.getExecutorName(); |
| String className = cgTransformation.getName(); |
| String transformationName = qvtiGlobalContext.getTransformationNameResolution().getResolvedName(); |
| Iterable<@NonNull CGTypedModel> cgTypedModels = QVTiCGUtil.getOwnedTypedModels(cgTransformation); |
| // |
| js.append("protected final "); |
| js.appendIsRequired(true); |
| js.append(" "); |
| js.append(className); |
| js.append(" "); |
| js.append(transformationName); |
| js.append(" = this;\n"); |
| js.append("\n"); |
| // |
| js.append("public " + className + "(final "); |
| js.appendClassReference(true, TransformationExecutor.class); |
| js.append(" "); |
| js.append(evaluatorName); |
| js.append(") {\n"); |
| js.pushIndentation(null); |
| js.append("super("); |
| js.append(evaluatorName); |
| js.append(", "); |
| js.appendIntegerString(Iterables.size(cgTypedModels)); |
| js.append(");\n"); |
| if (oppositeName != null) { |
| js.append("initOpposites("); |
| js.append(oppositeName); |
| js.append(");\n"); |
| } |
| int modelNumber = 0; |
| for (@NonNull CGTypedModel cgTypedModel : cgTypedModels) { |
| js.append("initModel("); |
| js.appendIntegerString(modelNumber); |
| js.append(", "); |
| String name = cgTypedModel.getName(); |
| js.appendString(name != null ? name : ""); |
| js.append(")"); |
| if (allInstancesAnalyses != null) { |
| AllInstancesAnalysis allInstancesAnalysis = allInstancesAnalyses.get(modelNumber); |
| if (allInstancesAnalysis != null) { |
| js.append(".initClassIds("); |
| js.append(allInstancesAnalysis.getNames()[0]); |
| js.append(", "); |
| js.append(allInstancesAnalysis.getNames()[1]); |
| js.append(")"); |
| int extentClassIndex = allInstancesAnalysis.getExtentClassIndex(); |
| if (extentClassIndex >= 0) { |
| js.append(".initExtent("); |
| js.appendIntegerString(extentClassIndex); |
| js.append(", "); |
| String extentOppositesName = allInstancesAnalysis.getExtentOppositesName(); |
| js.append(extentOppositesName != null ? extentOppositesName : "null"); |
| js.append(")"); |
| } |
| } |
| } |
| js.append(";\n"); |
| modelNumber++; |
| } |
| js.append("initConnections();\n"); |
| /* ImperativeTransformation transformation = QVTiCGUtil.getAST(cgTransformation); |
| EntryPointsAnalysis entryPointsAnalysis = context.getEntryPointsAnalysis(transformation); |
| for (@NonNull EntryPointAnalysis entryPointAnalysis : entryPointsAnalysis.getEntryPointAnalyses()) { |
| Iterable<@NonNull EAttribute> eAttributes = entryPointAnalysis.getSpeculatedEAttributes(); |
| if ((eAttributes != null) && !Iterables.isEmpty(eAttributes)) { |
| js.append("initSpeculatedEAttributes("); |
| js.appendString(entryPointAnalysis.getEntryPoint().getName()); |
| for (@NonNull EAttribute eAttribute : eAttributes) { |
| js.append(", "); |
| appendQualifiedLiteralName(eAttribute); |
| } |
| js.append(");\n"); |
| } |
| } */ |
| // doMappingConstructorInitializers(cgTransformation); |
| // doFunctionConstructorInitializers(cgTransformation); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| |
| /* protected void doCreateInterval(@NonNull CGTransformation cgTransformation) { |
| js.append("@Override\n"); |
| js.append("protected "); |
| js.appendClassReference(true, Interval.class); |
| js.append(" createInterval(int intervalIndex) {\n"); |
| js.pushIndentation(null); |
| js.append("switch (intervalIndex) {\n"); |
| js.append("}\n"); |
| js.append("return new "); |
| js.appendClassReference(null, DefaultInterval.class); |
| js.append("(invocationManager, intervalIndex);\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| } */ |
| |
| /* protected void doCreateIncrementalManagers() { |
| js.append("@Override\n"); |
| js.append("protected "); |
| js.appendClassReference(true, InvocationManager.class); |
| js.append(" createInvocationManager() {\n"); |
| js.pushIndentation(null); |
| js.append("return new "); |
| js.appendClassReference(null, IncrementalInvocationManager.class); |
| js.append("("); |
| js.append(qvtiGlobalContext.getExecutorName()); |
| js.append(");\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| js.append("\n"); |
| js.append("@Override\n"); |
| js.append("protected "); |
| js.appendClassReference(true, ObjectManager.class); |
| js.append(" createObjectManager() {\n"); |
| js.pushIndentation(null); |
| js.append("return new "); |
| js.appendClassReference(null, IncrementalObjectManager.class); |
| js.append("(("); |
| js.appendClassReference(null, IncrementalInvocationManager.class); |
| js.append(")invocationManager);\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| } */ |
| |
| protected boolean doCreateRealizedVariable(@NonNull CGRealizedVariable cgRealizedVariable) { |
| if (isIncremental) { |
| js.appendClassReference(null, cgRealizedVariable); |
| js.append(" "); |
| js.appendValueName(cgRealizedVariable); |
| js.append(" = this."); |
| js.appendValueName(cgRealizedVariable); |
| js.append(";\n"); |
| js.append("if ("); |
| js.appendValueName(cgRealizedVariable); |
| js.append(" == null) {\n"); |
| js.pushIndentation(null); |
| } |
| boolean flowContinues = cgRealizedVariable.accept(this).booleanValue(); |
| if (flowContinues) { |
| doAddRealization(cgRealizedVariable); |
| // |
| if (isIncremental) { |
| js.append("assert "); |
| js.appendValueName(cgRealizedVariable); |
| js.append(" != null;\n"); |
| js.append("this."); |
| js.appendValueName(cgRealizedVariable); |
| js.append(" = "); |
| js.appendValueName(cgRealizedVariable); |
| js.append(";\n"); |
| } |
| } |
| if (isIncremental) { |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| return flowContinues; |
| } |
| |
| /** |
| * Create a Ecore Class, returning |
| * false if an exception thrown for an abstract class |
| * null |
| * @param cgElement |
| * @param eClass |
| * @return |
| */ |
| protected boolean doEcoreCreateClass(@NonNull CGValuedElement cgElement, @NonNull EClass eClass, boolean setClassNonNull) { |
| if (eClass.isAbstract()) { |
| CGMapping cgMapping = QVTiCGUtil.getContainingCGMapping(cgElement); |
| js.append("throw new "); |
| js.appendClassReference(null, InvalidEvaluationException.class); |
| js.append("(\""); |
| js.append("Cannot create an instance of the abstract EClass "); |
| js.append(LabelUtil.getLabel(eClass)); |
| js.append(" in "); |
| js.append(LabelUtil.getLabel(cgMapping)); |
| js.append("\");\n"); |
| return false; |
| } |
| String createMethodName = "create" + eClass.getName(); |
| boolean canSetNonNull = false; |
| EPackage ePackage = eClass.getEPackage(); |
| 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) { |
| canSetNonNull = true; |
| } |
| } |
| } |
| else { |
| javaClass = genModelHelper.getQualifiedFactoryInterfaceName(ePackage); |
| } |
| } |
| else { |
| javaClass = null; |
| } |
| // |
| CGMapping cgMapping = QVTiCGUtil.basicGetContainingCGMapping(cgElement); |
| if ((cgMapping == null) || !useClass(cgMapping) || !isIncremental) { |
| js.append("final "); |
| if (!canSetNonNull) { |
| js.appendSuppressWarningsNull(false); |
| } |
| js.appendClassReference(true, cgElement); |
| js.append(" "); |
| } |
| js.appendValueName(cgElement); |
| js.append(" = "); |
| boolean hasParts = false; |
| if (cgElement instanceof CGRealizedVariable) { |
| CGRealizedVariable cgRealizedVariable = (CGRealizedVariable)cgElement; |
| NewStatement iNewStatement = QVTiCGUtil.getAST(cgRealizedVariable); |
| List<NewStatementPart> ownedParts = iNewStatement.getOwnedParts(); |
| if (ownedParts.size() > 0) { |
| hasParts = true; |
| assert cgMapping != null; |
| js.append(getNativeInstanceInstanceName(cgRealizedVariable.getExecutorType())); |
| js.append(".evaluate("); |
| boolean isFirst = true; |
| for (@NonNull CGRealizedVariablePart cgPart : cgRealizedVariable.getOwnedParts()) { |
| if (!isFirst) { |
| js.append(", "); |
| } |
| js.appendValueName(cgPart.getInit()); |
| isFirst = false; |
| } |
| js.append(")"); |
| js.append(";\n"); |
| } |
| } |
| if (!hasParts) { |
| js.appendClassReference(null, javaClass); |
| js.append(".eINSTANCE."); |
| js.append(createMethodName); |
| js.append("();\n"); |
| } |
| // js.append("assert "); |
| // js.appendValueName(cgElement); |
| // js.append(" != null;\n"); |
| // |
| if (setClassNonNull) { |
| ((CGVariable)cgElement).setNonNull(); |
| } |
| return true; |
| } |
| |
| protected boolean doEcoreCreateDataType(@NonNull CGValuedElement cgElement, @NonNull EDataType eDataType, @NonNull CGValuedElement cgInit) { |
| // |
| // Availability of a GenPackage is mandatory since we must have an EFactory.createFromString method to do the construction. |
| // |
| final Class<?> javaClass = eDataType.getInstanceClass(); |
| if (javaClass == null) { |
| throw new IllegalStateException("No Java class for " + cgElement + " in QVTiCG2JavaVisitor.doEcoreCreateDataType()"); |
| } |
| final EPackage ePackage = eDataType.getEPackage(); |
| String nsURI = ePackage.getNsURI(); |
| if (nsURI == null) { |
| throw new IllegalStateException("No EPackage NsURI for " + cgElement + " in QVTiCG2JavaVisitor.doEcoreCreateDataType()"); |
| } |
| GenPackage genPackage = environmentFactory.getMetamodelManager().getGenPackage(nsURI); |
| if (genPackage == null) { |
| throw new IllegalStateException("No GenPackage for " + cgElement + " in QVTiCG2JavaVisitor.doEcoreCreateDataType()"); |
| } |
| 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 = classLoader.loadClass(ePackageName); |
| } |
| catch (ClassNotFoundException e) { |
| throw new IllegalStateException("Load class failure for " + cgElement + " in QVTiCG2JavaVisitor.doEcoreCreateDataType()", e); |
| } |
| // |
| |
| |
| |
| String createMethodName = qvtiGlobalContext.getCreateFromStringName().getResolvedName(); |
| boolean doSetNonNull = false; |
| // String javaClass2; |
| // Class<?> factoryClass2 = genModelHelper.getEcoreFactoryClass(ePackage); |
| if (factoryClass != null) { |
| // javaClass2 = factoryClass.getName(); |
| Method factoryMethod = context.getLeastDerivedMethod(factoryClass, createMethodName); |
| if (factoryMethod != null) { |
| if (context.getIsNonNull(factoryMethod) == Boolean.TRUE) { |
| doSetNonNull = true; |
| } |
| } |
| } |
| // else { |
| // javaClass2 = genModelHelper.getQualifiedFactoryInterfaceName(ePackage); |
| // } |
| // |
| js.appendDeclaration(cgElement); |
| js.append(" = "); |
| js.append("("); |
| js.appendClassReference(null, javaClass); |
| js.append(")"); |
| js.appendClassReference(null, factoryClass); |
| js.append(".eINSTANCE."); |
| js.append(createMethodName); |
| js.append("("); |
| js.appendClassReference(null, packageClass); |
| js.append(".Literals." + dataTypeName + ", "); |
| js.appendValueName(cgInit); |
| js.append(");\n"); |
| js.append("assert "); |
| js.appendValueName(cgElement); |
| js.append(" != null;\n"); |
| // |
| return doSetNonNull; |
| } |
| |
| protected boolean doFunctionBody(@NonNull CGFunction cgFunction) { |
| CGValuedElement body = getExpression(cgFunction.getBody()); |
| ElementId elementId = cgFunction.getTypeId().getElementId(); |
| js.append(" {\n"); |
| js.pushIndentation(null); |
| // if (isIncremental) { |
| // js.append("super(\""); |
| // js.append(getFunctionName(cgFunction)); |
| // js.append("\");\n"); |
| // } |
| // 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.appendSuppressWarningsNull(false); |
| js.appendIsRequired(true); |
| js.append(" "); |
| } |
| if (elementId != null) { |
| TypeDescriptor javaTypeDescriptor = context.getUnboxedDescriptor(elementId); |
| js.appendClassReference(null, javaTypeDescriptor); |
| } |
| String emptyListName = qvtiGlobalContext.getEmptyListName(); |
| js.append(" " + emptyListName + " = "); |
| js.appendClassReference(null, Collections.class); |
| js.append("." + emptyListName + "();\n"); |
| js.append("return " + emptyListName + ";\n"); |
| } |
| else { // FIXME Fudge for body-less functions |
| js.append("return \"\";\n"); |
| } |
| } |
| js.popIndentation(); |
| js.append("}\n"); |
| return true; |
| } |
| |
| protected boolean doFunctionBody3(@NonNull CGFunction cgFunction) { |
| String functionName = getFunctionName(cgFunction); |
| String cachedResultName = getCachedResultName(cgFunction); |
| CGValuedElement cgBody = cgFunction.getBody(); |
| ElementId elementId = cgFunction.getTypeId().getElementId(); |
| // FIXME merge locals into AST as LetExps. |
| if (cgBody != null) { |
| CGValuedElement body = getExpression(cgBody); |
| if (!js.appendLocalStatements(body)) { |
| return false; |
| } |
| js.appendThis(functionName); |
| js.append("." + cachedResultName + " = "); |
| js.appendValueName(body); |
| js.append(";\n"); |
| } |
| /* else if (QVTiCGUtil.getAST(cgFunction).getImplementationClass() != null) { -- Java Class has synthesized CGLibraryOperationCallExp |
| final CGTypeId resultType = cgFunction.getTypeId(); |
| Function asFunction = QVTiCGUtil.getAST(cgFunction); |
| TypeDescriptor functionTypeDescriptor = context.getTypeDescriptor(cgFunction).getEcoreDescriptor(context, null); |
| // js.append("/* " + localContext.getIdResolverVariable(cgFunction) + "* /"); |
| |
| functionTypeDescriptor.appendBox(js, localContext, cgFunction, cgFunction); |
| /* js.appendClassReference(null, ValueUtil.class); |
| js.append(".createSetValue("); |
| js.appendValueName(resultType); |
| js.append(", "); * / |
| js.append(asFunction.getImplementationClass()); |
| js.append(".INSTANCE.evaluate("); |
| js.append(qvtiGlobalContext.getExecutorName()); |
| js.append(", "); |
| js.appendValueName(resultType); |
| for (@NonNull CGParameter cgParameter : QVTiCGUtil.getParameters(cgFunction)) { |
| js.append(", "); |
| js.appendValueName(cgParameter); |
| } |
| js.append(");\n"); |
| js.appendThis(functionName); |
| js.append("." + instanceName + " = "); |
| js.appendValueName(cgFunction); |
| js.append(";\n"); |
| } */ |
| else { |
| TypeId asTypeId = cgFunction.getASTypeId(); |
| if (asTypeId == TypeId.STRING) { // FIXME Fudge for body-less functions |
| js.appendThis(functionName); |
| js.append("." + cachedResultName + " = \"\";\n"); |
| } |
| else if (asTypeId == TypeId.REAL) { // FIXME Fudge for body-less functions |
| js.appendThis(functionName); |
| js.append("." + cachedResultName + " = 0;\n"); |
| } |
| else if (asTypeId == TypeId.INTEGER) { // FIXME Fudge for body-less functions |
| js.appendThis(functionName); |
| js.append("." + cachedResultName + " = 0;\n"); |
| } |
| else if (asTypeId instanceof CollectionTypeId) { // FIXME Fudge for body-less functions |
| if (js.isUseNullAnnotations()) { |
| js.appendSuppressWarningsNull(false); |
| js.appendIsRequired(true); |
| js.append(" "); |
| } |
| if (elementId != null) { |
| TypeDescriptor javaTypeDescriptor = context.getUnboxedDescriptor(elementId); |
| js.appendClassReference(null, javaTypeDescriptor); |
| } |
| String emptyListName = qvtiGlobalContext.getEmptyListName(); |
| js.append(" " + emptyListName + " = "); |
| js.appendClassReference(null, Collections.class); |
| js.append("." + emptyListName + "();\n"); |
| js.appendThis(functionName); |
| js.append("." + cachedResultName + " = " + emptyListName + ";\n"); |
| } |
| else { // FIXME Fudge for body-less functions |
| js.appendThis(functionName); |
| js.append("." + cachedResultName + " = \"\";\n"); |
| } |
| } |
| return true; |
| } |
| |
| protected boolean doFunctionBody2(@NonNull CGFunction cgFunction, @NonNull CGShadowExp cgShadowExp) { |
| Function function = QVTiCGUtil.getAST(cgFunction); |
| ImperativeTransformation transformation = QVTimperativeUtil.getContainingTransformation(function); |
| EntryPointsAnalysis entryPointsAnalysis = context.getEntryPointsAnalysis(transformation); |
| String functionName = getFunctionName(cgFunction); |
| String cachedResultName = getCachedResultName(cgFunction); |
| js.append(" {\n"); |
| js.pushIndentation(null); |
| if (isIncremental) { |
| js.append("super(\""); |
| js.append(functionName); |
| js.append("\");\n"); |
| } |
| EClassifier eClassifier = ClassUtil.nonNullState(cgShadowExp.getEcoreClassifier()); |
| if (eClassifier instanceof EDataType) { |
| CGShadowPart cgShadowPart = ClassUtil.nullFree(cgShadowExp.getParts()).get(0); |
| CGValuedElement cgInit = ClassUtil.nonNullState(cgShadowPart.getInit()); |
| if (!js.appendLocalStatements(cgInit)) { |
| return false; |
| } |
| doEcoreCreateDataType(cgShadowExp, (EDataType)eClassifier, cgInit); |
| } |
| else if (eClassifier instanceof EClass) { |
| if (!doEcoreCreateClass(cgShadowExp, (EClass)eClassifier, false)) { |
| return false; |
| } |
| 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("("); |
| int finalI = index++; |
| SubStream castBody = new SubStream() { |
| @Override |
| public void append() { |
| js.append("boundValues[" + finalI + "]"); |
| } |
| }; |
| js.appendClassCast(cgShadowPart, castBody); |
| js.append(");\n"); |
| } |
| } |
| // |
| js.appendThis(functionName); |
| js.append("."); |
| js.append(cachedResultName); |
| js.append(" = "); |
| js.appendValueName(cgShadowExp); |
| js.append(";\n"); |
| // |
| EPackage ePackage = eClassifier.getEPackage(); |
| TypedModel bestOutputTypedModel = null; |
| TypedModel bestMiddleTypedModel = null; |
| TypedModel bestInputTypedModel = null; |
| for (@NonNull TypedModel typedModel : QVTimperativeUtil.getModelParameters(entryPointsAnalysis.getTransformation())) { |
| TypedModel imperativeTypedModel = null; |
| for (org.eclipse.ocl.pivot.Package usedPackage : typedModel.getUsedPackage()) { |
| if (usedPackage.getESObject() == ePackage) { |
| imperativeTypedModel = typedModel; |
| } |
| } |
| if (imperativeTypedModel != null) { |
| if (QVTimperativeUtil.isOutput(imperativeTypedModel)) { |
| bestOutputTypedModel = imperativeTypedModel; |
| } |
| else if (!QVTimperativeUtil.isInput(imperativeTypedModel)) { |
| bestMiddleTypedModel = imperativeTypedModel; |
| } |
| else { |
| bestInputTypedModel = imperativeTypedModel; |
| } |
| } |
| } |
| TypedModel asTypedModel = null; |
| if (bestOutputTypedModel != null) { |
| asTypedModel = bestOutputTypedModel; |
| } |
| else if (bestMiddleTypedModel != null) { |
| asTypedModel = bestMiddleTypedModel; |
| } |
| else if (bestInputTypedModel != null) { |
| asTypedModel = bestInputTypedModel; |
| } |
| if ((eClassifier instanceof EClass) && (asTypedModel != null)) { // FIXME Why are shadow objects put in a model at all -- testQVTrCompiler_SeqToStm_CG requires it |
| CGTypedModel cgTypedModel = context.getAnalyzer().getTypedModel(asTypedModel); |
| appendModelReference(cgTypedModel); |
| js.append(".add("); |
| js.appendValueName(cgShadowExp); |
| js.append(");\n"); |
| } |
| // |
| js.popIndentation(); |
| js.append("}\n"); |
| return true; |
| } |
| |
| protected void doFunctionConstructor(@NonNull CGFunction cgFunction) { |
| String functionName = getFunctionName(cgFunction); |
| String thisTransformerName = getThisTransformerName(cgFunction); |
| String cachedResultName = getCachedResultName(cgFunction); |
| 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(functionName); |
| js.append("(/*Nullable*/ Object "); |
| js.appendIsRequired(true); |
| js.append(" [] boundValues) {\n"); |
| js.pushIndentation(null); |
| if (isIncremental) { |
| js.append("super(\""); |
| js.append(functionName); |
| js.append("\");\n"); |
| } |
| js.appendThis(functionName); |
| js.append("." + thisTransformerName + " = ("); |
| js.appendClassReference(cgClass); |
| js.append(")boundValues[0];\n"); |
| int i = 1; |
| for (@NonNull CGParameter cgParameter : cgParameters) { |
| String valueName = getResolvedName(cgParameter); |
| js.appendThis(functionName); |
| js.append("."); |
| js.append(valueName); |
| js.append(" = "); |
| int finalI = i++; |
| SubStream castBody = new SubStream() { |
| @Override |
| public void append() { |
| js.append("boundValues[" + finalI + "]"); |
| } |
| }; |
| js.appendClassCast(cgParameter, castBody); |
| js.append(";\n"); |
| } |
| doFunctionBody3(cgFunction); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| |
| protected void doFunctionConstructor(@NonNull CGFunction cgFunction, @NonNull CGShadowExp cgShadowExp) { |
| // 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 = getResolvedName(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); |
| } |
| |
| protected void doFunctionConstructorConstants(/*@NonNull*/ List<@NonNull CGOperation> cgOperations) { |
| for (@NonNull CGOperation cgOperation : cgOperations) { |
| if (cgOperation instanceof CGFunction) { |
| CGFunction cgFunction = (CGFunction)cgOperation; |
| if (useClass(cgFunction) || useCache(cgFunction)) { |
| String functionName = getFunctionName(cgFunction); |
| js.append("protected final "); |
| js.appendClassReference(true, AbstractComputationConstructor.class); |
| js.append(" " + getFunctionCtorName(cgFunction) + " = new "); |
| js.appendClassReference(null, AbstractComputationConstructor.class); |
| js.append("(idResolver)\n"); |
| js.append("{\n"); |
| js.pushIndentation(null); |
| js.append("@Override\n"); |
| js.append("public "); |
| js.appendIsRequired(true); |
| js.append(" " + functionName + " newInstance("); |
| js.appendClassReference(false, Object.class); |
| js.append(" "); |
| js.appendIsRequired(true); |
| js.append(" [] values) {\n"); |
| js.pushIndentation(null); |
| js.append("return new " + functionName + "(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) { |
| String cachedResultName = getCachedResultName(cgFunction); |
| 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 " + cachedResultName + ";\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| |
| protected void doFunctionIsEqual(@NonNull CGFunction cgFunction) { |
| String functionName = getFunctionName(cgFunction); |
| String thisTransformerName = getThisTransformerName(cgFunction); |
| js.append("@Override\n"); |
| js.append("public boolean isEqual("); |
| js.appendClassReference(true, IdResolver.class); |
| js.append(" idResolver, "); |
| js.appendIsRequired(false); |
| js.append(" Object "); |
| js.appendIsRequired(true); |
| js.append(" [] thoseValues) {\n"); |
| js.pushIndentation(null); |
| js.append("return "); |
| js.appendThis(functionName); |
| js.append("." + thisTransformerName + " == thoseValues[0]"); |
| int index = 1; |
| for (@NonNull CGParameter cgParameter : ClassUtil.nullFree(cgFunction.getParameters())) { |
| js.append("\n\t&& "); |
| js.append("idResolver.oclEquals("); // FIXME oclEquals / == |
| js.appendThis(functionName); |
| js.append("."); |
| 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("@Override\n"); |
| js.append("public boolean isEqual("); |
| js.appendClassReference(true, 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\t&& "); |
| } |
| 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.basicGetContainingCGMapping(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) { |
| // |
| js.append(qvtiGlobalContext.getObjectManagerName()); |
| js.append(".getting("); |
| js.appendValueName(source); |
| js.append(", "); |
| appendQualifiedLiteralName(eStructuralFeature); |
| js.append(", "); |
| js.appendBooleanString(isOpposite); |
| js.append(");\n"); |
| } |
| } |
| |
| protected void doGot(@NonNull CGNavigationCallExp cgPropertyCallExp, @NonNull CGValuedElement source, @NonNull EStructuralFeature eStructuralFeature) { |
| if (useGot) { |
| // |
| String objectManagerName = qvtiGlobalContext.getObjectManagerName(); |
| js.append(objectManagerName); |
| js.append(".got("); |
| // if (localPrefix != null) { |
| // js.append(localPrefix); |
| // js.append("."); |
| // } |
| appendThis(cgPropertyCallExp); |
| js.append(", "); |
| js.appendValueName(source); |
| js.append(", "); |
| if (!(cgPropertyCallExp instanceof CGOppositePropertyCallExp)) { |
| appendQualifiedLiteralName(eStructuralFeature); |
| } |
| else { |
| EReference eOpposite = ((EReference)eStructuralFeature).getEOpposite(); |
| if (eOpposite != null) { |
| appendQualifiedLiteralName(eOpposite); |
| } |
| else { |
| js.append(objectManagerName); |
| js.append(".getEOppositeReference("); |
| appendQualifiedLiteralName(eStructuralFeature); |
| js.append(")"); |
| } |
| } |
| js.append(", "); |
| js.appendValueName(cgPropertyCallExp); |
| js.append(");\n"); |
| } |
| } |
| |
| private void doInstanceCaches(@NonNull CGTransformation cgTransformation) { |
| Map<org.eclipse.ocl.pivot.@NonNull Class, @NonNull CachedInstance> cachedInstances = new HashMap<>(); |
| for (@NonNull EObject element : new TreeIterable(cgTransformation, false)) { |
| if (element instanceof CGRealizedVariable) { |
| CGRealizedVariable cgRealizedVariable = (CGRealizedVariable)element; |
| List<CGRealizedVariablePart> ownedParts = cgRealizedVariable.getOwnedParts(); |
| if (ownedParts.size() > 0) { |
| CGExecutorType cgExecutorType = cgRealizedVariable.getExecutorType(); |
| org.eclipse.ocl.pivot.@NonNull Class asClass = (org.eclipse.ocl.pivot.Class) cgExecutorType.getAst(); |
| List<@NonNull CGExecutorProperty> cgProperties = new ArrayList<>(); |
| for (CGRealizedVariablePart ownedPart : ownedParts) { |
| cgProperties.add(ownedPart.getExecutorProperty()); |
| } |
| Collections.sort(cgProperties, NameUtil.NAMEABLE_COMPARATOR); |
| NewStatement iNewStatement = QVTiCGUtil.getAST(cgRealizedVariable); |
| TypedModel asTypedModel = ClassUtil.nonNullState(iNewStatement.getReferredTypedModel()); |
| CGTypedModel cgTypedModel = ClassUtil.nonNullState(analyzer.getTypedModel(asTypedModel)); |
| int modelIndex = cgTypedModel.getModelIndex(); |
| CachedInstance cachedInstance = cachedInstances.get(asClass); |
| if (cachedInstance == null) { |
| cachedInstance = new CachedInstance(asClass, cgExecutorType, cgProperties, modelIndex); |
| cachedInstances.put(asClass, cachedInstance); |
| } |
| else { |
| cachedInstance.check(cgProperties, modelIndex); |
| } |
| } |
| } |
| } |
| List<org.eclipse.ocl.pivot.@NonNull Class> asClasses = new ArrayList<>(cachedInstances.keySet()); |
| Collections.sort(asClasses, NameUtil.NAMEABLE_COMPARATOR); |
| for (org.eclipse.ocl.pivot.@NonNull Class asClass : asClasses) { |
| CachedInstance cachedInstance = cachedInstances.get(asClass); |
| assert cachedInstance != null; |
| cachedInstance.doCachedInstance(); |
| } |
| } |
| |
| protected void doInvocationWrapperPrefix(@NonNull Mapping invocationWrapper) { |
| Integer firstPass = invocationWrapper.getFirstPass(); |
| if (firstPass == null) { |
| js.append("invocationManager.flush();\n"); // Legacy support for auto-allocated pass numbers. |
| } |
| js.append("new "); |
| js.appendClassReference(null, AbstractSimpleInvocation.class); |
| js.append("(lazyCreateInterval("); |
| // js.appendIntegerString(firstPass != null ? firstPass : -1); |
| js.append(Integer.toString(firstPass != null ? firstPass : -1)); |
| js.append("/*.." + invocationWrapper.getLastPass() + "*/"); |
| js.append("), "); |
| js.appendString(PivotUtil.getName(invocationWrapper)); |
| js.append(") {\n"); |
| js.pushIndentation(null); |
| js.append("@Override\n"); |
| js.append("public boolean execute() {\n"); |
| js.pushIndentation(null); |
| } |
| |
| protected void doInvocationWrapperSuffix(@NonNull Mapping invocationWrapper) { |
| js.append("return true;\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| js.popIndentation(); |
| js.append("};\n"); |
| Integer firstPass = invocationWrapper.getFirstPass(); |
| if (firstPass == null) { |
| js.append("invocationManager.flush();\n"); // Legacy support for auto-allocated pass numbers. |
| } |
| } |
| |
| protected void doIsEqual(@NonNull List<@NonNull ? extends CGParameter> cgFreeVariables) { |
| js.append("@Override\n"); |
| js.append("public boolean isEqual("); |
| js.appendClassReference(true, IdResolver.class); |
| js.append(" idResolver, "); |
| js.appendIsRequired(true); |
| js.append(" Object "); |
| js.appendIsRequired(true); |
| js.append(" [] thoseValues) {\n"); |
| js.pushIndentation(null); |
| js.append("return "); |
| if (cgFreeVariables.size() > 0) { |
| int index = 0; |
| for (@NonNull CGParameter cgFreeVariable : cgFreeVariables) { |
| if (index > 0) { |
| js.append("\n\t&& "); |
| } |
| js.append("idResolver.oclEquals("); |
| js.append(getResolvedName(cgFreeVariable)); |
| js.append(", thoseValues[" + index++ + "])"); |
| } |
| } |
| else { |
| js.append("true"); |
| } |
| js.append(";\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| |
| protected void doMappingBody(@NonNull CGMapping cgMapping, @Nullable Iterable<@NonNull CGGuardVariable> cgGuardVariables) { |
| CGValuedElement cgBody = cgMapping.getOwnedBody(); |
| js.append(" {\n"); |
| js.pushIndentation(null); |
| if ((cgGuardVariables != null) && isGeneratedDebug) { |
| js.append("if (debugInvocations) {\n"); |
| js.pushIndentation(null); |
| js.appendClassReference(null, AbstractTransformer.class); |
| js.append(".INVOCATIONS.println(\"invoke " + getMappingName(cgMapping) + "\""); |
| for (@NonNull CGGuardVariable cgGuardVariable : cgGuardVariables) { |
| if (!(cgGuardVariable instanceof CGConnectionVariable)) { |
| js.append(" +\n\t\"\\n\\t"); |
| // js.append(cgGuardVariable.getClass().getSimpleName()); |
| // js.append(", "); |
| js.append("\\\"" + cgGuardVariable.getName() + "\\\":\""); |
| js.append(" + toDebugString("); |
| js.append(getResolvedName(cgGuardVariable)); |
| js.append(")"); |
| Element ast = cgGuardVariable.getAst(); |
| if (ast instanceof TypedElement) { |
| org.eclipse.ocl.pivot.Class type = PivotUtil.getClass((TypedElement)ast); |
| Property trace2dispatcherProperty = NameUtil.getNameable(PivotUtil.getOwnedProperties(type), "dispatcher"); |
| if (trace2dispatcherProperty != null) { |
| js.append(" +\n\t\"\\n\\t"); |
| js.append("\\\"dispatcher\\\":\""); |
| js.append(" + toDebugString("); |
| js.append(getResolvedName(cgGuardVariable)); |
| js.append(".getDispatcher())"); |
| for (Property dispatcherProperty : PivotUtil.getOwnedProperties(PivotUtil.getClass(trace2dispatcherProperty))) { |
| String name = PivotUtil.getName(dispatcherProperty); |
| if ((name.length() >= 2) && (name.charAt(0) == 'd') && Character.isDigit(name.charAt(1))) { |
| js.append(" +\n\t\"\\n\\t"); |
| js.append("\\\"dispatcher." + name + "\\\":\""); |
| js.append(" + toDebugString("); |
| js.append(getResolvedName(cgGuardVariable)); |
| String prefix = dispatcherProperty.getTypeId() == TypeId.BOOLEAN ? "is" : "get"; // FIXME Use GenModel |
| js.append(".getDispatcher()." + prefix + Character.toUpperCase(name.charAt(0)) + name.substring(1) + "())"); |
| |
| } |
| } |
| } |
| } |
| } |
| // } |
| } |
| js.append(");\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| // if (cgBody.isInvalid()) { |
| // js.append("return handleExecutionFailure(\"" + getMappingName(cgMapping) + "\", "); |
| // js.appendValueName(cgBody); |
| // js.append(");\n"); |
| // } |
| // else { |
| // js.append("try {\n"); |
| // js.pushIndentation(null); |
| if (!cgBody.isInlined()) { |
| cgBody.accept(this); |
| } |
| // if (cgGuardVariables != null) { |
| for (@NonNull CGGuardVariable cgGuardVariable : QVTiCGUtil.getOwnedGuardVariables(cgMapping)) { |
| VariableDeclaration asGuardVariable = QVTiCGUtil.getAST(cgGuardVariable); |
| if (asGuardVariable instanceof GuardParameter) { |
| GuardParameter asGuardParameter = (GuardParameter)asGuardVariable; |
| Property successProperty = asGuardParameter.getSuccessProperty(); |
| if (successProperty != null) { |
| EStructuralFeature eStructuralFeature = ClassUtil.nonNullState((EStructuralFeature) successProperty.getESObject()); |
| String setAccessor = genModelHelper.getSetAccessor(eStructuralFeature); |
| // |
| js.appendValueName(cgGuardVariable); |
| js.append("."); |
| js.append(setAccessor); |
| js.append("("); |
| js.appendValueName(cgBody); |
| js.append(");\n"); |
| // js.append("if ("); |
| // js.appendValueName(cgBody); |
| // js.append(") {\n"); |
| // js.pushIndentation(null); |
| doAssigned(cgGuardVariable, eStructuralFeature, cgBody); |
| // js.popIndentation(); |
| // js.append("}\n"); |
| } |
| } |
| } |
| // } |
| if (cgGuardVariables != null) { |
| if (isGeneratedDebug) { |
| js.append("if (debugInvocations) {\n"); |
| js.pushIndentation(null); |
| js.appendClassReference(null, AbstractTransformer.class); |
| js.append(".INVOCATIONS.println(("); |
| js.appendValueName(cgBody); |
| js.append(" ? \"done \" : \"fail \") + \"" + getMappingName(cgMapping) + "\");\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| } |
| js.append("return "); |
| js.appendValueName(cgBody); |
| js.append(";\n"); |
| // 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"); |
| } |
| |
| public @NonNull Boolean doMappingCall_Class(@NonNull CGMappingCall cgMappingCall) { |
| MappingCall pMappingCall = QVTiCGUtil.getAST(cgMappingCall); |
| Mapping pReferredMapping = QVTimperativeUtil.getReferredMapping(pMappingCall); |
| CGMapping cgReferredMapping = analyzer.getMapping(pReferredMapping); |
| assert cgReferredMapping != null; |
| Iterable<@NonNull CGMappingCallBinding> cgMappingCallBindings = QVTiCGUtil.getOwnedMappingCallBindings(cgMappingCall); |
| // |
| // Set loopVariable non-null if it needs to be type-checked and cast to a narrower type. |
| // |
| for (@NonNull CGMappingCallBinding cgMappingCallBinding : cgMappingCallBindings) { |
| CGValuedElement ownedValue = cgMappingCallBinding.getOwnedValue(); |
| TypeDescriptor checkedType = needsTypeCheck(cgMappingCallBinding); |
| if (checkedType != null) { |
| js.append("if ("); |
| js.appendValueName(ownedValue); |
| js.append(" instanceof "); |
| js.appendClassReference(null, checkedType); |
| js.append(") {\n"); |
| js.pushIndentation(null); |
| } |
| else if (!ownedValue.isNonNull()) { |
| Element asMappingParameterBinding = cgMappingCallBinding.getAst(); |
| if (!(asMappingParameterBinding instanceof GuardParameterBinding)) { // FIXME this should be part of isNonNull |
| js.append("if ("); |
| js.appendValueName(ownedValue); |
| js.append(" != null) {\n"); |
| js.pushIndentation(null); |
| } |
| } |
| } |
| // |
| // Emit the mapping call. |
| // |
| Iterable<@NonNull CGMappingCallBinding> iterateBindings = getIterateBindings(cgMappingCallBindings); |
| String mappingCtorName = getMappingCtorName(cgReferredMapping); |
| if (iterateBindings == null) { |
| for (CGMappingCallBinding cgMappingCallBinding : cgMappingCallBindings) { |
| Element ast = cgMappingCallBinding.getAst(); |
| js.append(mappingCtorName); |
| js.append("."); |
| js.append(ast instanceof AppendParameterBinding ? "addAppendedConnection" : "addConsumedConnection"); |
| js.append("("); |
| appendConnectionBinding(cgMappingCallBinding); |
| js.append(");\n"); |
| } |
| } |
| else { |
| js.append(mappingCtorName); |
| js.append(".invoke("); |
| boolean isFirst = true; |
| for (@NonNull CGMappingCallBinding cgMappingCallBinding : cgMappingCallBindings) { |
| if (!isFirst) { |
| js.append(", "); |
| } |
| TypeDescriptor checkedType = needsTypeCheck(cgMappingCallBinding); |
| if (checkedType != null) { |
| js.append("("); |
| js.appendClassReference(null, checkedType); |
| js.append(")"); |
| } |
| js.appendValueName(cgMappingCallBinding.getOwnedValue()); |
| isFirst = false; |
| } |
| js.append(");\n"); |
| } |
| // |
| // End the type check. |
| // |
| for (@NonNull CGMappingCallBinding cgMappingCallBinding : cgMappingCallBindings) { |
| TypeDescriptor checkedType = needsTypeCheck(cgMappingCallBinding); |
| if (checkedType != null) { |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| else if (!cgMappingCallBinding.getOwnedValue().isNonNull()) { |
| Element asMappingParameterBinding = cgMappingCallBinding.getAst(); |
| if (!(asMappingParameterBinding instanceof GuardParameterBinding)) { // FIXME this should be part of isNonNull |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| } |
| } |
| return true; |
| } |
| |
| public @NonNull Boolean doMappingCall_Function(@NonNull CGMappingCall cgMappingCall) { |
| MappingCall pMappingCall = QVTiCGUtil.getAST(cgMappingCall); |
| Mapping pReferredMapping = QVTimperativeUtil.getReferredMapping(pMappingCall); |
| if (invocationWrapper == null) { |
| doInvocationWrapperPrefix(pReferredMapping); |
| } |
| CGMapping cgReferredMapping = analyzer.getMapping(pReferredMapping); |
| assert cgReferredMapping != null; |
| Iterable<@NonNull CGMappingCallBinding> cgMappingCallBindings = QVTiCGUtil.getOwnedMappingCallBindings(cgMappingCall); |
| // |
| // Set loopVariable non-null if it needs to be type-checked and cast to a narrower type. |
| // |
| for (@NonNull CGMappingCallBinding cgMappingCallBinding : cgMappingCallBindings) { |
| MappingParameterBinding asMappingParameterBinding = (MappingParameterBinding)cgMappingCallBinding.getAst(); |
| if (asMappingParameterBinding instanceof AppendParameterBinding) { |
| } |
| else if (asMappingParameterBinding instanceof GuardParameterBinding) { |
| js.append("for ("); |
| js.appendClassReference(Boolean.TRUE, cgMappingCallBinding); |
| js.append(" "); |
| js.appendValueName(cgMappingCallBinding); |
| js.append(" : "); |
| js.appendValueName(cgMappingCallBinding.getOwnedValue()); |
| js.append(".typedIterable("); |
| js.appendClassReference(null, cgMappingCallBinding); |
| js.append(".class)"); |
| js.append(") {\n"); |
| js.pushIndentation(null); |
| // FIXME typeCheck |
| } |
| else { |
| TypeDescriptor checkedType = needsTypeCheck(cgMappingCallBinding); |
| if (checkedType != null) { |
| js.append("if ("); |
| js.appendValueName(cgMappingCallBinding.getOwnedValue()); |
| js.append(" instanceof "); |
| js.appendClassReference(null, checkedType); |
| js.append(") {\n"); |
| js.pushIndentation(null); |
| } |
| else if (!cgMappingCallBinding.getOwnedValue().isNonNull()) { |
| js.append("if ("); |
| js.appendValueName(cgMappingCallBinding.getOwnedValue()); |
| js.append(" != null) {\n"); |
| js.pushIndentation(null); |
| } |
| } |
| } |
| // |
| // Emit the mapping call. |
| // |
| js.append(getMappingName(cgReferredMapping) + "("); |
| boolean isFirst = true; |
| for (@NonNull CGMappingCallBinding cgMappingCallBinding : cgMappingCallBindings) { |
| if (!isFirst) { |
| js.append(", "); |
| } |
| TypeDescriptor checkedType = needsTypeCheck(cgMappingCallBinding); |
| if (checkedType != null) { |
| js.append("("); |
| js.appendClassReference(null, checkedType); |
| js.append(")"); |
| } |
| MappingParameterBinding asMappingParameterBinding = (MappingParameterBinding)cgMappingCallBinding.getAst(); |
| if (asMappingParameterBinding instanceof GuardParameterBinding) { |
| js.appendValueName(cgMappingCallBinding); |
| } |
| else { |
| js.appendValueName(cgMappingCallBinding.getOwnedValue()); |
| } |
| isFirst = false; |
| } |
| js.append(");\n"); |
| // |
| // End the type check. |
| // |
| for (@NonNull CGMappingCallBinding cgMappingCallBinding : cgMappingCallBindings) { |
| MappingParameterBinding asMappingParameterBinding = (MappingParameterBinding)cgMappingCallBinding.getAst(); |
| if (asMappingParameterBinding instanceof AppendParameterBinding) { |
| } |
| else if (asMappingParameterBinding instanceof GuardParameterBinding) { |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| else {TypeDescriptor checkedType = needsTypeCheck(cgMappingCallBinding); |
| if (checkedType != null) { |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| else if (!cgMappingCallBinding.getOwnedValue().isNonNull()) { |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| } |
| } |
| if (invocationWrapper == null) { |
| doInvocationWrapperSuffix(pReferredMapping); |
| } |
| return true; |
| } |
| |
| protected void doMappingConnectionVariable(@NonNull CGGuardVariable cgFreeVariable) { |
| if (cgFreeVariable instanceof CGConnectionVariable) { |
| js.append("final "); |
| js.appendClassReference(true, isIncremental ? Connection.Incremental.class : Connection.class); |
| js.append(" "); |
| js.append(getResolvedName(cgFreeVariable)); |
| } |
| else{ |
| js.getBoxedTypeRepresentation().appendDeclaration(cgFreeVariable); |
| } |
| } |
| |
| protected void doMappingConstructor(@NonNull CGMapping cgMapping) { |
| String constructorName = qvtiGlobalContext.getConstructorName(); |
| Iterable<@NonNull CGGuardVariable> cgGuardVariables = QVTiCGUtil.getOwnedGuardVariables(cgMapping); |
| // if (js.isUseNullAnnotations()) { |
| // js.append("@SuppressWarnings(\"null\")\n"); // Accurate casts are too hard |
| // } |
| js.append("public "); |
| js.append(getMappingName(cgMapping)); |
| js.append("("); |
| js.appendClassReference(true, isIncremental ? InvocationConstructor.Incremental.class : InvocationConstructor.class); |
| js.append(" "); |
| js.append(constructorName); |
| if (isIncremental) { |
| js.append(", int "); |
| js.append(qvtiGlobalContext.getInvocationHashCodeName()); |
| } |
| js.append(", "); |
| js.appendIsRequired(true); |
| js.append(" Object "); |
| js.appendIsRequired(true); |
| js.append(" [] boundValues) {\n"); |
| js.pushIndentation(null); |
| // if (isIncremental) { |
| js.append("super("); |
| js.append(constructorName); |
| if (isIncremental) { |
| js.append(", "); |
| js.append(qvtiGlobalContext.getInvocationHashCodeName()); |
| } |
| js.append(");\n"); |
| // |
| int i = 0; |
| for (@NonNull CGGuardVariable cgGuardVariable : cgGuardVariables) { |
| String valueName = getResolvedName(cgGuardVariable); |
| js.append(valueName); |
| js.append(" = "); |
| // js.appendClassCast(cgFreeVariable); |
| int finalI = i++; |
| SubStream castBody = new SubStream() { |
| @Override |
| public void append() { |
| js.append("boundValues[" + finalI + "]"); |
| } |
| }; |
| if (cgGuardVariable instanceof CGConnectionVariable) { |
| js.append("("); |
| // js.appendClassReference(null, cgFreeVariable); |
| // js.append(".Accumulator)"); // FIXME Embed properly as a nested typeid |
| js.appendClassReference(null, isIncremental ? Connection.Incremental.class : Connection.class); |
| js.append(")"); // FIXME Embed properly as a nested typeid |
| castBody.append(); |
| } |
| else{ |
| js.appendClassCast(cgGuardVariable, castBody); |
| } |
| js.append(";\n"); |
| } |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| |
| protected void doMappingConstructorConstants(/*@NonNull*/ List<@NonNull CGMapping> cgMappings) { |
| for (@NonNull CGMapping cgMapping : cgMappings) { |
| if (useClass(cgMapping)) {// && (isIncremental || (cgMapping.getFreeVariables().size() > 0))) { |
| Mapping asMapping = QVTiCGUtil.getAST(cgMapping); |
| Class<?> constructorClass = isIncremental ? AbstractInvocationConstructor.Incremental.class : AbstractInvocationConstructor.class; |
| js.append("protected final "); |
| js.appendClassReference(true, constructorClass); |
| js.append(" " + getMappingCtorName(cgMapping) + " = new "); |
| js.appendClassReference(null, constructorClass); |
| js.append("(invocationManager, "); |
| js.appendString(QVTiCGUtil.getName(cgMapping)); |
| if (!isIncremental) { |
| js.append(", "); |
| js.appendBooleanString(QVTiCGUtil.getAST(cgMapping).isIsStrict()); |
| } |
| js.append(", lazyCreateInterval("); |
| Integer firstPass = asMapping.getFirstPass(); |
| // js.appendIntegerString(firstPass != null ? firstPass : -1); |
| js.append(Integer.toString(firstPass != null ? firstPass : -1)); |
| js.append("))\n"); |
| js.append("{\n"); |
| js.pushIndentation(null); |
| js.append("@Override\n"); |
| js.append("public "); |
| js.appendIsRequired(true); |
| js.append(" " + getMappingName(cgMapping) + " newInstance("); |
| if (isIncremental) { |
| js.append("int "); |
| js.append(qvtiGlobalContext.getInvocationHashCodeName()); |
| js.append(", "); |
| } |
| js.appendClassReference(true, Object.class); |
| js.append(" "); |
| js.appendIsRequired(true); |
| js.append(" [] values) {\n"); |
| js.pushIndentation(null); |
| js.append("return new " + getMappingName(cgMapping) + "("); |
| js.append("this"); |
| if (isIncremental) { |
| js.append(", "); |
| js.append(qvtiGlobalContext.getInvocationHashCodeName()); |
| } |
| js.append(", "); |
| js.append("values);\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| js.popIndentation(); |
| js.append("};\n\n"); |
| } |
| } |
| } |
| |
| protected void doMappingDestroy(@NonNull CGMapping cgMapping) { |
| js.append("/*\n"); |
| js.append(" * Eliminate all trace of the construction and execution of this invocation.\n"); |
| js.append(" */\n"); |
| js.append("@Override\n"); |
| js.append("public synchronized void destroy() {\n"); |
| js.pushIndentation(null); |
| js.append("/*\n"); |
| js.append(" * Remove this invocation from the invocation cache.\n"); |
| js.append(" * Revoke all object property assignments.\n"); |
| js.append(" * Revoke all consumed input objects.\n"); |
| js.append(" */\n"); |
| js.append("super.destroy();\n"); |
| /* Iterable<@NonNull CGGuardVariable> ownedGuardVariables = QVTiCGUtil.getOwnedGuardVariables(cgMapping); |
| if (!Iterables.isEmpty(ownedGuardVariables)) { |
| boolean firstConsume = true; |
| int i = 0; |
| for (@NonNull CGGuardVariable cgGuardVariable : ownedGuardVariables) { |
| if (!(cgGuardVariable instanceof CGConnectionVariable)) { |
| if (firstConsume) { |
| js.append("/*\n"); |
| js.append(" * Revoke all consumed input objects.\n"); |
| js.append(" * /\n"); |
| js.appendClassReference(List.class, Connection.Incremental.class); |
| js.append(" consumedConnections = "); |
| js.append(QVTiGlobalContext.CONSTRUCTOR_NAME); |
| js.append(".getConsumedConnections();\n"); |
| firstConsume = false; |
| } |
| js.append("consumedConnections.get(" + i++ + ").revokeConsumer("); |
| js.appendValueName(cgGuardVariable); |
| js.append(", this);\n"); |
| } |
| } |
| } */ |
| boolean firstAppend = true; |
| for (@NonNull EObject eObject : new TreeIterable(cgMapping, false)) { |
| if (eObject instanceof CGConnectionAssignment) { |
| if (firstAppend) { |
| js.append("/*\n"); |
| js.append(" * Revoke all appended output objects.\n"); |
| js.append(" */\n"); |
| firstAppend = false; |
| } |
| CGConnectionAssignment cgConnectionAssignment = (CGConnectionAssignment)eObject; |
| js.append("if (this."); |
| js.appendValueName(cgConnectionAssignment); |
| js.append(" != null) {\n"); |
| js.pushIndentation(null); |
| js.append("this."); |
| js.appendValueName(cgConnectionAssignment.getConnectionVariable()); |
| js.append(".revoke("); |
| js.appendValueName(cgConnectionAssignment); |
| js.append(");\n"); |
| js.append("this."); |
| js.appendValueName(cgConnectionAssignment); |
| js.append(" = null;\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| } |
| Iterable<@NonNull CGRealizedVariable> ownedRealizedVariables = QVTiCGUtil.getOwnedRealizedVariables(cgMapping); |
| if (!Iterables.isEmpty(ownedRealizedVariables)) { |
| js.append("/*\n"); |
| js.append(" * Destroy all created objects.\n"); |
| js.append(" */\n"); |
| for (@NonNull CGRealizedVariable cgRealizedVariable : ownedRealizedVariables) { |
| CGTypedModel cgTypedModel = cgRealizedVariable.getTypedModel(); |
| // |
| js.appendClassReference(null, cgRealizedVariable); |
| js.append(" "); |
| js.appendValueName(cgRealizedVariable); |
| js.append(" = this."); |
| js.appendValueName(cgRealizedVariable); |
| js.append(";\n"); |
| js.append("if ("); |
| js.appendValueName(cgRealizedVariable); |
| js.append(" != null) {\n"); |
| js.pushIndentation(null); |
| js.append("(("); |
| js.appendClassReference(null, RuntimeModelsManager.Model.Incremental.class); |
| js.append(")"); |
| appendModelReference(cgTypedModel); |
| js.append(").remove("); |
| js.appendValueName(cgRealizedVariable); |
| js.append(");\n"); |
| js.append(qvtiGlobalContext.getObjectManagerName()); |
| js.append(".destroyed("); |
| js.appendValueName(cgRealizedVariable); |
| js.append(");\n"); |
| js.append("this."); |
| js.appendValueName(cgRealizedVariable); |
| js.append(" = null;\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| } |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| |
| protected boolean doMappingFields(@NonNull CGMapping cgMapping) { |
| boolean needsNewLine = false; |
| for (@NonNull CGGuardVariable cgVariable : ClassUtil.nullFree(cgMapping.getOwnedGuardVariables())) { |
| js.append("protected "); |
| doMappingConnectionVariable(cgVariable); |
| js.append(";\n"); |
| needsNewLine = true; |
| } |
| if (isIncremental) { |
| for (@NonNull CGRealizedVariable cgVariable : QVTiCGUtil.getOwnedRealizedVariables(cgMapping)) { |
| js.append("protected "); |
| js.appendClassReference(false, cgVariable); |
| js.append(" "); |
| js.appendValueName(cgVariable); |
| if (isIncremental) { |
| js.append(" = null"); |
| } |
| js.append(";\n"); |
| needsNewLine = true; |
| } |
| for (@NonNull EObject eObject : new TreeIterable(cgMapping, false)) { |
| if (eObject instanceof CGConnectionAssignment) { |
| CGConnectionAssignment cgConnectionAssignment = (CGConnectionAssignment)eObject; |
| js.append("protected "); |
| js.appendClassReference(false, Object.class); |
| js.append(" "); |
| js.appendValueName(cgConnectionAssignment); |
| js.append(" = null;\n"); |
| needsNewLine = true; |
| } |
| } |
| } |
| return needsNewLine; |
| } |
| |
| protected void doMappingGetBoundValue(@NonNull CGMapping cgMapping) { |
| Iterable<@NonNull CGGuardVariable> cgGuardVariables = QVTiCGUtil.getOwnedGuardVariables(cgMapping); |
| js.append("/*\n"); |
| js.append(" * Return the index'th bound value.\n"); |
| js.append(" */\n"); |
| js.append("@Override\n"); |
| js.append("public "); |
| js.appendClassReference(true, Object.class); |
| js.append(" getBoundValue(int index) {\n"); |
| js.pushIndentation(null); |
| js.append("switch(index) {\n"); |
| js.pushIndentation(null); |
| int i = 0; |
| for (@NonNull CGGuardVariable cgGuardVariable : cgGuardVariables) { |
| String valueName = getResolvedName(cgGuardVariable); |
| js.append("case " + i++ + ": return "); |
| js.append(valueName); |
| js.append(";\n"); |
| } |
| js.popIndentation(); |
| js.append("}\n"); |
| js.append("throw new "); |
| js.appendClassReference(null, IllegalArgumentException.class); |
| js.append("();\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| |
| protected void doMappingGetBoundValues(@NonNull CGMapping cgMapping) { |
| Iterable<@NonNull CGGuardVariable> cgGuardVariables = QVTiCGUtil.getOwnedGuardVariables(cgMapping); |
| js.append("/*\n"); |
| js.append(" * Return the number of bound values.\n"); |
| js.append(" */\n"); |
| js.append("@Override\n"); |
| js.append("public int getBoundValues() {\n"); |
| js.pushIndentation(null); |
| js.append("return " + Iterables.size(cgGuardVariables) + ";\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| |
| protected void doMappingSuccess(@NonNull CGMappingExp cgMappingExp) { |
| // CGMapping cgMapping = QVTiCGUtil.getContainingCGMapping(cgMappingExp); |
| // CGValuedElement cgBody = cgMapping.getOwnedBody(); |
| // CGGuardVariable cgTraceParameter = QVTiCGUtil.getTraceParameter(cgMapping); |
| // if (cgTraceParameter == null) { |
| js.appendDeclaration(cgMappingExp); |
| js.append(" = "); |
| js.appendClassReference(null, ValueUtil.class); |
| js.append(".TRUE_VALUE;\n"); |
| // } |
| // else { |
| // js.appendDeclaration(cgMappingExp); |
| // js.append(" = "); |
| // // js.appendValueName(cgBody); |
| // // js.append(" && "); |
| // js.appendName(qvtiGlobalContext.getObjectManagerName()); |
| // js.append(".addSpeculation("); |
| // js.appendValueName(cgTraceParameter); |
| // for (@NonNull CGGuardVariable cgGuardVariable : QVTiCGUtil.getOwnedGuardVariables(cgMapping)) { |
| // js.append(", "); |
| // js.appendValueName(cgGuardVariable); |
| // } |
| // js.append(");\n"); |
| /* js.append("if ("); |
| js.appendValueName(cgMappingExp); |
| js.append(") {\n"); |
| js.pushIndentation(null); |
| if (isGeneratedDebug) { |
| js.append("if (debugInvocations) {\n"); |
| js.pushIndentation(null); |
| js.appendClassReference(null, AbstractTransformer.class); |
| js.append(".INVOCATIONS.println(\"done " + getMappingName(cgMapping) + "\");\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| js.popIndentation(); |
| js.append("}\n"); |
| js.append("else {\n"); |
| js.pushIndentation(null); |
| if (isGeneratedDebug) { |
| js.append("if (debugInvocations) {\n"); |
| js.pushIndentation(null); |
| js.appendClassReference(null, AbstractTransformer.class); |
| js.append(".INVOCATIONS.println(\"speculating " + getMappingName(cgMapping) + "\");\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| js.popIndentation(); |
| js.append("}\n"); */ |
| /* js.append("if (debugInvocations) {\n"); |
| js.pushIndentation(null); |
| js.appendClassReference(null, AbstractTransformer.class); |
| js.append(".INVOCATIONS.println(("); |
| js.appendValueName(cgMappingExp); |
| js.append(" ? \"done \" : \"speculating \") + \"" + getMappingName(cgMapping) + "\");\n"); |
| js.popIndentation(); |
| js.append("}\n"); */ |
| // } |
| } |
| |
| protected void doOppositeCaches(@NonNull EntryPointsAnalysis entryPointsAnalysis) { |
| Map<@NonNull Property, @NonNull Integer> opposites = entryPointsAnalysis.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<>(); |
| for (Map.Entry<@NonNull Property, @NonNull Integer> entry : opposites.entrySet()) { |
| Property property = entry.getKey(); |
| String name = qvtiGlobalContext.addOppositeProperty(property); |
| |
| key2property.put(name, property); |
| } |
| List<String> sortedKeys = new ArrayList<>(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(PivotUtil.getElementalType(PivotUtil.getType(property)).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, new @NonNull TypeDescriptor[] {}); |
| js.append("();\n"); |
| } |
| } |
| |
| protected @Nullable String doOppositePropertyIds(@NonNull EntryPointsAnalysis entryPointsAnalysis) { |
| // 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<@NonNull Property, @NonNull Integer> opposites = entryPointsAnalysis.getCaches(); |
| if (opposites.size() <= 0) { |
| return null; |
| } |
| Property dummyProperty = opposites.keySet().iterator().next(); |
| List<@NonNull Property> sortedList = new ArrayList<>(); |
| for (int i = 0; i < opposites.size();i++) { |
| sortedList.add(dummyProperty); |
| } |
| for (Map.Entry<@NonNull Property, @NonNull 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 = qvtiGlobalContext.getOppositeIndex2propertyIdName(); |
| js.append("private static final "); |
| js.appendClassReference(true, PropertyId.class); |
| js.append(" "); |
| js.appendIsRequired(true); |
| js.append(" [] "); |
| js.append(oppositeIndex2propertyIdName); |
| js.append(" = new "); |
| js.appendClassReference(true, PropertyId.class); |
| js.append("[]{\n"); |
| js.pushIndentation(null); |
| for (int i = 0; i < sortedList.size(); i++) { |
| Property property = sortedList.get(i); |
| CGElementId cgPropertyId = analyzer.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, @Nullable List<@Nullable AllInstancesAnalysis> allInstancesAnalyses) { |
| CompleteModelInternal completeModel = environmentFactory.getCompleteModel(); |
| Map<@NonNull TypedModel, @NonNull CGTypedModel> asTypedModel2cgTypedModel = new HashMap<>(); |
| ImperativeTransformation asTransformation = QVTiCGUtil.getAST(cgTransformation); |
| List<@NonNull TypedModel> asTypedModels = QVTimperativeUtil.Internal.getModelParameterList(asTransformation); |
| for (@NonNull CGTypedModel cgTypedModel : QVTiCGUtil.getOwnedTypedModels(cgTransformation)) { |
| TypedModel asTypedModel = QVTiCGUtil.getAST(cgTypedModel); |
| asTypedModel2cgTypedModel.put(asTypedModel, cgTypedModel); |
| } |
| List<@NonNull CGMapping> cgRootMappings = new ArrayList<>(); |
| // CGMapping cgRootMapping = NameUtil.getNameable(cgTransformation.getOwnedMappings(), QVTscheduleConstants.ROOT_MAPPING_NAME); // Obsolete relic |
| for (@NonNull CGMapping cgMapping : QVTiCGUtil.getOwnedMappings(cgTransformation)) { |
| Mapping asMapping = QVTiCGUtil.getAST(cgMapping); |
| if (asMapping instanceof EntryPoint) { |
| cgRootMappings.add(cgMapping); |
| } |
| } |
| Collections.sort(cgRootMappings, new Comparator<@NonNull CGMapping>() { |
| |
| @Override |
| public int compare(@NonNull CGMapping o1, @NonNull CGMapping o2) { |
| EntryPoint asEntryPoint1 = (EntryPoint) QVTiCGUtil.getAST(o1); |
| EntryPoint asEntryPoint2 = (EntryPoint) QVTiCGUtil.getAST(o2); |
| List<TypedModel> asOutputTypedModels1 = asEntryPoint1.getOutputTypedModels(); |
| List<TypedModel> asOutputTypedModels2 = asEntryPoint2.getOutputTypedModels(); |
| TypedModel asTypedModel1 = asOutputTypedModels1.size() > 0 ? asOutputTypedModels1.get(0) : null; |
| TypedModel asTypedModel2 = asOutputTypedModels2.size() > 0 ? asOutputTypedModels2.get(0) : null; |
| int index1 = asTypedModels.indexOf(asTypedModel1); |
| int index2 = asTypedModels.indexOf(asTypedModel2); |
| return index1 - index2; |
| }}); |
| boolean isMultiDirectional = cgRootMappings.size() > 1; |
| js.append("@Override\n"); |
| js.append("public boolean run("); |
| js.appendClassReference(true, String.class); |
| js.append(" targetName"); |
| js.append(") {\n"); |
| js.pushIndentation(null); |
| if (!isMultiDirectional) { |
| js.append("return run();\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| js.append("\n"); |
| js.append("@Override\n"); |
| js.append("public boolean run() {\n"); |
| js.pushIndentation(null); |
| } |
| if (isMultiDirectional) { |
| js.append("switch (targetName) {\n"); |
| js.pushIndentation(null); |
| } |
| for (@NonNull CGMapping cgRootMapping : cgRootMappings) { |
| EntryPoint asEntryPoint = (EntryPoint) QVTiCGUtil.getAST(cgRootMapping); |
| if (isMultiDirectional) { |
| List<TypedModel> asOutputTypedModels = asEntryPoint.getOutputTypedModels(); |
| if (asOutputTypedModels.size() > 0) { |
| js.append("case \""); |
| js.append(asEntryPoint.getTargetName()); |
| js.append("\": {\n"); |
| js.pushIndentation(null); |
| } |
| else { |
| continue; // Avoid generating code for not-enforceable TypedModel |
| } |
| } |
| ImperativeTransformation transformation = QVTiCGUtil.getAST(cgTransformation); |
| EntryPointsAnalysis entryPointsAnalysis = context.getEntryPointsAnalysis(transformation); |
| EntryPointAnalysis entryPointAnalysis = entryPointsAnalysis.getEntryPointAnalysis(asEntryPoint); |
| Iterable<@NonNull EAttribute> eAttributes = entryPointAnalysis.getSpeculatedEAttributes(); |
| if ((eAttributes != null) && !Iterables.isEmpty(eAttributes)) { |
| js.append("initSpeculatedEAttributes("); |
| boolean isFirst = true; |
| for (@NonNull EAttribute eAttribute : eAttributes) { |
| if (!isFirst) { |
| js.append(",\n\t\t\t\t\t\t"); |
| } |
| else { |
| isFirst = false; |
| } |
| appendQualifiedLiteralName(eAttribute); |
| } |
| js.append(");\n"); |
| } |
| for (@NonNull CGGuardVariable cgGuardVariable : QVTiCGUtil.getOwnedGuardVariables(cgRootMapping)) { |
| // js.appendDeclaration(cgGuardVariable); |
| js.append("final "); |
| js.appendClassReference(true, Connection.class); |
| js.append(" "); |
| js.appendValueName(cgGuardVariable); |
| js.append(" = "); |
| js.append(qvtiGlobalContext.getModelsName()); |
| js.append("["); |
| VariableDeclaration asGuardVariable = QVTiCGUtil.getAST(cgGuardVariable); |
| Type type = QVTimperativeUtil.getType(asGuardVariable); |
| org.eclipse.ocl.pivot.Package asPackage = PivotUtil.getContainingPackage(type); |
| assert asPackage != null; |
| AllInstancesAnalysis allInstancesAnalysis = null; |
| CGTypedModel cgTypedModel = null; |
| for (@NonNull TypedModel asTypedModel : QVTimperativeUtil.getInputTypedModels(asEntryPoint)) { |
| if (asTypedModel.getUsedPackage().contains(asPackage)) { |
| assert cgTypedModel == null; |
| cgTypedModel = asTypedModel2cgTypedModel.get(asTypedModel); |
| assert cgTypedModel != null; |
| } |
| } |
| if (cgTypedModel != null) { |
| appendModelIndex(cgTypedModel); |
| assert allInstancesAnalyses != null; |
| allInstancesAnalysis = allInstancesAnalyses.get(cgTypedModel.getModelIndex()); |
| } |
| js.append("].getConnection("); |
| assert allInstancesAnalysis != null; |
| CompleteClass completeType = completeModel.getCompleteClass(type); |
| Integer classIndex = allInstancesAnalysis.getInstancesCompleteClass2index().get(completeType); |
| js.append(classIndex + "/*" + type + "*/"); |
| js.append(");\n"); |
| } |
| if (isIncremental || useClass(cgRootMapping)) { |
| js.append(getMappingCtorName(cgRootMapping) + ".invoke("); |
| } |
| else { |
| js.append("return "); |
| js.append(getMappingName(cgRootMapping)); |
| js.append("("); |
| } |
| boolean isFirst = true; |
| for (@NonNull CGGuardVariable cgGuardVariable : QVTiCGUtil.getOwnedGuardVariables(cgRootMapping)) { |
| if (!isFirst) { |
| js.append(", "); |
| } |
| js.appendValueName(cgGuardVariable); |
| isFirst = false; |
| } |
| js.append(")"); |
| if (isIncremental || useClass(cgRootMapping)) { |
| js.append(";\n"); |
| js.append("return invocationManager.flush();\n"); |
| } |
| else { |
| js.append(" && invocationManager.flush();\n"); |
| } |
| if (isMultiDirectional) { |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| } |
| if (isMultiDirectional) { |
| js.append("default: {\n"); |
| js.pushIndentation(null); |
| js.append("throwInvalidEvaluationException(\"Unsupported target name \'\'{0}\'\'\", targetName);\n"); |
| js.append("return false;\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| |
| protected void doTransformationExecution(@NonNull CGTransformation cgTransformation) { |
| ImperativeTransformation iTransformation = QVTiCGUtil.getAST(cgTransformation); |
| Type contextType = iTransformation.getContextType(); |
| if (contextType != null) { |
| EClass eClass = (EClass) contextType.getESObject(); |
| if (eClass != null) { // QVTc / manual QVTi has no trace EClass |
| String createMethodName = "create" + eClass.getName(); |
| EPackage ePackage = eClass.getEPackage(); |
| assert ePackage != null; |
| String javaFactory = genModelHelper.getQualifiedFactoryInterfaceName(ePackage); |
| String javaClass = genModelHelper.getEcoreInterfaceClassifierName(eClass); |
| js.append("private "); |
| js.appendClassReference(false, javaClass); |
| String transformationExecutionName = qvtiGlobalContext.getTransformationExecutionName(); |
| js.append(" " + transformationExecutionName + " = null;\n"); |
| js.append("\n"); |
| js.append("public "); |
| js.appendClassReference(true, javaClass); |
| js.append(" " + qvtiGlobalContext.getGetTransformationExecutionName() + "() {\n"); |
| js.pushIndentation(null); |
| js.append("if (" + transformationExecutionName + " == null) {\n"); |
| js.pushIndentation(null); |
| js.append(transformationExecutionName + " = "); |
| js.appendClassReference(null, javaFactory); |
| js.append(".eINSTANCE."); |
| js.append(createMethodName); |
| js.append("();\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| js.append("return " + transformationExecutionName + ";\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| js.append("\n"); |
| } |
| } |
| } |
| |
| protected @NonNull Class<? extends Transformer> getAbstractTransformationExecutorClass() { |
| return isIncremental ? AbstractTransformer.Incremental.class : AbstractTransformer.class; |
| } |
| |
| @Override |
| public @NonNull QVTiAnalyzer getAnalyzer() { |
| return (QVTiAnalyzer) super.getAnalyzer(); |
| } |
| |
| protected @NonNull String getCachedResultName(@NonNull CGFunction cgFunction) { |
| return cgFunction.getVariantResolvedName(getCodeGenerator().getCACHED_RESULT_NameVariant()); |
| } |
| |
| 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; |
| } |
| |
| @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 = environmentFactory.getMetamodelManager(); |
| LibraryProperty libraryProperty = metamodelManager.getImplementation(null, null, asProperty); |
| if (!(libraryProperty instanceof OclElementOclContainerProperty)) { |
| return null; |
| } |
| } |
| return OCLstdlibPackage.Literals.OCL_ELEMENT__OCL_CONTAINER; |
| } |
| |
| protected @NonNull 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; |
| } |
| |
| private @Nullable Mapping getInvocationWrapper(@NonNull CGValuedElement cgValue) { |
| Mapping mapping = null; |
| if (cgValue instanceof CGSequence) { |
| for (@NonNull CGValuedElement cgStatement : QVTiCGUtil.getOwnedStatements((CGSequence) cgValue)) { |
| mapping = getInvocationWrapper(cgStatement); |
| if (mapping != null) { |
| return mapping; |
| } |
| } |
| } |
| else if (cgValue instanceof CGMappingLoop) { |
| return getInvocationWrapper(QVTiCGUtil.getBody((CGMappingLoop)cgValue)); |
| } |
| else if (cgValue instanceof CGLetExp) { |
| return getInvocationWrapper(QVTiCGUtil.getIn((CGLetExp)cgValue)); |
| } |
| else if (cgValue instanceof CGMappingCall) { |
| MappingCall pMappingCall = QVTiCGUtil.getAST((CGMappingCall)cgValue); |
| Mapping pReferredMapping = QVTimperativeUtil.getReferredMapping(pMappingCall); |
| CGMapping cgReferredMapping = analyzer.getMapping(pReferredMapping); |
| assert cgReferredMapping != null; |
| if (!useClass(cgReferredMapping)) { |
| return pReferredMapping; |
| } |
| } |
| return null; |
| } |
| |
| private @Nullable Iterable<@NonNull CGMappingCallBinding> getIterateBindings(@NonNull Iterable<@NonNull CGMappingCallBinding> cgMappingCallBindings) { |
| List<@NonNull CGMappingCallBinding> bindings = null; |
| for (@NonNull CGMappingCallBinding cgMappingCallBinding : cgMappingCallBindings) { |
| Element ast = cgMappingCallBinding.getAst(); |
| if (ast instanceof LoopParameterBinding) { |
| if (bindings == null) { |
| bindings = new ArrayList<>(); |
| } |
| bindings.add(cgMappingCallBinding); |
| } |
| } |
| return bindings; |
| } |
| |
| protected @NonNull 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 @NonNull String getNativeInstanceClassName(@NonNull CGExecutorType cgType) { |
| Element ast = cgType.getAst(); |
| return JavaStream.convertToJavaIdentifier("ICACHE_" + ((NamedElement)ast).getName()); |
| } |
| |
| protected @NonNull String getNativeInstanceInstanceName(@NonNull CGExecutorType cgType) { |
| return "INSTANCE_" + getNativeInstanceClassName(cgType); |
| } |
| |
| @Override |
| protected @NonNull String getResolvedName(@NonNull CGValuedElement cgElement) { |
| if (cgElement instanceof CGVariableExp) { |
| CGVariable cgVariable = ((CGVariableExp)cgElement).getReferredVariable(); |
| if (cgVariable != null) { |
| Element asVariable = cgVariable.getAst(); |
| if (asVariable instanceof Parameter) { |
| EObject asContainer = asVariable.eContainer(); |
| if (asContainer instanceof TypedModel) { |
| Transformation asTransformation = ((TypedModel)asContainer).getTransformation(); |
| if (asTransformation != null) { |
| int index = asTransformation.getModelParameter().indexOf(asContainer); |
| String name = qvtiGlobalContext.getModelsName() + "[" + index + "/*" + ((TypedModel)asContainer).getName() + "*/]"; |
| return name; |
| } |
| } |
| } |
| } |
| } |
| return super.getResolvedName(cgElement); |
| } |
| |
| /* @Deprecated |
| protected @NonNull String getThisName(@NonNull CGElement cgElement) { |
| for (EObject eObject = cgElement; eObject != null; eObject = eObject.eContainer()) { |
| if (eObject instanceof CGMapping) { |
| return getMappingName((CGMapping)eObject); // + ".this" |
| } |
| if (eObject instanceof CGFunction) { |
| return getFunctionName((CGFunction)eObject); // + ".this" |
| } |
| if (eObject instanceof CGClass) { |
| return ClassUtil.nonNullState(((CGClass)eObject).getName()); // + ".this" |
| } |
| } |
| assert false; |
| return ""; // "this" * / |
| } */ |
| |
| protected @NonNull String getThisTransformerName(@NonNull CGFunction cgFunction) { |
| return cgFunction.getVariantResolvedName(getCodeGenerator().getTHIS_TRANSFORMER_NameVariant()); |
| } |
| |
| private boolean isConnection(CGValuedElement source) { |
| return (source.getAst() instanceof VariableExp) && (((VariableExp)source.getAst()).getReferredVariable() instanceof ConnectionVariable); |
| } |
| |
| 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); |
| if (observedProperties.contains(navigatedProperty)) { |
| return true; |
| } |
| Property navigatedOppositeProperty = navigatedProperty.getOpposite(); |
| if (observedProperties.contains(navigatedOppositeProperty)) { |
| return true; |
| } |
| break; |
| } |
| } |
| return false; |
| } |
| |
| 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.getOwnedValue(); |
| 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 useClassToCreateObject(@NonNull CGFunction cgFunction) { |
| CGValuedElement cgBody = cgFunction.getBody(); |
| while (cgBody instanceof CGLetExp) { |
| cgBody = ((CGLetExp)cgBody).getIn(); |
| } |
| if (cgBody instanceof CGShadowExp) { // QVTr Key |
| if (!(((TypedElement)cgBody.getAst()).getType() instanceof DataType)) |
| return (CGShadowExp)cgBody; // FIXME replace with clearer strategy |
| } |
| return null; |
| } |
| |
| protected boolean useClass(@NonNull CGFunction cgFunction) { |
| return true; |
| } |
| |
| protected boolean useClass(@NonNull CGMapping cgMapping) { |
| if (alwaysUseClasses) { |
| return true; |
| } |
| if (isIncremental) { |
| return true; |
| } |
| if (cgMapping.isUseClass()) { |
| return true; |
| } |
| return false; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGConnectionAssignment(@NonNull CGConnectionAssignment cgConnectionAssignment) { |
| CGValuedElement initValue = QVTiCGUtil.getOwnedInitValue(cgConnectionAssignment); |
| if (!js.appendLocalStatements(initValue)) { |
| return false; |
| } |
| final String iteratorName = getVariantResolvedName(cgConnectionAssignment, context.getITER_NameVariant()); |
| TypeId concreteElementTypeId = cgConnectionAssignment.getConnectionVariable().getASTypeId(); |
| assert concreteElementTypeId != null; |
| BoxedDescriptor concreteBoxedDescriptor = context.getBoxedDescriptor(concreteElementTypeId); |
| BoxedDescriptor abstractBoxedDescriptor = concreteBoxedDescriptor; |
| if (!(initValue.getASTypeId() instanceof CollectionTypeId)) { |
| if (isIncremental) { |
| js.appendValueName(cgConnectionAssignment); |
| js.append(" = "); |
| } |
| js.appendReferenceTo(cgConnectionAssignment.getConnectionVariable()); |
| js.append(".appendElement("); |
| 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(null, ValueUtil.class); |
| js.append(".typedIterable("); |
| js.appendClassReference(null, 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(null, 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 = QVTiCGUtil.getEStructuralFeature(cgPropertyAssignment); |
| CGValuedElement cgSlot = getExpression(QVTiCGUtil.getOwnedSlotValue(cgPropertyAssignment)); |
| CGValuedElement cgInit = getExpression(QVTiCGUtil.getOwnedInitValue(cgPropertyAssignment)); |
| // 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); |
| SetStatement asSetStatement = QVTiCGUtil.getAST(cgPropertyAssignment); |
| EStructuralFeature eStructuralFeature = QVTiCGUtil.getEStructuralFeature(cgPropertyAssignment); |
| CGValuedElement cgSlot = getExpression(QVTiCGUtil.getOwnedSlotValue(cgPropertyAssignment)); |
| CGValuedElement cgInit = getExpression(QVTiCGUtil.getOwnedInitValue(cgPropertyAssignment)); |
| // 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; |
| } |
| boolean isPartial = asSetStatement.isIsPartial(); |
| appendEcoreSet(cgSlot, eStructuralFeature, cgInit, isPartial); |
| doAssigned(cgPropertyAssignment, isPartial); |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGEcorePropertyCallExp(@NonNull CGEcorePropertyCallExp cgPropertyCallExp) { |
| CGValuedElement cgSource = getExpression(cgPropertyCallExp.getSource()); |
| if (!js.appendLocalStatements(cgSource)) { |
| return false; |
| } |
| ElementId sourceTypeId = cgSource.getTypeId().getElementId(); |
| ImperativeTransformation iTransformation = getAnalyzer().getCodeGenerator().getTransformation(); |
| org.eclipse.ocl.pivot.Class runtimeContextClass = QVTimperativeUtil.getRuntimeContextClass(iTransformation); |
| TypeId runtimeContextTypeId = runtimeContextClass.getTypeId(); |
| if (sourceTypeId == runtimeContextTypeId) { // FIXME make transformationInstance regular - cloned from appendCGEcorePropertyCallExp |
| Property asProperty = ClassUtil.nonNullState(cgPropertyCallExp.getReferredProperty()); |
| EStructuralFeature eStructuralFeature = ClassUtil.nonNullState(getESObject(asProperty)); |
| String getAccessor = genModelHelper.getGetAccessor(eStructuralFeature); |
| js.appendDeclaration(cgPropertyCallExp); |
| js.append(" = " + qvtiGlobalContext.getGetTransformationExecutionName() + "()."); |
| js.append(getAccessor); |
| js.append("();\n"); |
| return true; |
| } |
| EStructuralFeature eStructuralFeature = QVTiCGUtil.getEStructuralFeature(cgPropertyCallExp); |
| doGetting(cgPropertyCallExp, eStructuralFeature, false); |
| Boolean status = appendCGEcorePropertyCallExp(cgPropertyCallExp, cgSource); |
| if (status != ValueUtil.TRUE_VALUE) { |
| return status; |
| } |
| doGot(cgPropertyCallExp, cgSource, eStructuralFeature); |
| return status; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGEcoreRealizedVariable(@NonNull CGEcoreRealizedVariable cgRealizedVariable) { |
| EClassifier eClassifier = ClassUtil.nonNullState(cgRealizedVariable.getEClassifier()); |
| return doEcoreCreateClass(cgRealizedVariable, (EClass)eClassifier, true); |
| } |
| |
| @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 = useClassToCreateObject(cgFunction); |
| String functionName = getFunctionName(cgFunction); |
| String cachedResultName = getCachedResultName(cgFunction); |
| if (cgShadowExp != null) { |
| js.append("protected class "); |
| js.append(functionName); |
| js.append(" extends "); |
| js.appendClassReference(null, isIncremental ? AbstractComputation.Incremental.class : AbstractComputation.class); |
| js.pushClassBody(functionName); |
| js.append("protected final "); |
| js.appendTypeDeclaration(cgFunction); |
| js.append(" " + cachedResultName + ";\n"); |
| js.append("\n"); |
| doFunctionConstructor(cgFunction, cgShadowExp); |
| js.append("\n"); |
| doFunctionGetInstance(cgFunction); |
| js.append("\n"); |
| doFunctionIsEqual(cgShadowExp, cachedResultName); |
| js.popClassBody(false); |
| } |
| else if (useCache(cgFunction)) { |
| String thisTransformerName = getThisTransformerName(cgFunction); |
| CGClass cgClass = ClassUtil.nonNullState(CGUtil.getContainingClass(cgFunction)); |
| js.append("protected class "); |
| js.append(functionName); |
| js.append(" extends "); |
| js.appendClassReference(null, isIncremental ? AbstractComputation.Incremental.class : AbstractComputation.class); |
| js.pushClassBody(functionName); |
| js.append("protected final "); |
| js.appendIsRequired(true); |
| js.append(" "); |
| js.appendClassReference(cgClass); |
| js.append(" " + thisTransformerName + ";\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(" " + cachedResultName + ";\n"); |
| js.append("\n"); |
| doFunctionConstructor(cgFunction); |
| js.append("\n"); |
| doFunctionGetInstance(cgFunction); |
| js.append("\n"); |
| doFunctionIsEqual(cgFunction); |
| js.popClassBody(false); |
| } |
| 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(null, 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()); |
| boolean useClass = useClass(cgFunction); |
| boolean useClassToCreateObject = useClassToCreateObject(cgFunction) != null; |
| boolean useCache = useCache(cgFunction); |
| boolean isIdentifiedInstance = useClass || 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 && !useClassToCreateObject) { |
| CGClass cgClass = ClassUtil.nonNullState(cgFunction.getContainingClass()); |
| // js.appendClassReference(cgClass); |
| // js.append(".this"); |
| appendThis(cgClass); |
| 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(")"); |
| String cachedResultName = getCachedResultName(cgFunction); |
| js.append("."); |
| js.append(cachedResultName); |
| } |
| 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.getOwnedGuardVariables()); |
| // |
| js.appendCommentWithOCL(null, cgMapping.getAst()); |
| String mappingName = getMappingName(cgMapping); |
| if (useClass(cgMapping) /*&& (cgFreeVariables.size() > 0)*/) { |
| js.append("protected class "); |
| js.append(mappingName); |
| js.append(" extends "); |
| js.appendClassReference(null, isIncremental ? AbstractInvocation.Incremental.class : AbstractInvocation.class); |
| js.pushClassBody(mappingName); |
| boolean needsNewLine = doMappingFields(cgMapping); |
| if (needsNewLine) { |
| js.append("\n"); |
| } |
| doMappingConstructor(cgMapping); |
| if (isIncremental) { |
| js.append("\n"); |
| doMappingDestroy(cgMapping); |
| } |
| js.append("\n"); |
| js.append("@Override\n"); |
| js.append("public boolean execute() "); |
| doMappingBody(cgMapping, null); |
| if (isIncremental) { |
| js.append("\n"); |
| doMappingGetBoundValue(cgMapping); |
| js.append("\n"); |
| doMappingGetBoundValues(cgMapping); |
| } |
| js.append("\n"); |
| doIsEqual(cgFreeVariables); |
| js.popClassBody(false); |
| } |
| else { |
| js.append("protected boolean " + mappingName + "("); |
| boolean isFirst = true; |
| for (@NonNull CGGuardVariable cgFreeVariable : cgFreeVariables) { |
| if (!isFirst) { |
| js.append(", "); |
| } |
| doMappingConnectionVariable(cgFreeVariable); |
| isFirst = false; |
| } |
| js.append(") "); |
| |
| doMappingBody(cgMapping, cgFreeVariables); |
| } |
| } |
| finally { |
| localContext = null; |
| } |
| } |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGMappingCall(@NonNull CGMappingCall cgMappingCall) { |
| MappingCall pMappingCall = QVTiCGUtil.getAST(cgMappingCall); |
| Mapping pReferredMapping = QVTimperativeUtil.getReferredMapping(pMappingCall); |
| CGMapping cgReferredMapping = analyzer.getMapping(pReferredMapping); |
| if (cgReferredMapping == null) { |
| return true; |
| } |
| List<CGMappingCallBinding> cgMappingCallBindings = cgMappingCall.getOwnedMappingCallBindings(); |
| for (@SuppressWarnings("null")@NonNull CGMappingCallBinding cgMappingCallBinding : cgMappingCallBindings) { |
| CGValuedElement value = cgMappingCallBinding.getOwnedValue(); |
| if (value != null) { |
| if (!js.appendLocalStatements(value)) { |
| return false; |
| } |
| } |
| } |
| if (useClass(cgReferredMapping)) { |
| return doMappingCall_Class(cgMappingCall); |
| } |
| else { |
| return doMappingCall_Function(cgMappingCall); |
| } |
| } |
| |
| @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 |
| CGMapping cgMapping = QVTiCGUtil.getContainingCGMapping(cgMappingExp); |
| Iterable<@NonNull CGAccumulator> cgAccumulators = QVTiCGUtil.getOwnedAccumulators(cgMappingExp); |
| if (!Iterables.isEmpty(cgAccumulators)) { |
| js.append("// interval variables\n"); |
| String modeFactoryName = "modeFactory"; |
| String rootIntervalName = "rootInterval"; |
| js.append("final "); |
| js.appendClassReference(true, ModeFactory.class); |
| js.append(" " + modeFactoryName + " = getModeFactory();\n"); |
| js.append("final "); |
| js.appendClassReference(true, Interval.class); |
| js.append(" " + rootIntervalName + " = lazyCreateInterval(0);\n"); |
| js.append("// connection variables\n"); |
| for (@NonNull CGAccumulator cgAccumulator : cgAccumulators) { |
| Element ast = cgAccumulator.getAst(); |
| js.append("final "); |
| // js.appendClassReference(true, isIncremental ? Connection.Incremental.class : Connection.class); |
| js.appendClassReference(true, Connection.class); |
| js.append(" "); |
| js.appendValueName(cgAccumulator); |
| js.append(" = "); |
| if ((ast instanceof BufferStatement) && (((BufferStatement)ast).getFirstPass() != null)) { |
| js.append("lazyCreateInterval("); |
| js.appendIntegerString(((BufferStatement)ast).getFirstPass()); |
| js.append(")"); |
| } |
| else { |
| js.append(rootIntervalName); |
| } |
| js.append(".createConnection("); |
| js.appendString(QVTiCGUtil.getName(cgAccumulator)); |
| js.append(", "); |
| js.appendValueName(cgAccumulator.getTypeId()); |
| js.append(", "); |
| js.appendBooleanString((ast instanceof BufferStatement) && ((BufferStatement)ast).isIsStrict()); |
| js.append(", "); |
| js.append(modeFactoryName); |
| js.append(");\n"); |
| /* |
| if ((ast instanceof ConnectionVariable) && (((ConnectionVariable)ast).getType() instanceof SetType)) { |
| js.append("createUnenforcedSetAccumulatorValue("); |
| } |
| else { |
| js.append("("); |
| js.appendClassReference(null, cgAccumulator); |
| js.append(".Accumulator)"); |
| js.appendClassReference(null, 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 = getVariantResolvedName(cgMappingExp, context.getITER_NameVariant()); |
| 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(null, ValueUtil.class); |
| js.append(".typedIterable("); |
| js.appendClassReference(null, boxedDescriptor); |
| js.append(".class, "); |
| js.appendValueName(cgInit); |
| js.append(")"); |
| // js.appendReferenceTo(cgAccumulator.getInit()); |
| js.append(") {\n"); |
| js.pushIndentation(null); |
| js.appendReferenceTo(cgAccumulator); |
| js.append(".appendElement("); |
| js.append(iteratorName); |
| js.append(");\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| } |
| } |
| Iterable<@NonNull CGRealizedVariable> cgRealizedVariables = QVTiCGUtil.getOwnedRealizedVariables(cgMapping); |
| if (!Iterables.isEmpty(cgRealizedVariables)) { |
| js.append("// creations\n"); |
| for (@NonNull CGRealizedVariable cgRealizedVariable : cgRealizedVariables) { |
| if (!doCreateRealizedVariable(cgRealizedVariable)) { |
| return false; |
| } |
| } |
| } |
| Iterable<@NonNull CGPropertyAssignment> cgPropertyAssignments = QVTiCGUtil.getOwnedAssignments(cgMapping); |
| if (!Iterables.isEmpty(cgPropertyAssignments)) { |
| js.append("// property assignments\n"); |
| for (@NonNull CGPropertyAssignment cgAssignment : cgPropertyAssignments) { |
| if (!cgAssignment.accept(this)) { |
| return false; |
| } |
| } |
| } |
| Iterable<@NonNull CGConnectionAssignment> cgConnectionAssignments = QVTiCGUtil.getOwnedConnectionAssignments(cgMapping); |
| if (!Iterables.isEmpty(cgConnectionAssignments)) { |
| js.append("// connection assignments\n"); |
| for (@NonNull CGConnectionAssignment cgConnectionAssignment : cgConnectionAssignments) { |
| if (!cgConnectionAssignment.accept(this)) { |
| return false; |
| } |
| } |
| } |
| CGValuedElement body = cgMappingExp.getOwnedBody(); |
| if (body != null) { |
| js.append("// mapping statements\n"); |
| if (!body.accept(this)) { |
| return false; |
| } |
| } |
| doMappingSuccess(cgMappingExp); |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGMappingLoop(@NonNull CGMappingLoop cgMappingLoop) { |
| CGValuedElement source = getExpression(cgMappingLoop.getSource()); |
| CGIterator iterator = cgMappingLoop.getIterators().get(0); |
| CGValuedElement body = QVTiCGUtil.getBody(cgMappingLoop); |
| if (!js.appendLocalStatements(source)) { |
| return false; |
| } |
| Mapping thisInvocationWrapper = null; |
| if (invocationWrapper == null) { |
| invocationWrapper = thisInvocationWrapper = getInvocationWrapper(body); |
| if (thisInvocationWrapper != null) { |
| doInvocationWrapperPrefix(thisInvocationWrapper); |
| } |
| } |
| js.append("for ("); |
| js.appendClassReference(Boolean.TRUE, iterator); |
| js.append(" "); |
| js.appendValueName(iterator); |
| js.append(" : "); |
| if (isConnection(source)) { |
| js.appendValueName(source); |
| js.append(".typedIterable("); |
| js.appendClassReference(null, iterator); |
| js.append(".class)"); |
| } |
| else if (source.isBoxed()) { |
| js.appendClassReference(null, 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); |
| } |
| body.accept(this); |
| if (!iterator.isNonNull()) { |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| js.popIndentation(); |
| js.append("}\n"); |
| boolean needsFlush = false; |
| for (EObject eObject : new TreeIterable(body, false)) { |
| if (eObject instanceof CGMappingCall) { |
| CGMappingCall cgMappingCall = (CGMappingCall)eObject; |
| MappingCall asMappingCall = QVTiCGUtil.getAST(cgMappingCall); |
| Mapping pReferredMapping = QVTimperativeUtil.getReferredMapping(asMappingCall); |
| CGMapping cgReferredMapping = analyzer.getMapping(pReferredMapping); |
| if ((cgReferredMapping != null) && useClass(cgReferredMapping)) { |
| needsFlush = true; |
| break; |
| } |
| } |
| } |
| if (thisInvocationWrapper != null) { |
| doInvocationWrapperSuffix(thisInvocationWrapper); |
| invocationWrapper = null; |
| } |
| if (needsFlush) { |
| js.append("//invocationManager.flush();\n"); |
| } |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGMiddlePropertyAssignment(@NonNull CGMiddlePropertyAssignment cgMiddlePropertyAssignment) { |
| Property pReferredProperty = QVTiCGUtil.getReferredProperty(cgMiddlePropertyAssignment); |
| assert !pReferredProperty.isIsImplicit(); |
| CGValuedElement slotValue = QVTiCGUtil.getOwnedSlotValue(cgMiddlePropertyAssignment); |
| CGValuedElement initValue = QVTiCGUtil.getOwnedInitValue(cgMiddlePropertyAssignment); |
| Map<@NonNull Property, @NonNull String> oppositeProperties = qvtiGlobalContext.getOppositeProperties(); |
| if (oppositeProperties != null) { |
| String cacheName = oppositeProperties.get(pReferredProperty); |
| if (cacheName != null) { |
| TypeDescriptor outerTypeDescriptor = context.getBoxedDescriptor(pReferredProperty.getOwningClass().getTypeId()); |
| TypeDescriptor middleTypeDescriptor = context.getBoxedDescriptor(PivotUtil.getElementalType(PivotUtil.getType(pReferredProperty)).getTypeId()); |
| js.append(cacheName); |
| js.append(".put("); |
| js.appendReferenceTo(middleTypeDescriptor, initValue); |
| js.append(", "); |
| js.appendReferenceTo(outerTypeDescriptor, 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 = qvtiGlobalContext.getOppositeProperties(); |
| if (oppositeProperties != null) { |
| boolean isRequired = cgPropertyCallExp.isRequired(); |
| String cacheName = oppositeProperties.get(asProperty); |
| if (cacheName != null) { |
| SubStream castBody = new SubStream() { |
| @Override |
| public void append() { |
| if (isRequired) { |
| js.appendClassReference(null, ClassUtil.class); |
| js.append(".nonNullState ("); |
| } |
| js.append(cacheName); |
| js.append(".get("); |
| js.appendValueName(source); |
| js.append(")"); |
| if (isRequired) { |
| js.append(")"); |
| } |
| } |
| }; |
| if (asOppositeProperty.isIsMany()) { |
| js.appendClassCast(cgPropertyCallExp, castBody); |
| } |
| else { |
| castBody.append(); |
| } |
| } |
| js.append(";\n"); |
| } |
| doGot(cgPropertyCallExp, source, eStructuralFeature); |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGPropertyAssignment(@NonNull CGPropertyAssignment cgPropertyAssignment) { |
| CGExecutorProperty cgExecutorProperty = cgPropertyAssignment.getExecutorProperty(); |
| CGValuedElement slotValue = QVTiCGUtil.getOwnedSlotValue(cgPropertyAssignment); |
| CGValuedElement initValue = QVTiCGUtil.getOwnedInitValue(cgPropertyAssignment); |
| 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) { |
| CGMapping cgMapping = QVTiCGUtil.getOwningMapping(cgRealizedVariable); |
| if (useClass(cgMapping)) { |
| js.appendValueName(cgRealizedVariable); |
| } |
| else { |
| js.appendDeclaration(cgRealizedVariable); |
| } |
| js.append(" = "); |
| js.appendReferenceTo(cgRealizedVariable.getExecutorType()); |
| js.append(".createInstance();\n"); |
| } |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGRealizedVariablePart(@NonNull CGRealizedVariablePart cgRealizedVariablePart) { |
| CGValuedElement init = getExpression(cgRealizedVariablePart.getInit()); |
| if (!js.appendLocalStatements(init)) { |
| return false; |
| } |
| // |
| js.append(".initValue("); |
| js.appendValueName(cgRealizedVariablePart.getOwningRealizedVariable()); |
| js.append(", "); |
| js.appendValueName(init); |
| js.append(");\n"); |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGSequence(@NonNull CGSequence cgSequence) { |
| for (@NonNull CGValuedElement cgStatement : ClassUtil.nullFree(cgSequence.getOwnedStatements())) { |
| cgStatement.accept(this); |
| } |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGSpeculateExp(@NonNull CGSpeculateExp cgSpeculateExp) { |
| CGMapping cgMapping = QVTiCGUtil.getContainingCGMapping(cgSpeculateExp); |
| for (@NonNull CGGuardVariable cgGuardVariable : QVTiCGUtil.getOwnedGuardVariables(cgMapping)) { |
| VariableDeclaration asGuardVariable = QVTiCGUtil.getAST(cgGuardVariable); |
| if (asGuardVariable instanceof GuardParameter) { |
| GuardParameter asGuardParameter = (GuardParameter)asGuardVariable; |
| Property successProperty = asGuardParameter.getSuccessProperty(); |
| if (successProperty != null) { |
| String getSpeculationSlotStateName = qvtiGlobalContext.getGetSpeculationSlotStateName(); |
| String inputSpeculationSlotStateName = qvtiGlobalContext.getInputSpeculationSlotStateName(); |
| String inputSpeculationSlotStatusName = qvtiGlobalContext.getInputSpeculationSlotStatusName(); |
| String needsSpeculationName = qvtiGlobalContext.getNeedsSpeculationName(); |
| String outputSpeculationSlotStateName = qvtiGlobalContext.getOutputSpeculationSlotStateName(); |
| String outputSpeculationSlotStatusName = qvtiGlobalContext.getOutputSpeculationSlotStatusName(); |
| EStructuralFeature eStructuralFeature = ClassUtil.nonNullState((EStructuralFeature) successProperty.getESObject()); |
| String setAccessor = genModelHelper.getSetAccessor(eStructuralFeature); |
| // |
| js.appendClassReference(true, SlotState.Speculating.class); |
| js.append(" " + outputSpeculationSlotStateName + " = "); |
| js.append(qvtiGlobalContext.getObjectManagerName()); |
| js.append("."); |
| js.append(getSpeculationSlotStateName); |
| js.append("("); |
| js.appendValueName(cgGuardVariable); |
| js.append(", "); |
| appendQualifiedLiteralName(eStructuralFeature); |
| js.append(");\n"); |
| // |
| js.appendClassReference(null, Boolean.class); |
| js.append(" " + outputSpeculationSlotStatusName + " = " + outputSpeculationSlotStateName + "." + qvtiGlobalContext.getGetSpeculationStatusName() + "();\n"); |
| // |
| js.append("if (" + outputSpeculationSlotStatusName + " != "); |
| js.appendClassReference(null, ValueUtil.class); |
| js.append(".TRUE_VALUE) {\n"); |
| js.pushIndentation(null); |
| js.append("if (" + outputSpeculationSlotStatusName + " == "); |
| js.appendClassReference(null, ValueUtil.class); |
| js.append(".FALSE_VALUE) {\n"); |
| js.pushIndentation(null); |
| js.appendValueName(cgGuardVariable); |
| js.append("."); |
| js.append(setAccessor); |
| js.append("("); |
| js.appendClassReference(null, ValueUtil.class); |
| js.append(".FALSE_VALUE);\n"); |
| // doAssigned(cgGuardVariable, eStructuralFeature, outputSpeculatingSlotStatus); |
| js.append("return "); |
| js.appendClassReference(null, ValueUtil.class); |
| js.append(".FALSE_VALUE;\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| // |
| js.appendClassReference(true, SlotState.Speculating.class); |
| js.append(" " + inputSpeculationSlotStateName + ";\n"); |
| js.appendClassReference(null, Boolean.class); |
| js.append(" " + inputSpeculationSlotStatusName + ";\n"); |
| js.append("boolean " + needsSpeculationName + " = false;\n"); |
| for (CGSpeculatePart cgSpeculatePart : cgSpeculateExp.getParts()) { |
| // if (cgInput instanceof CGEcorePropertyCallExp) {cgInput; |
| CGValuedElement cgInputObject = cgSpeculatePart.getObjectExp(); |
| // boolean isRequired = cgInputObject.isRequired(); |
| boolean isNonNull = cgInputObject.isNonNull(); |
| if (isNonNull) { |
| js.append("if ("); |
| js.appendValueName(cgInputObject); |
| js.append(" == null) {\n"); |
| js.pushIndentation(null); |
| js.append("throw new "); |
| js.appendClassReference(null, InvalidEvaluationException.class); |
| js.append("("); |
| js.appendString("Null " + cgInputObject/*.getMessage()*/ + " speculation source"); |
| js.append(");\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| else { |
| js.append("if ("); |
| js.appendValueName(cgInputObject); |
| js.append(" != null) {\n"); |
| js.pushIndentation(null); |
| } |
| EStructuralFeature inputAttribute = cgSpeculatePart.getEStructuralFeature(); |
| String inputSetAccessor = genModelHelper.getSetAccessor(eStructuralFeature); |
| // |
| js.append(inputSpeculationSlotStateName); |
| js.append(" = "); |
| js.append(qvtiGlobalContext.getObjectManagerName()); |
| js.append("."); |
| js.append(getSpeculationSlotStateName); |
| js.append("("); |
| js.appendValueName(cgInputObject); |
| js.append(", "); |
| appendQualifiedLiteralName(inputAttribute); |
| js.append(");\n"); |
| js.append(inputSpeculationSlotStatusName); |
| js.append(" = "); |
| js.append(inputSpeculationSlotStateName); |
| js.append("."); |
| js.append(qvtiGlobalContext.getGetSpeculationStatusName()); |
| js.append("();\n"); |
| // |
| js.append("if (" + inputSpeculationSlotStatusName + " != "); |
| js.appendClassReference(null, ValueUtil.class); |
| js.append(".TRUE_VALUE) {\n"); |
| js.pushIndentation(null); |
| js.append("if (" + inputSpeculationSlotStatusName + " == "); |
| js.appendClassReference(null, ValueUtil.class); |
| js.append(".FALSE_VALUE) {\n"); |
| js.pushIndentation(null); |
| js.appendValueName(cgInputObject); |
| js.append("."); |
| js.append(inputSetAccessor); |
| js.append("("); |
| js.appendClassReference(null, ValueUtil.class); |
| js.append(".FALSE_VALUE);\n"); |
| // doAssigned(cgInputObject, inputAttribute, outputSpeculatingSlotStatus); |
| js.append("return "); |
| js.appendClassReference(null, ValueUtil.class); |
| js.append(".FALSE_VALUE;\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| |
| js.append("if (" + outputSpeculationSlotStateName + " != " + inputSpeculationSlotStateName + ") {\n"); |
| js.pushIndentation(null); |
| js.append(outputSpeculationSlotStateName + ".addInput(" + inputSpeculationSlotStateName + ");\n"); |
| js.append(needsSpeculationName + " = true;\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| // |
| js.popIndentation(); |
| js.append("}\n"); |
| // |
| if (!isNonNull) { |
| js.popIndentation(); |
| js.append("}\n"); |
| } |
| // if (Telement2element != null) { |
| // SlotState.Speculating inputSpeculatingSlotState = objectManager.getSpeculatingSlotState(Telement2element, trace_Forward2ReversePackage.Literals.TELEMENT2ELEMENT__S0GLOBAL, outputSpeculatingSlotState); |
| // if (inputSpeculatingSlotState != outputSpeculatingSlotState) { // Bypass the depends-on-self unit cycle |
| // needsSpeculation = true; |
| // } |
| // } |
| } |
| js.append("if (" + needsSpeculationName + ") {\n"); |
| js.pushIndentation(null); |
| js.append("throw new "); |
| js.appendClassReference(null, InvocationFailedException.class); |
| js.append("(" + outputSpeculationSlotStateName + ", true);\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| js.popIndentation(); |
| js.append("}\n"); |
| break; // Only one trace |
| } |
| } |
| } |
| |
| js.append("boolean "); |
| js.appendValueName(cgSpeculateExp); |
| js.append(" = true;\n"); |
| |
| CGValuedElement cgSpeculated = cgSpeculateExp.getSpeculated(); |
| if (cgSpeculated != null) { |
| if (!js.appendLocalStatements(cgSpeculated)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGSpeculatePart(@NonNull CGSpeculatePart object) { |
| // TODO Auto-generated method stub |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGTransformation(@NonNull CGTransformation cgTransformation) { |
| js.appendClassHeader(cgTransformation.getContainingPackage()); |
| ImperativeTransformation transformation = QVTiCGUtil.getAST(cgTransformation); |
| EntryPointsAnalysis entryPointsAnalysis = context.getEntryPointsAnalysis(transformation); |
| // this.entryPointsAnalysis = entryPointsAnalysis; |
| String className = cgTransformation.getName(); |
| assert className != null; |
| 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 addRootEObjects(String,List)}\n"); |
| js.append(" * <br>\n"); |
| js.append(" * {@link run()}\n"); |
| js.append(" * <br>\n"); |
| js.append(" * Extract each output model with {@link getRootEObjects(String)}\n"); |
| js.append(" */\n"); |
| // js.append("@SuppressWarnings({\"nls\",\"unused\"})\n"); |
| js.append("@SuppressWarnings(\"unused\")\n"); |
| js.append("public class " + className + " extends "); |
| js.appendClassReference(null, getAbstractTransformationExecutorClass()); |
| js.pushClassBody(className); |
| if (sortedGlobals != null) { |
| for (CGValuedElement cgElement : sortedGlobals) { |
| assert cgElement.isGlobal(); |
| cgElement.accept(this); |
| } |
| } |
| doOppositeCaches(entryPointsAnalysis); |
| js.append("\n"); |
| String oppositeIndex2propertyIdName = doOppositePropertyIds(entryPointsAnalysis); |
| if (oppositeIndex2propertyIdName != null) { |
| js.append("\n"); |
| } |
| List<@NonNull CGMapping> cgMappings = ClassUtil.nullFree(cgTransformation.getOwnedMappings()); |
| List<CGOperation> cgOperations = cgTransformation.getOperations(); |
| doMappingConstructorConstants(cgMappings); |
| doFunctionConstructorConstants(ClassUtil.nullFree(cgOperations)); |
| doInstanceCaches(cgTransformation); |
| js.append("\n"); |
| List<@Nullable AllInstancesAnalysis> allInstancesAnalyses = doAllInstances(entryPointsAnalysis); |
| js.append("\n"); |
| doConstructor(cgTransformation, oppositeIndex2propertyIdName, allInstancesAnalyses); |
| js.append("\n"); |
| /* if (isIncremental) { |
| doCreateIncrementalManagers(); |
| js.append("\n"); |
| } */ |
| /* doCreateInterval(cgTransformation); |
| js.append("\n"); */ |
| doTransformationExecution(cgTransformation); |
| doRun(cgTransformation, allInstancesAnalyses); |
| // break; |
| // } |
| for (@NonNull CGOperation cgOperation : ClassUtil.nullFree(cgOperations)) { |
| if (!(cgOperation instanceof CGCachedOperation)) { |
| js.append("\n"); |
| cgOperation.accept(this); |
| } |
| } |
| for (@NonNull CGOperation cgOperation : ClassUtil.nullFree(cgOperations)) { |
| if ((cgOperation instanceof CGCachedOperation) && (((CGCachedOperation)cgOperation).getFinalOperations().size() <= 0)) { |
| js.append("\n"); |
| cgOperation.accept(this); |
| } |
| } |
| for (@NonNull CGOperation cgOperation : ClassUtil.nullFree(cgOperations)) { |
| if ((cgOperation instanceof CGCachedOperation) && (((CGCachedOperation)cgOperation).getFinalOperations().size() > 0)) { |
| js.append("\n"); |
| cgOperation.accept(this); |
| } |
| } |
| for (@NonNull CGMapping cgMapping : ClassUtil.nullFree(cgTransformation.getOwnedMappings())) { |
| js.append("\n"); |
| cgMapping.accept(this); |
| } |
| js.popClassBody(false); |
| assert js.peekClassNameStack() == null; |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean visitCGTypedModel(@NonNull CGTypedModel object) { |
| return true; |
| } |
| } |