diff options
author | Ed Willink | 2016-11-05 20:21:50 +0000 |
---|---|---|
committer | Ed Willink | 2016-12-20 21:48:27 +0000 |
commit | 6ca7fee8ffebac38ad7e67a6e20afc6e53e59225 (patch) | |
tree | e55b12d8b826723a90d035d20be6def843ed181f | |
parent | 4ba6beeb41b6e650cdae972ffce067719fd40632 (diff) | |
download | org.eclipse.qvtd-6ca7fee8ffebac38ad7e67a6e20afc6e53e59225.tar.gz org.eclipse.qvtd-6ca7fee8ffebac38ad7e67a6e20afc6e53e59225.tar.xz org.eclipse.qvtd-6ca7fee8ffebac38ad7e67a6e20afc6e53e59225.zip |
[500962] Test a working incremental execution of a property change
26 files changed, 1079 insertions, 780 deletions
diff --git a/plugins/org.eclipse.qvtd.codegen/src/org/eclipse/qvtd/codegen/qvti/java/QVTiCG2JavaVisitor.java b/plugins/org.eclipse.qvtd.codegen/src/org/eclipse/qvtd/codegen/qvti/java/QVTiCG2JavaVisitor.java index cf9d6028e..fc769dff3 100644 --- a/plugins/org.eclipse.qvtd.codegen/src/org/eclipse/qvtd/codegen/qvti/java/QVTiCG2JavaVisitor.java +++ b/plugins/org.eclipse.qvtd.codegen/src/org/eclipse/qvtd/codegen/qvti/java/QVTiCG2JavaVisitor.java @@ -131,6 +131,7 @@ 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.AbstractTransformerInternal.Model; import com.google.common.collect.Iterables; @@ -139,6 +140,49 @@ import com.google.common.collect.Iterables; */ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerator> implements QVTiCGModelVisitor<@NonNull Boolean> { + protected static class AllInstancesAnalysis + { + protected final @NonNull Set<org.eclipse.ocl.pivot.@NonNull Class> allInstancesClasses; + protected final @NonNull Map<org.eclipse.ocl.pivot.@NonNull Class, @Nullable List<org.eclipse.ocl.pivot.@NonNull Class>> instancesClassAnalysis; + protected final @NonNull Map<org.eclipse.ocl.pivot.@NonNull Class, @NonNull Integer> instancesClass2index; + protected final @NonNull List<org.eclipse.ocl.pivot.@NonNull Class> sortedList; + private @NonNull String @Nullable [] names = null; + + public AllInstancesAnalysis(@NonNull QVTiTransformationAnalysis transformationAnalysis, @NonNull Set<org.eclipse.ocl.pivot.@NonNull Class> allInstancesClasses) { + this.allInstancesClasses = allInstancesClasses; + this.instancesClassAnalysis = transformationAnalysis.getInstancesClassAnalysis(allInstancesClasses); + // + // Populate a mapping from instancesClass to linear index. + // + this.instancesClass2index = new HashMap<>(instancesClassAnalysis.size()); + this.sortedList = new ArrayList<>(instancesClassAnalysis.keySet()); + Collections.sort(sortedList, NameUtil.NameableComparator.INSTANCE); + for (int i = 0; i < sortedList.size(); i++) { + instancesClass2index.put(sortedList.get(i), i); + } + } + + protected @NonNull Map<org.eclipse.ocl.pivot.@NonNull Class, @NonNull Integer> getInstancesClass2index() { + return instancesClass2index; + } + + protected @NonNull Map<org.eclipse.ocl.pivot.@NonNull Class, @Nullable List<org.eclipse.ocl.pivot.@NonNull Class>> getInstancesClassAnalysis() { + return instancesClassAnalysis; + } + + protected @NonNull String @NonNull [] getNames() { + return ClassUtil.nonNullState(names); + } + + protected @NonNull List<org.eclipse.ocl.pivot.@NonNull Class> getSortedList() { + return sortedList; + } + + public void setNames(@NonNull String[] names) { + this.names = names; + } + } + /** * The run-time API version. * @@ -226,49 +270,6 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato } } - protected static class AllInstancesAnalysis - { - protected final @NonNull Set<org.eclipse.ocl.pivot.@NonNull Class> allInstancesClasses; - protected final @NonNull Map<org.eclipse.ocl.pivot.@NonNull Class, @Nullable List<org.eclipse.ocl.pivot.@NonNull Class>> instancesClassAnalysis; - protected final @NonNull Map<org.eclipse.ocl.pivot.@NonNull Class, @NonNull Integer> instancesClass2index; - protected final @NonNull List<org.eclipse.ocl.pivot.@NonNull Class> sortedList; - private @NonNull String @Nullable [] names = null; - - public AllInstancesAnalysis(@NonNull QVTiTransformationAnalysis transformationAnalysis, @NonNull Set<org.eclipse.ocl.pivot.@NonNull Class> allInstancesClasses) { - this.allInstancesClasses = allInstancesClasses; - this.instancesClassAnalysis = transformationAnalysis.getInstancesClassAnalysis(allInstancesClasses); - // - // Populate a mapping from instancesClass to linear index. - // - this.instancesClass2index = new HashMap<>(instancesClassAnalysis.size()); - this.sortedList = new ArrayList<>(instancesClassAnalysis.keySet()); - Collections.sort(sortedList, NameUtil.NameableComparator.INSTANCE); - for (int i = 0; i < sortedList.size(); i++) { - instancesClass2index.put(sortedList.get(i), i); - } - } - - protected @NonNull Map<org.eclipse.ocl.pivot.@NonNull Class, @NonNull Integer> getInstancesClass2index() { - return instancesClass2index; - } - - protected @NonNull Map<org.eclipse.ocl.pivot.@NonNull Class, @Nullable List<org.eclipse.ocl.pivot.@NonNull Class>> getInstancesClassAnalysis() { - return instancesClassAnalysis; - } - - protected @NonNull String @NonNull [] getNames() { - return ClassUtil.nonNullState(names); - } - - protected @NonNull List<org.eclipse.ocl.pivot.@NonNull Class> getSortedList() { - return sortedList; - } - - public void setNames(@NonNull String[] names) { - this.names = names; - } - } - protected @Nullable AllInstancesAnalysis doAllInstances(@NonNull QVTiTransformationAnalysis transformationAnalysis) { Set<org.eclipse.ocl.pivot.@NonNull Class> allInstancesClasses = transformationAnalysis.getAllInstancesClasses(); if (allInstancesClasses.size() > 0) { @@ -382,9 +383,9 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato } protected void doAssigned(@NonNull CGEcoreContainerAssignment cgPropertyAssignment) { - EStructuralFeature eStructuralFeature = ClassUtil.nonNullModel(cgPropertyAssignment.getEStructuralFeature()); - CGValuedElement cgSlot = getExpression(cgPropertyAssignment.getOwnedSlotValue()); - CGValuedElement cgInit = getExpression(cgPropertyAssignment.getOwnedInitValue()); + EStructuralFeature eStructuralFeature = QVTiCGUtil.getEStructuralFeature(cgPropertyAssignment); + CGValuedElement cgSlot = getExpression(QVTiCGUtil.getOwnedSlotValue(cgPropertyAssignment)); + CGValuedElement cgInit = getExpression(QVTiCGUtil.getOwnedInitValue(cgPropertyAssignment)); EPackage ePackage = ClassUtil.nonNullModel(eStructuralFeature.getEContainingClass().getEPackage()); if (isIncremental || ((SetStatement)cgPropertyAssignment.getAst()).isIsNotify()) { js.append("objectManager.assigned("); @@ -404,9 +405,9 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato } protected void doAssigned(@NonNull CGEcorePropertyAssignment cgPropertyAssignment) { - EStructuralFeature eStructuralFeature = ClassUtil.nonNullModel(cgPropertyAssignment.getEStructuralFeature()); - CGValuedElement cgSlot = getExpression(cgPropertyAssignment.getOwnedSlotValue()); - CGValuedElement cgInit = getExpression(cgPropertyAssignment.getOwnedInitValue()); + EStructuralFeature eStructuralFeature = QVTiCGUtil.getEStructuralFeature(cgPropertyAssignment); + CGValuedElement cgSlot = getExpression(QVTiCGUtil.getOwnedSlotValue(cgPropertyAssignment)); + CGValuedElement cgInit = getExpression(QVTiCGUtil.getOwnedInitValue(cgPropertyAssignment)); EPackage ePackage = ClassUtil.nonNullModel(eStructuralFeature.getEContainingClass().getEPackage()); if (isIncremental || ((SetStatement)cgPropertyAssignment.getAst()).isIsNotify()) { js.append("objectManager.assigned("); @@ -504,6 +505,36 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato js.append("}\n"); } */ + protected void 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); + } + cgRealizedVariable.accept(this); + 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"); + js.popIndentation(); + js.append("}\n"); + } + } + protected boolean doEcoreCreateClass(@NonNull CGValuedElement cgElement, @NonNull EClass eClass) { String createMethodName = "create" + eClass.getName(); boolean doSetNonNull = false; @@ -528,7 +559,16 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato javaClass = null; } // - js.appendDeclaration(cgElement); + CGMapping cgMapping = QVTiCGUtil.basicGetContainingCGMapping(cgElement); + if ((cgMapping == null) || !useClass(cgMapping) || !isIncremental) { + js.append("final "); + if (!doSetNonNull) { + js.appendSuppressWarningsNull(false); + } + js.appendClassReference(true, cgElement); + js.append(" "); + } + js.appendValueName(cgElement); js.append(" = "); js.appendClassReference(javaClass); js.append(".eINSTANCE."); @@ -649,7 +689,7 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato } else if (asTypeId instanceof CollectionTypeId) { // FIXME Fudge for body-less functions if (js.isUseNullAnnotations()) { - js.append("@SuppressWarnings(\"null\")"); + js.appendSuppressWarningsNull(false); js.appendIsRequired(true); js.append(" "); } @@ -701,7 +741,7 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato } else if (asTypeId instanceof CollectionTypeId) { // FIXME Fudge for body-less functions if (js.isUseNullAnnotations()) { - js.append("@SuppressWarnings(\"null\")"); + js.appendSuppressWarningsNull(false); js.appendIsRequired(true); js.append(" "); } @@ -854,9 +894,9 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato protected void doFunctionConstructor(@NonNull CGFunction cgFunction, @NonNull CGShadowExp cgShadowExp, @NonNull String instanceName) { // List<@NonNull CGParameter> cgParameters = ClassUtil.nullFree(cgFunction.getParameters()); - if (js.isUseNullAnnotations()) { - js.append("@SuppressWarnings(\"null\")\n"); // Accurate casts are too hard - } + // if (js.isUseNullAnnotations()) { + // js.append("@SuppressWarnings(\"null\")\n"); // Accurate casts are too hard + // } js.append("public "); js.append(getFunctionName(cgFunction)); js.append("(/*Nullable*/ Object "); @@ -1122,9 +1162,8 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato public @NonNull Boolean doMappingCall_Class(@NonNull CGMappingCall cgMappingCall) { js.append("invocationManager.flush();\n"); - MappingCall pMappingCall = (MappingCall) cgMappingCall.getAst(); - Mapping pReferredMapping = pMappingCall.getReferredMapping(); - assert pReferredMapping != null; + 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); @@ -1132,20 +1171,21 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato // 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(cgMappingCallBinding.getOwnedValue()); + js.appendValueName(ownedValue); js.append(" instanceof "); js.appendClassReference(checkedType); js.append(") {\n"); js.pushIndentation(null); } - else if (!cgMappingCallBinding.isNonNull()) { + else if (!ownedValue.isNonNull()) { Element asMappingParameterBinding = cgMappingCallBinding.getAst(); if (!(asMappingParameterBinding instanceof GuardParameterBinding)) { // FIXME this should be part of isNonNull js.append("if ("); - js.appendValueName(cgMappingCallBinding.getOwnedValue()); + js.appendValueName(ownedValue); js.append(" != null) {\n"); js.pushIndentation(null); } @@ -1195,7 +1235,7 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato js.popIndentation(); js.append("}\n"); } - else if (!cgMappingCallBinding.isNonNull()) { + else if (!cgMappingCallBinding.getOwnedValue().isNonNull()) { Element asMappingParameterBinding = cgMappingCallBinding.getAst(); if (!(asMappingParameterBinding instanceof GuardParameterBinding)) { // FIXME this should be part of isNonNull js.popIndentation(); @@ -1208,16 +1248,15 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato } public @NonNull Boolean doMappingCall_Function(@NonNull CGMappingCall cgMappingCall) { - MappingCall pMappingCall = (MappingCall) cgMappingCall.getAst(); - Mapping pReferredMapping = pMappingCall.getReferredMapping(); - assert pReferredMapping != null; + MappingCall pMappingCall = QVTiCGUtil.getAST(cgMappingCall); + Mapping pReferredMapping = QVTimperativeUtil.getReferredMapping(pMappingCall); CGMapping cgReferredMapping = analyzer.getMapping(pReferredMapping); assert cgReferredMapping != null; - List<CGMappingCallBinding> cgMappingCallBindings = cgMappingCall.getOwnedMappingCallBindings(); + 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 (@SuppressWarnings("null")@NonNull CGMappingCallBinding cgMappingCallBinding : cgMappingCallBindings) { + for (@NonNull CGMappingCallBinding cgMappingCallBinding : cgMappingCallBindings) { MappingParameterBinding asMappingParameterBinding = (MappingParameterBinding)cgMappingCallBinding.getAst(); if (asMappingParameterBinding instanceof AppendParameterBinding) { } @@ -1258,7 +1297,7 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato // js.append(getMappingName(cgReferredMapping) + "("); boolean isFirst = true; - for (@SuppressWarnings("null")@NonNull CGMappingCallBinding cgMappingCallBinding : cgMappingCallBindings) { + for (@NonNull CGMappingCallBinding cgMappingCallBinding : cgMappingCallBindings) { if (!isFirst) { js.append(", "); } @@ -1281,7 +1320,7 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato // // End the type check. // - for (@SuppressWarnings("null")@NonNull CGMappingCallBinding cgMappingCallBinding : cgMappingCallBindings) { + for (@NonNull CGMappingCallBinding cgMappingCallBinding : cgMappingCallBindings) { MappingParameterBinding asMappingParameterBinding = (MappingParameterBinding)cgMappingCallBinding.getAst(); if (asMappingParameterBinding instanceof AppendParameterBinding) { } @@ -1371,7 +1410,7 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato js.append("(invocationManager, "); js.appendString(QVTiCGUtil.getName(cgMapping)); js.append(", "); - js.appendBooleanString(((Mapping)cgMapping.getAst()).isIsStrict()); + js.appendBooleanString(QVTiCGUtil.getAST(cgMapping).isIsStrict()); js.append(")\n"); js.append("{\n"); js.pushIndentation(null); @@ -1399,16 +1438,63 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato } } - /* protected void doMappingConstructorInitializers(@NonNull CGTransformation cgTransformation) { - String className = cgTransformation.getName(); - for (@NonNull CGMapping cgMapping : ClassUtil.nullFree(cgTransformation.getMappings())) { - if (useClass(cgMapping) && (cgMapping.getFreeVariables().size() > 0)) { - js.append(getMappingCtorName(cgMapping) + " = "); - js.appendClassReference(ClassUtil.class); - js.append(".nonNullState(" + getMappingName(cgMapping) + ".class.getConstructor(" + className + ".class, Object[].class));\n"); + protected 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; } } - } */ + return needsNewLine; + } + + protected void doMappingRevokeInvocation(@NonNull CGMapping cgMapping) { + js.append("@Override\n"); + js.append("public void revokeInvocation() {\n"); + js.pushIndentation(null); + js.append("super.revokeInvocation();\n"); + for (@NonNull CGRealizedVariable cgRealizedVariable : QVTiCGUtil.getOwnedRealizedVariables(cgMapping)) { + 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(Model.Incremental.class); + js.append(")"); + js.append(QVTiGlobalContext.MODELS_NAME); + js.append("["); + appendModelIndex(cgTypedModel); + js.append("]).remove("); + js.appendValueName(cgRealizedVariable); + js.append(");\n"); + js.popIndentation(); + js.append("}\n"); + } + js.popIndentation(); + js.append("}\n"); + } protected void doOppositeCaches(@NonNull QVTiTransformationAnalysis transformationAnalysis) { Map<@NonNull Property, @NonNull Integer> opposites = transformationAnalysis.getCaches(); @@ -1725,8 +1811,7 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato @Override public @NonNull Boolean visitCGConnectionAssignment(@NonNull CGConnectionAssignment cgConnectionAssignment) { - CGValuedElement initValue = cgConnectionAssignment.getOwnedInitValue(); - assert initValue != null; + CGValuedElement initValue = QVTiCGUtil.getOwnedInitValue(cgConnectionAssignment); if (!js.appendLocalStatements(initValue)) { return false; } @@ -1737,7 +1822,7 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato BoxedDescriptor abstractBoxedDescriptor = concreteBoxedDescriptor; if (!(initValue.getASTypeId() instanceof CollectionTypeId)) { js.appendReferenceTo(cgConnectionAssignment.getConnectionVariable()); - js.append(".append("); + js.append(".appendElement("); js.appendValueName(initValue); js.append(");\n"); } @@ -1793,9 +1878,9 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato // Property pivotProperty = cgPropertyCallExp.getReferredProperty(); // CGTypeId cgTypeId = analyzer.getTypeId(pivotProperty.getOwningType().getTypeId()); // JavaTypeDescriptor requiredTypeDescriptor = context.getJavaTypeDescriptor(cgTypeId, false); - EStructuralFeature eStructuralFeature = ClassUtil.nonNullModel(cgPropertyAssignment.getEStructuralFeature()); - CGValuedElement cgSlot = getExpression(cgPropertyAssignment.getOwnedSlotValue()); - CGValuedElement cgInit = getExpression(cgPropertyAssignment.getOwnedInitValue()); + 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; @@ -1836,9 +1921,9 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato // Property pivotProperty = cgPropertyCallExp.getReferredProperty(); // CGTypeId cgTypeId = analyzer.getTypeId(pivotProperty.getOwningType().getTypeId()); // JavaTypeDescriptor requiredTypeDescriptor = context.getJavaTypeDescriptor(cgTypeId, false); - EStructuralFeature eStructuralFeature = ClassUtil.nonNullModel(cgPropertyAssignment.getEStructuralFeature()); - CGValuedElement cgSlot = getExpression(cgPropertyAssignment.getOwnedSlotValue()); - CGValuedElement cgInit = getExpression(cgPropertyAssignment.getOwnedInitValue()); + 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; @@ -1861,7 +1946,7 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato if (!js.appendLocalStatements(source)) { return false; } - EStructuralFeature eStructuralFeature = ClassUtil.nonNullState(cgPropertyCallExp.getEStructuralFeature()); + EStructuralFeature eStructuralFeature = QVTiCGUtil.getEStructuralFeature(cgPropertyCallExp); doGetting(cgPropertyCallExp, eStructuralFeature, false); Boolean status = appendCGEcorePropertyCallExp(cgPropertyCallExp, source); if (status != ValueUtil.TRUE_VALUE) { @@ -1877,12 +1962,6 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato if (doEcoreCreateClass(cgRealizedVariable, (EClass)eClassifier)) { cgRealizedVariable.setNonNull(); } - // - js.append("assert "); - js.appendValueName(cgRealizedVariable); - js.append(" != null;\n"); - // - doAddRealization(cgRealizedVariable); return true; } @@ -2085,13 +2164,7 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato js.append(" extends "); js.appendClassReference(isIncremental ? AbstractInvocation.Incremental.class : AbstractInvocation.class); js.pushClassBody(mappingName); - boolean needsNewLine = false; - for (@NonNull CGGuardVariable cgFreeVariable : cgFreeVariables) { - js.append("protected "); - doMappingConnectionVariable(cgFreeVariable); - js.append(";\n"); - needsNewLine = true; - } + boolean needsNewLine = doMappingFields(cgMapping); if (needsNewLine) { js.append("\n"); } @@ -2102,6 +2175,10 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato doMappingBody(cgMapping, true); js.append("\n"); doIsEqual(cgFreeVariables); + if (isIncremental && !Iterables.isEmpty(QVTiCGUtil.getOwnedRealizedVariables(cgMapping))) { + js.append("\n"); + doMappingRevokeInvocation(cgMapping); + } js.popClassBody(false); } else { @@ -2117,7 +2194,6 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato js.append(") "); doMappingBody(cgMapping, false); - } } finally { @@ -2129,11 +2205,8 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato @Override public @NonNull Boolean visitCGMappingCall(@NonNull CGMappingCall cgMappingCall) { - MappingCall pMappingCall = (MappingCall) cgMappingCall.getAst(); - Mapping pReferredMapping = pMappingCall.getReferredMapping(); - if (pReferredMapping == null) { - return true; - } + MappingCall pMappingCall = QVTiCGUtil.getAST(cgMappingCall); + Mapping pReferredMapping = QVTimperativeUtil.getReferredMapping(pMappingCall); CGMapping cgReferredMapping = analyzer.getMapping(pReferredMapping); if (cgReferredMapping == null) { return true; @@ -2163,9 +2236,9 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato @Override public @NonNull Boolean visitCGMappingExp(@NonNull CGMappingExp cgMappingExp) { // assert cgMappingExp.getPredicates().isEmpty(); // Get rewritten during JavaPre pass - CGMapping cgMapping = ClassUtil.nonNullState(QVTiCGUtil.getContainingCGMapping(cgMappingExp)); - List<@NonNull CGAccumulator> cgAccumulators = ClassUtil.nullFree(cgMappingExp.getOwnedAccumulators()); - if (cgAccumulators.size() > 0) { + CGMapping cgMapping = QVTiCGUtil.getContainingCGMapping(cgMappingExp); + Iterable<@NonNull CGAccumulator> cgAccumulators = QVTiCGUtil.getOwnedAccumulators(cgMappingExp); + if (!Iterables.isEmpty(cgAccumulators)) { js.append("// connection variables\n"); for (@NonNull CGAccumulator cgAccumulator : cgAccumulators) { Element ast = cgAccumulator.getAst(); @@ -2219,7 +2292,7 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato js.append(") {\n"); js.pushIndentation(null); js.appendReferenceTo(cgAccumulator); - js.append(".append("); + js.append(".appendElement("); js.append(iteratorName); js.append(");\n"); js.popIndentation(); @@ -2227,22 +2300,22 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato } } } - List<@NonNull CGRealizedVariable> cgRealizedVariables = ClassUtil.nullFree(cgMapping.getOwnedRealizedVariables()); - if (cgRealizedVariables.size() > 0) { + Iterable<@NonNull CGRealizedVariable> cgRealizedVariables = QVTiCGUtil.getOwnedRealizedVariables(cgMapping); + if (!Iterables.isEmpty(cgRealizedVariables)) { js.append("// creations\n"); for (@NonNull CGRealizedVariable cgRealizedVariable : cgRealizedVariables) { - cgRealizedVariable.accept(this); + doCreateRealizedVariable(cgRealizedVariable); } } - List<@NonNull CGPropertyAssignment> cgPropertyAssignments = ClassUtil.nullFree(cgMapping.getOwnedAssignments()); - if (cgPropertyAssignments.size() > 0) { + Iterable<@NonNull CGPropertyAssignment> cgPropertyAssignments = QVTiCGUtil.getOwnedAssignments(cgMapping); + if (!Iterables.isEmpty(cgPropertyAssignments)) { js.append("// property assignments\n"); for (@NonNull CGPropertyAssignment cgAssignment : cgPropertyAssignments) { cgAssignment.accept(this); } } - List<@NonNull CGConnectionAssignment> cgConnectionAssignments = ClassUtil.nullFree(cgMapping.getOwnedConnectionAssignments()); - if (cgConnectionAssignments.size() > 0) { + Iterable<@NonNull CGConnectionAssignment> cgConnectionAssignments = QVTiCGUtil.getOwnedConnectionAssignments(cgMapping); + if (!Iterables.isEmpty(cgConnectionAssignments)) { js.append("// connection assignments\n"); for (@NonNull CGConnectionAssignment cgConnectionAssignment : cgConnectionAssignments) { cgConnectionAssignment.accept(this); @@ -2309,14 +2382,12 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato for (EObject eObject : new TreeIterable(body, false)) { if (eObject instanceof CGMappingCall) { CGMappingCall cgMappingCall = (CGMappingCall)eObject; - MappingCall asMappingCall = (MappingCall) cgMappingCall.getAst(); - Mapping pReferredMapping = asMappingCall.getReferredMapping(); - if (pReferredMapping != null) { - CGMapping cgReferredMapping = analyzer.getMapping(pReferredMapping); - if ((cgReferredMapping != null) && useClass(cgReferredMapping)) { - needsFlush = true; - break; - } + MappingCall asMappingCall = QVTiCGUtil.getAST(cgMappingCall); + Mapping pReferredMapping = QVTimperativeUtil.getReferredMapping(asMappingCall); + CGMapping cgReferredMapping = analyzer.getMapping(pReferredMapping); + if ((cgReferredMapping != null) && useClass(cgReferredMapping)) { + needsFlush = true; + break; } } } @@ -2328,22 +2399,20 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato @Override public @NonNull Boolean visitCGMiddlePropertyAssignment(@NonNull CGMiddlePropertyAssignment cgMiddlePropertyAssignment) { - Property pReferredProperty = ClassUtil.nonNullModel(cgMiddlePropertyAssignment.getReferredProperty()); + Property pReferredProperty = QVTiCGUtil.getReferredProperty(cgMiddlePropertyAssignment); assert !pReferredProperty.isIsImplicit(); - CGValuedElement slotValue = cgMiddlePropertyAssignment.getOwnedSlotValue(); - CGValuedElement initValue = cgMiddlePropertyAssignment.getOwnedInitValue(); - if ((slotValue != null) && (initValue != null)) { - Map<@NonNull Property, @NonNull String> oppositeProperties = getGlobalContext().getOppositeProperties(); - if (oppositeProperties != null) { - String cacheName = oppositeProperties.get(pReferredProperty); - if (cacheName != null) { - js.append(cacheName); - js.append(".put("); - js.appendValueName(initValue); - js.append(", "); - js.appendValueName(slotValue); - js.append(");\n"); - } + CGValuedElement slotValue = QVTiCGUtil.getOwnedSlotValue(cgMiddlePropertyAssignment); + CGValuedElement initValue = QVTiCGUtil.getOwnedInitValue(cgMiddlePropertyAssignment); + Map<@NonNull Property, @NonNull String> oppositeProperties = getGlobalContext().getOppositeProperties(); + if (oppositeProperties != null) { + String cacheName = oppositeProperties.get(pReferredProperty); + if (cacheName != null) { + js.append(cacheName); + js.append(".put("); + js.appendValueName(initValue); + js.append(", "); + js.appendValueName(slotValue); + js.append(");\n"); } } return visitCGEcorePropertyAssignment(cgMiddlePropertyAssignment); @@ -2390,22 +2459,20 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato @Override public @NonNull Boolean visitCGPropertyAssignment(@NonNull CGPropertyAssignment cgPropertyAssignment) { CGExecutorProperty cgExecutorProperty = cgPropertyAssignment.getExecutorProperty(); - CGValuedElement slotValue = cgPropertyAssignment.getOwnedSlotValue(); - CGValuedElement initValue = cgPropertyAssignment.getOwnedInitValue(); - if ((slotValue != null) && (initValue != null)) { - if (!js.appendLocalStatements(slotValue)) { - return false; - } - if (!js.appendLocalStatements(initValue)) { - return false; - } - js.appendReferenceTo(cgExecutorProperty); - js.append(".initValue("); - js.appendValueName(slotValue); - js.append(", "); - js.appendValueName(initValue); - js.append(");\n"); + 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; } @@ -2413,13 +2480,17 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato public @NonNull Boolean visitCGRealizedVariable(@NonNull CGRealizedVariable cgRealizedVariable) { TypeId typeId = cgRealizedVariable.getASTypeId(); if (typeId != null) { - js.appendDeclaration(cgRealizedVariable); + 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"); } - // - doAddRealization(cgRealizedVariable); return true; } @@ -2466,7 +2537,7 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato js.append(" * <br>\n"); js.append(" * Extract each output model with {@link getRootObjects(String)}\n"); js.append(" */\n"); - js.append("@SuppressWarnings(\"nls\")\n"); + js.append("@SuppressWarnings({\"nls\",\"unused\"})\n"); js.append("public class " + className + " extends "); js.appendClassReference(getAbstractTransformationExecutorClass()); js.pushClassBody(className); diff --git a/plugins/org.eclipse.qvtd.codegen/src/org/eclipse/qvtd/codegen/utilities/QVTiCGUtil.java b/plugins/org.eclipse.qvtd.codegen/src/org/eclipse/qvtd/codegen/utilities/QVTiCGUtil.java index 042a4f0ad..260da702d 100644 --- a/plugins/org.eclipse.qvtd.codegen/src/org/eclipse/qvtd/codegen/utilities/QVTiCGUtil.java +++ b/plugins/org.eclipse.qvtd.codegen/src/org/eclipse/qvtd/codegen/utilities/QVTiCGUtil.java @@ -17,16 +17,22 @@ import org.eclipse.jdt.annotation.Nullable; import org.eclipse.ocl.examples.codegen.cgmodel.CGAccumulator; import org.eclipse.ocl.examples.codegen.cgmodel.CGEcorePropertyCallExp; import org.eclipse.ocl.examples.codegen.cgmodel.CGElement; +import org.eclipse.ocl.examples.codegen.cgmodel.CGValuedElement; import org.eclipse.ocl.examples.codegen.utilities.CGUtil; import org.eclipse.ocl.pivot.VariableDeclaration; +import org.eclipse.ocl.pivot.Property; import org.eclipse.ocl.pivot.utilities.ClassUtil; import org.eclipse.ocl.pivot.utilities.NameUtil; +import org.eclipse.qvtd.codegen.qvticgmodel.CGConnectionAssignment; import org.eclipse.qvtd.codegen.qvticgmodel.CGEcoreContainerAssignment; import org.eclipse.qvtd.codegen.qvticgmodel.CGEcorePropertyAssignment; 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.CGPropertyAssignment; +import org.eclipse.qvtd.codegen.qvticgmodel.CGRealizedVariable; import org.eclipse.qvtd.codegen.qvticgmodel.CGTransformation; import org.eclipse.qvtd.codegen.qvticgmodel.CGTypedModel; import org.eclipse.qvtd.pivot.qvtimperative.GuardParameter; @@ -85,12 +91,36 @@ public class QVTiCGUtil extends CGUtil return ClassUtil.nonNullState(cgPropertyCallExp.getEStructuralFeature()); } + public static @NonNull String getName(@NonNull CGAccumulator cgAccumulator) { + return ClassUtil.nonNullState(cgAccumulator.getName()); + } + public static @NonNull String getName(@NonNull CGMapping cgMapping) { return ClassUtil.nonNullState(cgMapping.getName()); } - public static @NonNull String getName(@NonNull CGAccumulator cgAccumulator) { - return ClassUtil.nonNullState(cgAccumulator.getName()); + public static @NonNull Iterable<@NonNull CGAccumulator> getOwnedAccumulators(@NonNull CGMappingExp cgMappingExp) { + return ClassUtil.nullFree(cgMappingExp.getOwnedAccumulators()); + } + + public static @NonNull Iterable<@NonNull CGPropertyAssignment> getOwnedAssignments(@NonNull CGMapping cgMapping) { + return ClassUtil.nullFree(cgMapping.getOwnedAssignments()); + } + + public static @NonNull Iterable<@NonNull CGConnectionAssignment> getOwnedConnectionAssignments(@NonNull CGMapping cgMapping) { + return ClassUtil.nullFree(cgMapping.getOwnedConnectionAssignments()); + } + + public static @NonNull Iterable<@NonNull CGGuardVariable> getOwnedGuardVariables(@NonNull CGMapping cgRootMapping) { + return ClassUtil.nullFree(cgRootMapping.getOwnedGuardVariables()); + } + + public static @NonNull CGValuedElement getOwnedInitValue(@NonNull CGConnectionAssignment cgConnectionAssignment) { + return ClassUtil.nonNullState(cgConnectionAssignment.getOwnedInitValue()); + } + + public static @NonNull CGValuedElement getOwnedInitValue(@NonNull CGPropertyAssignment cgPropertyAssignment) { + return ClassUtil.nonNullState(cgPropertyAssignment.getOwnedInitValue()); } public static @NonNull Iterable<@NonNull CGMappingCallBinding> getOwnedMappingCallBindings(@NonNull CGMappingCall cgMappingCall) { @@ -101,6 +131,31 @@ public class QVTiCGUtil extends CGUtil return ClassUtil.nullFree(cgTransformation.getOwnedMappings()); } + public static @NonNull Iterable<@NonNull CGRealizedVariable> getOwnedRealizedVariables(@NonNull CGMapping cgMapping) { + return ClassUtil.nullFree(cgMapping.getOwnedRealizedVariables()); + } + + public static @NonNull CGValuedElement getOwnedSlotValue(@NonNull CGPropertyAssignment cgPropertyAssignment) { + return ClassUtil.nonNullState(cgPropertyAssignment.getOwnedSlotValue()); + } + + public static @NonNull Iterable<@NonNull CGTypedModel> getOwnedTypedModels(@NonNull CGTransformation cgTransformation) { + return ClassUtil.nullFree(cgTransformation.getOwnedTypedModels()); + } + + public static @NonNull CGMapping getOwningMapping(@NonNull CGRealizedVariable cgRealizedVariable) { + return ClassUtil.nonNullState(cgRealizedVariable.getOwningMapping()); + } + + public static @NonNull CGTransformation getOwningTransformation(@NonNull CGMapping cgMapping) { + return ClassUtil.nonNullState(cgMapping.getOwningTransformation()); + + } + + public static @NonNull Property getReferredProperty(@NonNull CGPropertyAssignment cgPropertyAssignment) { + return ClassUtil.nonNullState(cgPropertyAssignment.getReferredProperty()); + } + public static @NonNull CGMapping getRootMapping(@NonNull CGTransformation cgTransformation) { CGMapping cgRootMapping = NameUtil.getNameable(cgTransformation.getOwnedMappings(), QVTimperativeUtil.ROOT_MAPPING_NAME); // Obsolete relic for (@NonNull CGMapping cgMapping : getOwnedMappings(cgTransformation)) { @@ -130,17 +185,4 @@ public class QVTiCGUtil extends CGUtil } return cgRootMapping; } - - public static @NonNull Iterable<@NonNull CGGuardVariable> getOwnedGuardVariables(@NonNull CGMapping cgRootMapping) { - return ClassUtil.nullFree(cgRootMapping.getOwnedGuardVariables()); - } - - public static @NonNull Iterable<@NonNull CGTypedModel> getOwnedTypedModels(@NonNull CGTransformation cgTransformation) { - return ClassUtil.nullFree(cgTransformation.getOwnedTypedModels()); - } - - public static @NonNull CGTransformation getOwningTransformation(@NonNull CGMapping cgMapping) { - return ClassUtil.nonNullState(cgMapping.getOwningTransformation()); - - } } diff --git a/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/BasicQVTiExecutor.java b/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/BasicQVTiExecutor.java index 3465732fb..7b3783d8a 100644 --- a/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/BasicQVTiExecutor.java +++ b/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/BasicQVTiExecutor.java @@ -400,7 +400,7 @@ public abstract class BasicQVTiExecutor extends AbstractExecutor implements QVTi Connection connection = rootInterval.createConnection(QVTimperativeUtil.getName(mappingParameter), type.getTypeId(), false); Iterable<@NonNull ? extends Object> objectsOfKind = modelInstance.getObjectsOfKind(type); for (@NonNull Object object : objectsOfKind) { - connection.append(object); + connection.appendElement(object); } getEvaluationEnvironment().add(mappingParameter, connection); } diff --git a/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/QVTiEvaluationVisitor.java b/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/QVTiEvaluationVisitor.java index c388c7280..6b6051245 100644 --- a/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/QVTiEvaluationVisitor.java +++ b/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/QVTiEvaluationVisitor.java @@ -101,7 +101,7 @@ public class QVTiEvaluationVisitor extends BasicEvaluationVisitor implements IQV // } // } // else { - connectionCollection.append(values); + connectionCollection.appendElement(values); // } return connectionCollection; } @@ -306,7 +306,7 @@ public class QVTiEvaluationVisitor extends BasicEvaluationVisitor implements IQV if (initValue != null) { for (Object value : (Iterable<?>)initValue) { assert value != null; - connection.append(value); + connection.appendElement(value); } } } diff --git a/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/utilities/QVTimperativeUtil.java b/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/utilities/QVTimperativeUtil.java index 33c49f484..3d4769c9c 100644 --- a/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/utilities/QVTimperativeUtil.java +++ b/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/utilities/QVTimperativeUtil.java @@ -308,6 +308,10 @@ public class QVTimperativeUtil extends QVTbaseUtil return (@NonNull Iterable<@NonNull ImperativeTypedModel>)modelParameter; } + public static @NonNull Mapping getReferredMapping(MappingCall asMappingCall) { + return ClassUtil.nonNullState(asMappingCall.getReferredMapping()); + } + public static @NonNull Mapping getRootMapping(@NonNull ImperativeTransformation asTransformation) { Mapping asRootMapping = NameUtil.getNameable(getOwnedMappings(asTransformation), QVTimperativeUtil.ROOT_MAPPING_NAME); // Obsolete relic for (@NonNull Mapping asMapping : getOwnedMappings(asTransformation)) { diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/AbstractComputation.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/AbstractComputation.java index 801e2ad5e..eb3395025 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/AbstractComputation.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/AbstractComputation.java @@ -41,6 +41,18 @@ public abstract class AbstractComputation implements Computation public @NonNull Iterable<@NonNull Object> getCreatedObjects() { return /*createdObjects != null ? createdObjects :*/ EMPTY_OBJECT_LIST; } + + @Override + public void revokeExecution() { + // TODO Auto-generated method stub + + } + + @Override + public void revokeInvocation() { + // TODO Auto-generated method stub + + } } @Override diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/AbstractInvocation.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/AbstractInvocation.java index e391c45a5..307f916d7 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/AbstractInvocation.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/AbstractInvocation.java @@ -99,6 +99,26 @@ public abstract class AbstractInvocation extends AbstractInvocationInternal } @Override + public void revokeExecution() { + if (writeSlots != null) { + for (SlotState.@NonNull Incremental writeSlot : writeSlots) { + writeSlot.revokeAssigned(); + } + } + interval.queue(this); + } + + @Override + public void revokeInvocation() { + if (writeSlots != null) { + for (SlotState.@NonNull Incremental writeSlot : writeSlots) { + writeSlot.revokeAssigned(); + } + } + interval.queue(this); + } + + @Override public @NonNull String toString() { return getName(); } diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/AbstractSlotState.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/AbstractSlotState.java index 33ed9e9a5..8668c73e1 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/AbstractSlotState.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/AbstractSlotState.java @@ -58,6 +58,12 @@ public abstract class AbstractSlotState implements SlotState public @NonNull Iterable<Execution.@NonNull Incremental> getTargets() { return targets != null ? targets : EMPTY_EXECUTIONS_LIST; } + + protected void revokeTargets() { + for (Execution.@NonNull Incremental target : getTargets()) { + target.revokeExecution(); + } + } } @Override diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/Connection.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/Connection.java index ba36c8104..2133f0555 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/Connection.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/Connection.java @@ -41,6 +41,16 @@ public interface Connection extends ExecutionVisitable, Nameable @NonNull Iterable<@NonNull InvocationConstructor> getAppenders(); /** + * Remove, inverse append, the old anElement. + * + * If the old value is a multiple value in a unique value connection, the multi-value count is decremented. + * + * Otherwise the old value is removed, its consumingInvocations are revoked + * so that their appends are also revoked. + */ + void removeElement(@NonNull Object anElement); + + /** * Replace the old value at connectionKey by newValue. * * If the old value is a multiple value in a unique value connection, the multi-value count is decremented @@ -67,12 +77,12 @@ public interface Connection extends ExecutionVisitable, Nameable boolean addConsumer(@NonNull InvocationConstructor consumingInvoker); /** - * Append aValue to the contents, enforcing uniqueness if necessary, and waking up the overall + * Append anElement to the contents, enforcing uniqueness if necessary, and waking up the overall * connection manager to schedule a propagate() to consumers when convenient. * * Return the new entry. */ - @NonNull Object append(@NonNull Object aValue); + @NonNull Object appendElement(@NonNull Object anElement); int getCapacity(); diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/Execution.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/Execution.java index 413b5b772..4263778af 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/Execution.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/Execution.java @@ -15,7 +15,7 @@ import org.eclipse.ocl.pivot.utilities.Nameable; /** * An Execution identifies a unique execution and the objects/values that it uses. - * Derived EXecutions support Mapping Invocations and unique Function Computations + * Derived Executions support Mapping Invocations and unique Function Computations * * @noimplement clients should derive from AbstractInvocation */ @@ -25,7 +25,20 @@ public interface Execution extends ExecutionVisitable, Nameable { void addReadSlot(SlotState.@NonNull Incremental readSlot); @NonNull Iterable<@NonNull Object> getCreatedObjects(); - @Override - @NonNull String getName(); + + /** + * Revoke the consequences of a previous execution in preparation for a new execution. + * This reverts all assigned slot states back to REASSIGNABLE. + */ + void revokeExecution(); + + /** + * Revoke the consequences of a previous execution that will not be re-executed. + * All created objects are revoked. + */ + void revokeInvocation(); } + + @Override + @NonNull String getName(); }
\ No newline at end of file diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/SlotState.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/SlotState.java index 7668dca99..b6af059d3 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/SlotState.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/SlotState.java @@ -49,5 +49,6 @@ public interface SlotState extends ExecutionVisitable @Nullable Object getValue(); @NonNull Iterable<Invocation.@NonNull Incremental> getSources(); @NonNull Iterable<Execution.@NonNull Incremental> getTargets(); + void revokeAssigned(); } } diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/StrictIncrementalConnection.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/StrictIncrementalConnection.java index 9b2eafd17..ca62a88c9 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/StrictIncrementalConnection.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/StrictIncrementalConnection.java @@ -10,6 +10,8 @@ *******************************************************************************/ package org.eclipse.qvtd.runtime.evaluation; +import java.util.List; + import org.eclipse.jdt.annotation.NonNull; import org.eclipse.ocl.pivot.ids.TypeId; import org.eclipse.qvtd.runtime.internal.evaluation.StrictIncrementalConnectionInternal; @@ -28,4 +30,31 @@ public class StrictIncrementalConnection extends StrictIncrementalConnectionInte public StrictIncrementalConnection(@NonNull Interval interval, @NonNull String name, @NonNull TypeId typeId) { super(interval, name, typeId); } + + /** + * Remove, inverse append, the old anElement. The old value is removed, + * its consumingInvocations are revoked so that their appends are also revoked. + */ + @Override + public synchronized void removeElement(@NonNull Object anElement) { + for (int i = 0; i < listOfValueAndConsumingInvocations.size(); i++) { + List<@NonNull Object> valueAndConsumingInvocations = listOfValueAndConsumingInvocations.get(i); + if ((valueAndConsumingInvocations != null) && (valueAndConsumingInvocations.get(VALUE_INDEX) == anElement)) { + Integer count = (Integer) valueAndConsumingInvocations.get(COUNT_INDEX); + assert count != null; + if (count <= 0) { + listOfValueAndConsumingInvocations.set(i, null); + int jMax = valueAndConsumingInvocations.size(); + for (int j = INDEX_INDEX+1; j < jMax; j++) { + AbstractInvocation.Incremental consumingInvocation = (AbstractInvocation.Incremental) valueAndConsumingInvocations.get(j); + consumingInvocation.revokeExecution(); + } + } + else { + valueAndConsumingInvocations.set(COUNT_INDEX, count-1); + } + break; + } + } + } }
\ No newline at end of file diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractConnectionInternal.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractConnectionInternal.java index ac67c953c..514c509e8 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractConnectionInternal.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractConnectionInternal.java @@ -45,17 +45,17 @@ public abstract class AbstractConnectionInternal extends AbstractConnection public void addAppender(@NonNull InvocationConstructor appendingInvoker) {} /** - * Append aValue to the contents, and waking up the overall + * Append anElement to the contents, and waking up the overall * connection manager to schedule a propagate() to consumers when convenient. */ @Override - public synchronized @NonNull Object append(@NonNull Object aValue) { + public synchronized @NonNull Object appendElement(@NonNull Object anElement) { if (debugAppends) { - AbstractTransformer.APPENDS.println(this + " <= " + LabelUtil.getLabel(aValue)); + AbstractTransformer.APPENDS.println(this + " <= " + LabelUtil.getLabel(anElement)); } - values.add(aValue); + values.add(anElement); queue(); - return aValue; + return anElement; } @Override diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractInvocationInternal.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractInvocationInternal.java index 6ac99e2ad..1dbb171cb 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractInvocationInternal.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractInvocationInternal.java @@ -54,10 +54,6 @@ public abstract class AbstractInvocationInternal implements Invocation next = this; } - public void revoke() { - throw new UnsupportedOperationException(); - } - @Override public String toString() { return getClass().getSimpleName() + "@" + Integer.toHexString(System.identityHashCode(this)); diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractTransformerInternal.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractTransformerInternal.java index 64bdaf9ea..a025651cf 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractTransformerInternal.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractTransformerInternal.java @@ -67,6 +67,11 @@ public abstract class AbstractTransformerInternal /*extends AbstractModelManager } @Override + protected @NonNull Connection createConnection(@NonNull String name, @NonNull TypeId typeId, boolean isStrict) { + return invocationManager.getRootInterval().createIncrementalConnection(name, typeId, isStrict); + } + + @Override protected @NonNull InvocationManager createInvocationManager() { return new IncrementalInvocationManager(executor); } @@ -74,7 +79,7 @@ public abstract class AbstractTransformerInternal /*extends AbstractModelManager @Override protected @NonNull Model createModel(@NonNull String modelName, @NonNull PropertyId @Nullable [] propertyIndex2propertyId, @NonNull ClassId @NonNull [] classIndex2classId, int @Nullable [] @NonNull [] classIndex2allClassIndexes) { - return new Model(modelName, propertyIndex2propertyId, classIndex2classId, classIndex2allClassIndexes); + return new Model.Incremental(this, modelName, propertyIndex2propertyId, classIndex2classId, classIndex2allClassIndexes); } @Override @@ -86,13 +91,13 @@ public abstract class AbstractTransformerInternal /*extends AbstractModelManager private static final @NonNull List<@NonNull Integer> EMPTY_INDEX_LIST = Collections.emptyList(); private static final @NonNull List<@NonNull Object> EMPTY_EOBJECT_LIST = Collections.emptyList(); - protected class Model extends AbstractTypedModelInstance + public static class Model extends AbstractTypedModelInstance { - protected class Incremental extends Model + public static class Incremental extends Model { - public Incremental(@NonNull String name, @NonNull PropertyId @Nullable [] propertyIndex2propertyId, + public Incremental(@NonNull AbstractTransformerInternal transformer, @NonNull String name, @NonNull PropertyId @Nullable [] propertyIndex2propertyId, @NonNull ClassId @NonNull [] classIndex2classId, int @Nullable [] @NonNull [] classIndex2allClassIndexes) { - super(name, propertyIndex2propertyId, classIndex2classId, classIndex2allClassIndexes); + super(transformer, name, propertyIndex2propertyId, classIndex2classId, classIndex2allClassIndexes); } public void remove(@NonNull EObject eObject) { @@ -122,12 +127,12 @@ public abstract class AbstractTransformerInternal /*extends AbstractModelManager private void unaccumulateEObject(@Nullable Map<@NonNull EClass, @NonNull Set<@NonNull Integer>> eClass2allClassIndexes, @Nullable Map<@NonNull EClass, @NonNull List<@NonNull Integer>> eClass2allPropertyIndexes, @Nullable Map<@NonNull EReference, @NonNull Integer> eReference2propertyIndex, @NonNull Object eObject) { - EClass eClass = eClass(eObject); + EClass eClass = transformer.eClass(eObject); if (eClass2allClassIndexes != null) { Set<@NonNull Integer> allClassIndexes = eClass2allClassIndexes.get(eClass); if (allClassIndexes != null) { for (@NonNull Integer classIndex : allClassIndexes) { - ((Connection.Incremental)classIndex2connection[classIndex]).revoke(eObject); + ((Connection.Incremental)classIndex2connection[classIndex]).removeElement(eObject); } } } @@ -136,14 +141,14 @@ public abstract class AbstractTransformerInternal /*extends AbstractModelManager assert eReference2propertyIndex2 != null; List<@NonNull Integer> allPropertyIndexes = eClass2allPropertyIndexes.get(eClass); if (allPropertyIndexes != null) { - Map<@NonNull Object, @NonNull Object>[] object2oppositeObject2 = object2oppositeObject; + Map<@NonNull Object, @NonNull Object>[] object2oppositeObject2 = transformer.object2oppositeObject; assert object2oppositeObject2 != null; for (@NonNull Integer propertyIndex : allPropertyIndexes) { - EReference @Nullable [] propertyIndex2eReference2 = propertyIndex2eReference; + EReference @Nullable [] propertyIndex2eReference2 = transformer.propertyIndex2eReference; assert propertyIndex2eReference2 != null; EReference eReference = propertyIndex2eReference2[propertyIndex]; if (eReference != null) { - Object object = eGet(eObject, eReference); + Object object = transformer.eGet(eObject, eReference); assert object != null; object2oppositeObject2[propertyIndex].remove(object); } @@ -153,18 +158,20 @@ public abstract class AbstractTransformerInternal /*extends AbstractModelManager } } + protected final @NonNull AbstractTransformerInternal transformer; protected final @NonNull String name; - private @Nullable List<@NonNull Object> allEObjects = null; + protected @Nullable List<@NonNull Object> allEObjects = null; private @Nullable List<@NonNull Object> rootEObjects = null; - private final @NonNull Map<@NonNull EClass, @NonNull Set<@NonNull Integer>> eClass2allClassIndexes = new HashMap<>(); + protected final @NonNull Map<@NonNull EClass, @NonNull Set<@NonNull Integer>> eClass2allClassIndexes = new HashMap<>(); /** * All possible allInstances() returns indexed by the ClassIndex of the ClassId for which allInstances() may be invoked. */ - private final @NonNull Connection [] classIndex2connection; + protected final @NonNull Connection [] classIndex2connection; - public Model(@NonNull String name, @NonNull PropertyId @Nullable [] propertyIndex2propertyId, + public Model(@NonNull AbstractTransformerInternal transformer, @NonNull String name, @NonNull PropertyId @Nullable [] propertyIndex2propertyId, @NonNull ClassId @NonNull [] classIndex2classId, int @Nullable [] @NonNull [] classIndex2allClassIndexes) { + this.transformer = transformer; this.name = name; // // Prepare the allInstances() fields @@ -174,7 +181,7 @@ public abstract class AbstractTransformerInternal /*extends AbstractModelManager for (int i = 0; i < classIds; i++) { @NonNull ClassId classId = classIndex2classId[i]; - classIndex2connection[i] = createConnection(name + "-" + classId, classId, false); + classIndex2connection[i] = transformer.createConnection(name + "-" + classId, classId, false); } } @@ -185,11 +192,11 @@ public abstract class AbstractTransformerInternal /*extends AbstractModelManager private void accumulateEObject1(@NonNull Object eObject, @NonNull EClass eClass) { Set<@NonNull Integer> allClassIndexes = eClass2allClassIndexes.get(eClass); if (allClassIndexes == null) { - allClassIndexes = getClassIndexes(eClass); + allClassIndexes = transformer.getClassIndexes(eClass); eClass2allClassIndexes.put(eClass, allClassIndexes); } for (@NonNull Integer classIndex : allClassIndexes) { - classIndex2connection[classIndex].append(eObject); + classIndex2connection[classIndex].appendElement(eObject); } } @@ -206,24 +213,24 @@ public abstract class AbstractTransformerInternal /*extends AbstractModelManager assert eReference2propertyIndex2 != null; List<@NonNull Integer> allPropertyIndexes = eClass2allPropertyIndexes.get(eClass); if (allPropertyIndexes == null) { - allPropertyIndexes = getOppositePropertyIndexes(eReference2propertyIndex2, eClass); + allPropertyIndexes = transformer.getOppositePropertyIndexes(eReference2propertyIndex2, eClass); eClass2allPropertyIndexes.put(eClass, allPropertyIndexes); } - Map<@NonNull Object, @NonNull Object>[] object2oppositeObject2 = object2oppositeObject; + Map<@NonNull Object, @NonNull Object>[] object2oppositeObject2 = transformer.object2oppositeObject; assert object2oppositeObject2 != null; for (@NonNull Integer propertyIndex : allPropertyIndexes) { - EReference @Nullable [] propertyIndex2eReference2 = propertyIndex2eReference; + EReference @Nullable [] propertyIndex2eReference2 = transformer.propertyIndex2eReference; assert propertyIndex2eReference2 != null; EReference eReference = propertyIndex2eReference2[propertyIndex]; if (eReference == null) { - PropertyId @Nullable [] propertyIndex2propertyId2 = propertyIndex2propertyId; + PropertyId @Nullable [] propertyIndex2propertyId2 = transformer.propertyIndex2propertyId; assert propertyIndex2propertyId2 != null; PropertyId propertyId = propertyIndex2propertyId2[propertyIndex]; assert propertyId != null; eReference = (EReference) NameUtil.getENamedElement(eClass.getEAllStructuralFeatures(), propertyId.getName()); assert eReference != null; } - Object object = eGet(eObject, eReference); + Object object = transformer.eGet(eObject, eReference); assert object != null; object2oppositeObject2[propertyIndex].put(object, eObject); } @@ -237,7 +244,7 @@ public abstract class AbstractTransformerInternal /*extends AbstractModelManager rootEObjects = null; assert !allEObjects2.contains(eObject); allEObjects2.add(eObject); - EClass eClass = eClass(eObject); + EClass eClass = transformer.eClass(eObject); accumulateEObject1(eObject, eClass); } @@ -252,7 +259,7 @@ public abstract class AbstractTransformerInternal /*extends AbstractModelManager allEObjects = null; Map<@NonNull EClass, @NonNull List<@NonNull Integer>> eClass2allPropertyIndexes = null; Map<@NonNull EReference, @NonNull Integer> eReference2propertyIndex = null; - if (propertyIndex2propertyId != null) { + if (transformer.propertyIndex2propertyId != null) { eClass2allPropertyIndexes = new HashMap<>(); eReference2propertyIndex = new HashMap<>(); } @@ -264,15 +271,15 @@ public abstract class AbstractTransformerInternal /*extends AbstractModelManager // // Accumulate the root object and all its child objects in the allInstances() returns // - EClass eRootClass = eClass(eRootObject); + EClass eRootClass = transformer.eClass(eRootObject); accumulateEObject1(eRootObject, eRootClass); if (eClass2allPropertyIndexes != null) { accumulateEObject2(eRootObject, eRootClass, eClass2allPropertyIndexes, eReference2propertyIndex); } - for (TreeIterator<? extends Object> tit = eAllContents(eRootObject); tit.hasNext(); ) { + for (TreeIterator<? extends Object> tit = transformer.eAllContents(eRootObject); tit.hasNext(); ) { Object eObject = tit.next(); if (eObject != null) { - EClass eClass = eClass(eObject); + EClass eClass = transformer.eClass(eObject); accumulateEObject1(eObject, eClass); if (eClass2allPropertyIndexes != null) { accumulateEObject2(eObject, eClass, eClass2allPropertyIndexes, eReference2propertyIndex); @@ -292,7 +299,7 @@ public abstract class AbstractTransformerInternal /*extends AbstractModelManager for (@NonNull Object eRootObject : rootEObjects2) { assert !allEObjects2.contains(eRootObject); allEObjects2.add(eRootObject); - for (TreeIterator<? extends Object> tit = eAllContents(eRootObject); tit.hasNext(); ) { + for (TreeIterator<? extends Object> tit = transformer.eAllContents(eRootObject); tit.hasNext(); ) { Object eObject = tit.next(); if (eObject != null) { assert !allEObjects2.contains(eObject); @@ -312,7 +319,7 @@ public abstract class AbstractTransformerInternal /*extends AbstractModelManager @Override public @NonNull Iterable<@NonNull Object> getObjectsOfKind(org.eclipse.ocl.pivot.@NonNull Class type) { TypeId classId = type.getTypeId(); - Integer classIndex = classId2classIndex.get(classId); + Integer classIndex = transformer.classId2classIndex.get(classId); if (classIndex != null) { Iterable<@NonNull Object> typedIterable = classIndex2connection[classIndex].typedIterable(Object.class); // List<@NonNull Object> collection = new ArrayList<>(); @@ -360,7 +367,7 @@ public abstract class AbstractTransformerInternal /*extends AbstractModelManager List<@NonNull Object> allEObjects2 = allEObjects; if (allEObjects2 != null) { for (@NonNull Object eObject : allEObjects2) { - if (eContainer(eObject) == null) { + if (transformer.eContainer(eObject) == null) { rootEObjects2.add(eObject); } } @@ -383,7 +390,7 @@ public abstract class AbstractTransformerInternal /*extends AbstractModelManager public <@NonNull T> Iterable<T> typedIterable(Class<T> javaClass, org.eclipse.ocl.pivot.@NonNull Class pivotType) { TypeId typeId = pivotType.getTypeId(); - Integer classIndex = classId2classIndex.get(typeId); + Integer classIndex = transformer.classId2classIndex.get(typeId); if (classIndex != null) { Connection connection = classIndex2connection[classIndex]; return connection.typedIterable(javaClass); @@ -559,7 +566,7 @@ public abstract class AbstractTransformerInternal /*extends AbstractModelManager protected @NonNull Model createModel(@NonNull String modelName, @NonNull PropertyId @Nullable [] propertyIndex2propertyId, @NonNull ClassId @NonNull [] classIndex2classId, int @Nullable [] @NonNull [] classIndex2allClassIndexes) { - return new Model(modelName, propertyIndex2propertyId, classIndex2classId, classIndex2allClassIndexes); + return new Model(this, modelName, propertyIndex2propertyId, classIndex2classId, classIndex2allClassIndexes); } @Deprecated // Use createConnection diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/IncrementalConnectionInternal.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/IncrementalConnectionInternal.java index b847fd50f..aaad51458 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/IncrementalConnectionInternal.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/IncrementalConnectionInternal.java @@ -37,16 +37,16 @@ public class IncrementalConnectionInternal extends AbstractIncrementalConnection } /** - * Append aValue to the contents, and waking up the overall + * Append anElement to the contents, and waking up the overall * connection manager to schedule a propagate() to consumers when convenient. */ @Override - public synchronized @NonNull Object append(@NonNull Object aValue) { + public synchronized @NonNull Object appendElement(@NonNull Object anElement) { if (debugAppends) { - AbstractTransformer.APPENDS.println(this + " <= " + LabelUtil.getLabel(aValue)); + AbstractTransformer.APPENDS.println(this + " <= " + LabelUtil.getLabel(anElement)); } List<@NonNull Object> valueAndConsumingInvocations = new ArrayList<>(); - valueAndConsumingInvocations.add(aValue); // VALUE_INDEX + valueAndConsumingInvocations.add(anElement); // VALUE_INDEX valueAndConsumingInvocations.add(listOfValueAndConsumingInvocations.size()); // INDEX_INDEX listOfValueAndConsumingInvocations.add(valueAndConsumingInvocations); queue(); @@ -64,6 +64,26 @@ public class IncrementalConnectionInternal extends AbstractIncrementalConnection } /** + * Remove, inverse append, the old anElement. The old value is removed, + * its consumingInvocations are revoked so that their appends are also revoked. + */ + @Override + public synchronized void removeElement(@NonNull Object anElement) { + for (int i = 0; i < listOfValueAndConsumingInvocations.size(); i++) { + List<@NonNull Object> valueAndConsumingInvocations = listOfValueAndConsumingInvocations.get(i); + if ((valueAndConsumingInvocations != null) && (valueAndConsumingInvocations.get(VALUE_INDEX) == anElement)) { + listOfValueAndConsumingInvocations.set(i, null); + int jMax = valueAndConsumingInvocations.size(); + for (int j = INDEX_INDEX+1; j < jMax; j++) { + AbstractInvocation.Incremental consumingInvocation = (AbstractInvocation.Incremental) valueAndConsumingInvocations.get(j); + consumingInvocation.revokeExecution(); + } + break; + } + } + } + + /** * Replace the old value at connectionKey by newValue.The old value is removed, * its consumingInvocations are invalidated so that they recompute with the newValue which replaces the old. */ @@ -93,8 +113,8 @@ public class IncrementalConnectionInternal extends AbstractIncrementalConnection listOfValueAndConsumingInvocations.set(valueIndex, null); // Do not disrupt index equivalence. int iMax = valueAndConsumingInvocations.size(); for (int i = INDEX_INDEX+1; i < iMax; i++) { - AbstractInvocation consumingInvocation = (AbstractInvocation) valueAndConsumingInvocations.get(i); - consumingInvocation.revoke(); + AbstractInvocation.Incremental consumingInvocation = (AbstractInvocation.Incremental) valueAndConsumingInvocations.get(i); + consumingInvocation.revokeExecution(); } } }
\ No newline at end of file diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/IncrementalObjectManager.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/IncrementalObjectManager.java index cbcd0dedd..f4a43b0e5 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/IncrementalObjectManager.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/IncrementalObjectManager.java @@ -41,7 +41,8 @@ public class IncrementalObjectManager extends AbstractObjectManager { public enum SlotMode { ASSIGNABLE, // No assignment has been performed, object reads are blocked (collections reads may be unblocked) - ASSIGNED // Last assignment has been performed, reads are unblocked + ASSIGNED, // Last assignment has been performed, reads are unblocked + REASSIGNABLE, // No assignment has been performed by a re-execution, object reads are blocked (collections reads may be unblocked) } protected final @NonNull Object eObject; @@ -69,12 +70,20 @@ public class IncrementalObjectManager extends AbstractObjectManager case ASSIGNABLE: mode = SlotMode.ASSIGNED; unblock(objectManager); + this.value = ecoreValue; break; case ASSIGNED: System.out.println("Re-assignment of " + eFeature.getEContainingClass().getName() + "::" + eFeature.getName() + " for " + eObject + " with " + ecoreValue); break; + case REASSIGNABLE: + mode = SlotMode.ASSIGNED; + if (this.value != ecoreValue) { // FIXME equals() ?? + this.value = ecoreValue; + revokeTargets(); + } + unblock(objectManager); + break; } - this.value = ecoreValue; } @Override @@ -115,6 +124,7 @@ public class IncrementalObjectManager extends AbstractObjectManager public synchronized void getting( @NonNull Object eObject, @NonNull EStructuralFeature eFeature) { switch (mode) { case ASSIGNABLE: + case REASSIGNABLE: throw new InvocationFailedException(this); case ASSIGNED: break; @@ -126,6 +136,12 @@ public class IncrementalObjectManager extends AbstractObjectManager } @Override + public void revokeAssigned() { + assert isAssigned(); + mode = SlotMode.REASSIGNABLE; + } + + @Override public String toString() { return getClass().getSimpleName() + "@" + Integer.toHexString(System.identityHashCode(this)) + "[" + eFeature.getEContainingClass().getName() + "::" + eFeature.getName() + " for " + eObject + "]"; } @@ -416,6 +432,7 @@ public class IncrementalObjectManager extends AbstractObjectManager // super.assigned(objectManager, eContainer, eReference, eObject); switch (mode) { case ASSIGNABLE: + case REASSIGNABLE: mode = SlotMode.ASSIGNED; unblock(IncrementalObjectManager.this); break; @@ -428,6 +445,7 @@ public class IncrementalObjectManager extends AbstractObjectManager public synchronized void getting(@NonNull Object eObject, @NonNull EStructuralFeature eFeature) { switch (mode) { case ASSIGNABLE: + case REASSIGNABLE: mode = SlotMode.ASSIGNED; unblock(IncrementalObjectManager.this); break; @@ -836,4 +854,11 @@ public class IncrementalObjectManager extends AbstractObjectManager BasicSlotState slotState = getSlotState(eObject, eFeature); execution.addReadSlot(slotState); } + + public void modified(@NonNull Object eObject, @NonNull EStructuralFeature eFeature) { + BasicSlotState slotState = getSlotState(eObject, eFeature); + for (Execution.@NonNull Incremental execution : slotState.getTargets()) { + execution.revokeExecution(); + } + } }
\ No newline at end of file diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/ModificationMonitor.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/ModificationMonitor.java new file mode 100644 index 000000000..7b0274c3e --- /dev/null +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/ModificationMonitor.java @@ -0,0 +1,104 @@ +package org.eclipse.qvtd.runtime.internal.evaluation; + +import java.util.List; + +import org.eclipse.emf.common.notify.Adapter; +import org.eclipse.emf.common.notify.Notification; +import org.eclipse.emf.common.notify.Notifier; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.ocl.pivot.utilities.TreeIterable; +import org.eclipse.qvtd.runtime.evaluation.TransformationExecutor; + +/** + * An adapter implementation for tracking resource modification. + */ +public class ModificationMonitor implements Adapter +{ + public static @Nullable ModificationMonitor basicGetModificationMonitor(@NonNull Resource resource, @NonNull TransformationExecutor executor) { + for (Adapter eAdapter : resource.eAdapters()) { + if (eAdapter instanceof ModificationMonitor) { + ModificationMonitor monitor = (ModificationMonitor)eAdapter; + if (monitor.getExecutor() == executor) { + return monitor; + } + } + } + return null; + } + + public static @NonNull ModificationMonitor getModificationMonitor(@NonNull Resource resource, @NonNull TransformationExecutor executor) { + List<Adapter> eAdapters = resource.eAdapters(); + for (Adapter eAdapter : eAdapters) { + if (eAdapter instanceof ModificationMonitor) { + ModificationMonitor monitor = (ModificationMonitor)eAdapter; + if (monitor.getExecutor() == executor) { + return monitor; + } + } + } + ModificationMonitor monitor = new ModificationMonitor(resource, executor); + for (@NonNull EObject eObject : new TreeIterable(resource)) { + eObject.eAdapters().add(monitor); + } + eAdapters.add(monitor); + return monitor; + } + + private @NonNull Resource resource; + private @NonNull TransformationExecutor executor; + + public ModificationMonitor(@NonNull Resource resource, @NonNull TransformationExecutor executor) { + this.resource = resource; + this.executor = executor; + } + + public @NonNull TransformationExecutor getExecutor() { + return executor; + } + + @Override + public @NonNull Resource getTarget() { + return resource; + } + + @Override + public boolean isAdapterForType(Object type) { + return type == ModificationMonitor.class; + } + + @Override + public void notifyChanged(Notification notification) + { + if (!notification.isTouch()) + { + Object notifier = notification.getNotifier(); + assert notifier != null; + IncrementalObjectManager objectManager = (IncrementalObjectManager) executor.getTransformer().getObjectManager(); + switch (notification.getEventType()) { + case Notification.ADD: + case Notification.REMOVE: { + break; + } + case Notification.ADD_MANY: + case Notification.REMOVE_MANY: { + break; + } + case Notification.SET: + case Notification.UNSET: { + Object feature = notification.getFeature(); + if (feature instanceof EStructuralFeature) { + objectManager.modified(notifier, (EStructuralFeature)feature); + } + break; + } + } + } + } + + @Override + public void setTarget(Notifier newTarget) {} +} diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/StrictConnectionInternal.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/StrictConnectionInternal.java index 131889241..19ed2944d 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/StrictConnectionInternal.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/StrictConnectionInternal.java @@ -42,28 +42,28 @@ public abstract class StrictConnectionInternal extends AbstractConnectionInterna * connection manager to schedule a propagate() to consumers when convenient. */ @Override - public synchronized @NonNull Object append(@NonNull Object aValue) { + public synchronized @NonNull Object appendElement(@NonNull Object anElement) { if (debugAppends) { - AbstractTransformer.APPENDS.println(this + " <= " + LabelUtil.getLabel(aValue)); + AbstractTransformer.APPENDS.println(this + " <= " + LabelUtil.getLabel(anElement)); } if (uniqueValues != null) { - if (!uniqueValues.add(aValue)) { - return aValue; + if (!uniqueValues.add(anElement)) { + return anElement; } } else if (values.size() < 10) { for (@NonNull Object value : values) { - if (value.equals(aValue)) { // FIXME ==/oclEquals - return aValue; + if (value.equals(anElement)) { // FIXME ==/oclEquals + return anElement; } } } - else if (!createUniqueValues().add(aValue)) { - return aValue; + else if (!createUniqueValues().add(anElement)) { + return anElement; } - values.add(aValue); + values.add(anElement); queue(); - return aValue; + return anElement; } private @NonNull Set<@NonNull Object> createUniqueValues() { diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/StrictIncrementalConnectionInternal.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/StrictIncrementalConnectionInternal.java index 9eb2eef62..98ea08109 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/StrictIncrementalConnectionInternal.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/StrictIncrementalConnectionInternal.java @@ -42,22 +42,22 @@ public abstract class StrictIncrementalConnectionInternal extends AbstractIncrem } /** - * Append aValue to the contents, enforcing uniqueness if necessary, and waking up the overall + * Append anElement to the contents, enforcing uniqueness if necessary, and waking up the overall * connection manager to schedule a propagate() to consumers when convenient. */ @Override - public synchronized @NonNull Object append(@NonNull Object aValue) { + public synchronized @NonNull Object appendElement(@NonNull Object anElement) { if (debugAppends) { - AbstractTransformer.APPENDS.println(this + " <= " + LabelUtil.getLabel(aValue)); + AbstractTransformer.APPENDS.println(this + " <= " + LabelUtil.getLabel(anElement)); } - List<@NonNull Object> valueAndConsumingInvocations = uniqueValues2valueAndConsumingInvocations.get(aValue); + List<@NonNull Object> valueAndConsumingInvocations = uniqueValues2valueAndConsumingInvocations.get(anElement); if (valueAndConsumingInvocations == null) { valueAndConsumingInvocations = new ArrayList<>(); - valueAndConsumingInvocations.add(aValue); // VALUE_INDEX + valueAndConsumingInvocations.add(anElement); // VALUE_INDEX valueAndConsumingInvocations.add(listOfValueAndConsumingInvocations.size()); // INDEX_INDEX valueAndConsumingInvocations.add(1); // COUNT_INDEX listOfValueAndConsumingInvocations.add(valueAndConsumingInvocations); - uniqueValues2valueAndConsumingInvocations.put(aValue, valueAndConsumingInvocations); + uniqueValues2valueAndConsumingInvocations.put(anElement, valueAndConsumingInvocations); queue(); } else { @@ -95,7 +95,7 @@ public abstract class StrictIncrementalConnectionInternal extends AbstractIncrem Integer count = (Integer) valueAndConsumingInvocations.get(COUNT_INDEX); if (count > 1) { valueAndConsumingInvocations.set(COUNT_INDEX, count-1); - return append(newValue); + return appendElement(newValue); } valueAndConsumingInvocations.set(VALUE_INDEX, newValue); int iMax = valueAndConsumingInvocations.size(); @@ -127,8 +127,8 @@ public abstract class StrictIncrementalConnectionInternal extends AbstractIncrem listOfValueAndConsumingInvocations.set(valueIndex, null); // Do not disrupt index equivalence. int iMax = valueAndConsumingInvocations.size(); for (int i = COUNT_INDEX+1; i < iMax; i++) { - AbstractInvocation consumingInvocation = (AbstractInvocation) valueAndConsumingInvocations.get(i); - consumingInvocation.revoke(); + AbstractInvocation.Incremental consumingInvocation = (AbstractInvocation.Incremental) valueAndConsumingInvocations.get(i); + consumingInvocation.revokeExecution(); } } }
\ No newline at end of file diff --git a/tests/org.eclipse.qvtd.compiler.tests/src/org/eclipse/qvtd/compiler/tests/RuntimeConnectionTests.java b/tests/org.eclipse.qvtd.compiler.tests/src/org/eclipse/qvtd/compiler/tests/RuntimeConnectionTests.java index 245d97e49..0e2d45160 100644 --- a/tests/org.eclipse.qvtd.compiler.tests/src/org/eclipse/qvtd/compiler/tests/RuntimeConnectionTests.java +++ b/tests/org.eclipse.qvtd.compiler.tests/src/org/eclipse/qvtd/compiler/tests/RuntimeConnectionTests.java @@ -208,7 +208,7 @@ public class RuntimeConnectionTests extends TestCase } public void append() { - append(counter++); + appendElement(counter++); } } diff --git a/tests/org.eclipse.qvtd.xtext.qvtimperative.tests/src/org/eclipse/qvtd/xtext/qvtimperative/tests/QVTiCompilerTests.java b/tests/org.eclipse.qvtd.xtext.qvtimperative.tests/src/org/eclipse/qvtd/xtext/qvtimperative/tests/QVTiCompilerTests.java index 4f5579cff..91c95a62b 100644 --- a/tests/org.eclipse.qvtd.xtext.qvtimperative.tests/src/org/eclipse/qvtd/xtext/qvtimperative/tests/QVTiCompilerTests.java +++ b/tests/org.eclipse.qvtd.xtext.qvtimperative.tests/src/org/eclipse/qvtd/xtext/qvtimperative/tests/QVTiCompilerTests.java @@ -17,6 +17,8 @@ import java.util.Map; import org.eclipse.emf.codegen.ecore.genmodel.GenModel; import org.eclipse.emf.codegen.ecore.genmodel.GenModelPackage; import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EAttribute; +import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; @@ -31,6 +33,7 @@ import org.eclipse.ocl.pivot.oclstdlib.OCLstdlibTables; import org.eclipse.ocl.pivot.resource.ASResource; import org.eclipse.ocl.pivot.resource.ProjectManager; import org.eclipse.ocl.pivot.utilities.ClassUtil; +import org.eclipse.ocl.pivot.utilities.TreeIterable; import org.eclipse.ocl.pivot.validation.ComposedEValidator; import org.eclipse.ocl.xtext.base.services.BaseLinkingService; import org.eclipse.ocl.xtext.base.utilities.BaseCSResource; @@ -45,15 +48,15 @@ import org.eclipse.qvtd.pivot.qvtimperative.QVTimperativePackage; import org.eclipse.qvtd.pivot.qvtimperative.evaluation.Execution2GraphVisitor; import org.eclipse.qvtd.pivot.qvtimperative.evaluation.QVTiEnvironmentFactory; import org.eclipse.qvtd.pivot.qvtimperative.evaluation.QVTiTransformationExecutor; +import org.eclipse.qvtd.runtime.evaluation.TransformationExecutor; import org.eclipse.qvtd.runtime.evaluation.Transformer; +import org.eclipse.qvtd.runtime.internal.evaluation.ModificationMonitor; import org.eclipse.qvtd.xtext.qvtbase.tests.LoadTestCase; import org.eclipse.qvtd.xtext.qvtbase.tests.ModelNormalizer; import org.eclipse.qvtd.xtext.qvtbase.tests.utilities.TestsXMLUtil; import org.eclipse.qvtd.xtext.qvtimperative.tests.ManualUML2RDBMS.ManualRDBMSNormalizer; import org.eclipse.qvtd.xtext.qvtimperative.tests.SimpleUML2RDBMS.SimpleRDBMSNormalizer; -import org.eclipse.qvtd.xtext.qvtimperative.tests.Tree2TallTree.Tree2TallTreeInstallManual; -import cg_qvtimperative_tests._hsv2hls.hsv2hls; import junit.framework.TestCase; /** @@ -142,9 +145,10 @@ public class QVTiCompilerTests extends LoadTestCase return (QVTiEnvironmentFactory) super.getEnvironmentFactory(); } - public void loadInput(@NonNull Transformer tx, @NonNull String inputModelName, URI inputModelURI) { + public @NonNull Resource loadInput(@NonNull Transformer tx, @NonNull String inputModelName, URI inputModelURI) { Resource inputResource = getResourceSet().getResource(inputModelURI, true); tx.addRootObjects(inputModelName, ClassUtil.nonNullState(inputResource.getContents())); + return inputResource; } public @NonNull Transformation loadTransformation(@NonNull URI transformURI, @NonNull URI genModelURI) throws Exception { @@ -233,7 +237,7 @@ public class QVTiCompilerTests extends LoadTestCase myQVT.dispose(); } - public void testCG_HSV2HLS_qvti2() throws Exception { + /* public void testCG_HSV2HLS_qvti2() throws Exception { MyQVT myQVT = createQVT(); URI inputModelURI = getProjectFileURI("HSV2HLS/HSVNode.xmi"); URI outputModelURI = getProjectFileURI("HSV2HLS/HLSNode.xmi"); @@ -243,7 +247,7 @@ public class QVTiCompilerTests extends LoadTestCase tx.run(); myQVT.saveOutput(tx, "hls", outputModelURI, referenceModelURI, null); myQVT.dispose(); - } + } */ public void testCG_ClassesCS2AS_qvti() throws Exception { MyQVT myQVT = createQVT(); @@ -327,52 +331,88 @@ public class QVTiCompilerTests extends LoadTestCase URI transformURI = getProjectFileURI("Tree2TallTree/Tree2TallTree.qvti"); URI inputModelURI = getProjectFileURI("Tree2TallTree/Tree.xmi"); URI outputModelURI = getProjectFileURI("Tree2TallTree/Tree2TallTree.xmi"); + URI outputModelURI2 = getProjectFileURI("Tree2TallTree/Tree2TallTree2.xmi"); URI referenceModelURI = getProjectFileURI("Tree2TallTree/TallTreeValidate.xmi"); + URI referenceModelURI2 = getProjectFileURI("Tree2TallTree/TallTreeValidate2.xmi"); Transformation asTransformation = myQVT.loadTransformation(transformURI, genModelURI); Class<? extends Transformer> txClass = myQVT.generateCode(asTransformation, true); Transformer tx = myQVT.createTransformer(txClass); - myQVT.loadInput(tx, "tree", inputModelURI); + Resource inputResource = myQVT.loadInput(tx, "tree", inputModelURI); tx.run(); + Execution2GraphVisitor.writeGraphMLfile(tx, getProjectFileURI("Tree2TallTree/Tree2TallTree-inc.graphml")); myQVT.saveOutput(tx, "talltree", outputModelURI, referenceModelURI, null); + TransformationExecutor executor = tx.getExecutor(); + @SuppressWarnings("unused") ModificationMonitor monitor = ModificationMonitor.getModificationMonitor(inputResource, executor); + int gotOne = 0; + for (EObject eObject : new TreeIterable(inputResource)) { + EClass eClass = eObject.eClass(); + if ("Node".equals(eClass.getName())) { + EAttribute nameAttribute = (EAttribute) eClass.getEStructuralFeature("name"); + Object name = eObject.eGet(nameAttribute); + if ("n1.1".equals(name)) { + gotOne++; + eObject.eSet(nameAttribute, "x1.1"); + } + } + } + assert gotOne == 1; + executor.getTransformer().getInvocationManager().flush(); + Execution2GraphVisitor.writeGraphMLfile(tx, getProjectFileURI("Tree2TallTree/Tree2TallTree-inc2.graphml")); + myQVT.saveOutput(tx, "talltree", outputModelURI2, referenceModelURI2, null); myQVT.dispose(); } - public void testCG_Tree2TallTreeInstall_qvti() throws Exception { + /* public void testCG_Tree2TallTree_Incremental_qvti2() throws Exception { // AbstractTransformer.INVOCATIONS.setState(true); MyQVT myQVT = createQVT(); URI genModelURI = getProjectFileURI("Tree2TallTree/Tree2TallTree.genmodel"); - URI transformURI = getProjectFileURI("Tree2TallTree/Tree2TallTreeInstall.qvti"); - + URI transformURI = getProjectFileURI("Tree2TallTree/Tree2TallTree.qvti"); URI inputModelURI = getProjectFileURI("Tree2TallTree/Tree.xmi"); URI outputModelURI = getProjectFileURI("Tree2TallTree/Tree2TallTree.xmi"); + URI outputModelURI2 = getProjectFileURI("Tree2TallTree/Tree2TallTree2.xmi"); URI referenceModelURI = getProjectFileURI("Tree2TallTree/TallTreeValidate.xmi"); - Transformation asTransformation = myQVT.loadTransformation(transformURI, genModelURI); - Class<? extends Transformer> txClass = myQVT.generateCode(asTransformation, true); + URI referenceModelURI2 = getProjectFileURI("Tree2TallTree/TallTreeValidate2.xmi"); + Class<? extends Transformer> txClass = Tree2TallTree.class; Transformer tx = myQVT.createTransformer(txClass); - myQVT.loadInput(tx, "tree", inputModelURI); + Resource inputResource = myQVT.loadInput(tx, "tree", inputModelURI); tx.run(); + Execution2GraphVisitor.writeGraphMLfile(tx, getProjectFileURI("Tree2TallTree/Tree2TallTree-inc.graphml")); myQVT.saveOutput(tx, "talltree", outputModelURI, referenceModelURI, null); + TransformationExecutor executor = tx.getExecutor(); + ModificationMonitor monitor = ModificationMonitor.getModificationMonitor(inputResource, executor); + int gotOne = 0; + for (EObject eObject : new TreeIterable(inputResource)) { + EClass eClass = eObject.eClass(); + if ("Node".equals(eClass.getName())) { + EAttribute nameAttribute = (EAttribute) eClass.getEStructuralFeature("name"); + Object name = eObject.eGet(nameAttribute); + if ("n1.1".equals(name)) { + gotOne++; + eObject.eSet(nameAttribute, "x1.1"); + } + } + } + assert gotOne == 1; + executor.getTransformer().getInvocationManager().flush(); + Execution2GraphVisitor.writeGraphMLfile(tx, getProjectFileURI("Tree2TallTree/Tree2TallTree-inc2.graphml")); + myQVT.saveOutput(tx, "talltree", outputModelURI2, referenceModelURI2, null); myQVT.dispose(); - } + } */ - public void testCG_Tree2TallTreeInstallManual_qvti() throws Exception { - // AbstractTransformer.APPENDS.setState(true); - // AbstractTransformer.CONSUMES.setState(true); - // AbstractTransformer.EXCEPTIONS.setState(true); + public void testCG_Tree2TallTreeInstall_qvti() throws Exception { // AbstractTransformer.INVOCATIONS.setState(true); MyQVT myQVT = createQVT(); - // URI genModelURI = getProjectFileURI("Tree2TallTree/Tree2TallTree.genmodel"); - // URI transformURI = getProjectFileURI("Tree2TallTree/Tree2TallTreeInstall.qvti"); + URI genModelURI = getProjectFileURI("Tree2TallTree/Tree2TallTree.genmodel"); + URI transformURI = getProjectFileURI("Tree2TallTree/Tree2TallTreeInstall.qvti"); URI inputModelURI = getProjectFileURI("Tree2TallTree/Tree.xmi"); URI outputModelURI = getProjectFileURI("Tree2TallTree/Tree2TallTree.xmi"); URI referenceModelURI = getProjectFileURI("Tree2TallTree/TallTreeValidate.xmi"); - // Transformation asTransformation = myQVT.loadTransformation(transformURI, genModelURI); - Class<? extends Transformer> txClass = Tree2TallTreeInstallManual.class; + Transformation asTransformation = myQVT.loadTransformation(transformURI, genModelURI); + Class<? extends Transformer> txClass = myQVT.generateCode(asTransformation, true); Transformer tx = myQVT.createTransformer(txClass); myQVT.loadInput(tx, "tree", inputModelURI); tx.run(); - Execution2GraphVisitor.writeGraphMLfile(tx, getProjectFileURI("Tree2TallTree/Tree2TallTreeInstallManual-execution.graphml")); myQVT.saveOutput(tx, "talltree", outputModelURI, referenceModelURI, null); myQVT.dispose(); } diff --git a/tests/org.eclipse.qvtd.xtext.qvtimperative.tests/src/org/eclipse/qvtd/xtext/qvtimperative/tests/RuntimeConnectionTests.java b/tests/org.eclipse.qvtd.xtext.qvtimperative.tests/src/org/eclipse/qvtd/xtext/qvtimperative/tests/RuntimeConnectionTests.java new file mode 100644 index 000000000..11aa0c7ab --- /dev/null +++ b/tests/org.eclipse.qvtd.xtext.qvtimperative.tests/src/org/eclipse/qvtd/xtext/qvtimperative/tests/RuntimeConnectionTests.java @@ -0,0 +1,385 @@ +/******************************************************************************* + * Copyright (c) 2016 Willink Transformations and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * E.D.Willink - initial API and implementation + *******************************************************************************/ +package org.eclipse.qvtd.xtext.qvtimperative.tests; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.ocl.pivot.evaluation.Executor; +import org.eclipse.ocl.pivot.evaluation.ModelManager; +import org.eclipse.ocl.pivot.ids.TypeId; +import org.eclipse.ocl.pivot.internal.evaluation.AbstractExecutor; +import org.eclipse.ocl.pivot.internal.utilities.EnvironmentFactoryInternal.EnvironmentFactoryInternalExtension; +import org.eclipse.ocl.pivot.utilities.EnvironmentFactory; +import org.eclipse.ocl.pivot.utilities.OCL; +import org.eclipse.qvtd.pivot.qvtimperative.evaluation.AbstractInterpretedInvocation; +import org.eclipse.qvtd.runtime.evaluation.Interval; +import org.eclipse.qvtd.runtime.evaluation.Invocation; +import org.eclipse.qvtd.runtime.evaluation.InvocationFailedException; +import org.eclipse.qvtd.runtime.evaluation.InvocationManager; +import org.eclipse.qvtd.runtime.evaluation.SimpleConnection; +import org.eclipse.qvtd.runtime.internal.evaluation.AbstractInvocationConstructor; +import org.eclipse.qvtd.runtime.internal.evaluation.AbstractInvocationManagerInternal; +import org.junit.Test; + +import junit.framework.TestCase; + + +public class RuntimeConnectionTests extends TestCase +{ + public static final class Tester + { + protected final @NonNull OCL ocl; + protected final @NonNull TestExecutor executor; + protected final @NonNull TestInvocationManager invocationManager; + protected final @NonNull TestInvocationConstructor invocationConstructor; + protected final @NonNull List<@NonNull TestConnection> testConnections = new ArrayList<>(); + + public Tester() { + ocl = OCL.newInstance(); + executor = new TestExecutor(ocl.getEnvironmentFactory()); + invocationManager = new TestInvocationManager(executor); + invocationConstructor = new TestInvocationConstructor(invocationManager, "name", false); + } + + public void addConsumedConnection(@NonNull TestConnection testConnection) { + invocationConstructor.addConsumedConnection(testConnection); + testConnections.add(testConnection); + } + + public void check() { + StringBuilder s = new StringBuilder(); + check(0, "9", s); + check(s.toString()); + } + + private void check(int connectionIndex, @NonNull String partialString, @NonNull StringBuilder s) { + if (connectionIndex < testConnections.size()) { + for (int i = 0; i < testConnections.get(connectionIndex).counter; i++) { + check(connectionIndex+1, partialString + i, s); + } + } + else { + if (s.length() > 0) { + s.append(","); + } + s.append(partialString); + } + } + + public void check(@Nullable String stringValue) { + invocationManager.flush(); + if (stringValue != null) { + assertEquals(stringValue, invocationConstructor.stringValue()); + } + int product = 1; + for (@NonNull TestConnection testConnection : testConnections) { + product *= testConnection.counter; + } + TestCase.assertEquals(product, invocationConstructor.allValues.size()); + @NonNull Object[] values = new @NonNull Object[testConnections.size()]; + invocationConstructor.check(0, values, testConnections); + } + + public @NonNull TestConnection createConsumedConnection() { + String name = "connection" + testConnections.size(); + TestConnection testConnection = new TestConnection(invocationManager.getRootInterval(), name, TypeId.INTEGER); + addConsumedConnection(testConnection); + return testConnection; + } + + public void dispose() { + ocl.dispose(); + } + + public @NonNull TestInvocationConstructor getInvocationConstructor() { + return invocationConstructor; + } + } + + public static final class TestExecutor extends AbstractExecutor + { + public TestExecutor(@NonNull EnvironmentFactory environmentFactory) { + super((@NonNull EnvironmentFactoryInternalExtension) environmentFactory); + } + + @Override + public @NonNull ModelManager getModelManager() { + throw new UnsupportedOperationException(); + } + } + + public static final class TestInvocationManager extends AbstractInvocationManagerInternal + { + public TestInvocationManager(@NonNull Executor executor) { + super(executor); + } + } + + public static final class TestInvocationConstructor extends AbstractInvocationConstructor + { + protected final @NonNull Set<@NonNull Integer> allValues = new HashSet<>(); + + public TestInvocationConstructor(@NonNull InvocationManager invocationManager, @NonNull String name, boolean isStrict) { + super(invocationManager, name, isStrict); + } + + public void executed(@NonNull Object @NonNull [] values) { + int intValue = compositeValue(values); + boolean wasAdded = allValues.add(intValue); + TestCase.assertTrue(wasAdded); + } + + public void check(int consumerIndex, @NonNull Object @NonNull [] values, @NonNull List<@NonNull TestConnection> testConnections) { + if (consumerIndex >= testConnections.size()) { + int intValue = compositeValue(values); + TestCase.assertTrue(allValues.contains(intValue)); + } + else { + for (int i = 0; i < testConnections.get(consumerIndex).counter; i++) { + values[consumerIndex] = i; + check(consumerIndex+1, values, testConnections); + } + } + } + + private int compositeValue(@NonNull Object @NonNull [] values) { + int intValue = 9; + for (@NonNull Object value : values) { + intValue = 10 * intValue + ((Integer)value).intValue(); + } + return intValue; + } + + @Override + public @NonNull Invocation newInstance(@NonNull Object @NonNull [] values) { + return new TestInvocation(this, values); + } + + public @NonNull String stringValue() { + List<@NonNull Integer> intValues = new ArrayList<>(allValues); + Collections.sort(intValues); + StringBuilder s = new StringBuilder(); + for (int i = 0; i < intValues.size(); i++) { + if (i != 0) { + s.append(","); + } + s.append(intValues.get(i)); + } + return s.toString(); + } + } + + public static final class TestInvocation extends AbstractInterpretedInvocation + { + protected final @NonNull TestInvocationConstructor invocationConstructor; + + public TestInvocation(@NonNull TestInvocationConstructor invocationConstructor, @NonNull Object @NonNull [] values) { + super(invocationConstructor, values); + this.invocationConstructor = invocationConstructor; + } + + @Override + public boolean execute() throws InvocationFailedException { + invocationConstructor.executed(values); + return false; + } + } + + public static final class TestConnection extends SimpleConnection + { + private Integer counter = 0; + + public TestConnection(@NonNull Interval interval, @NonNull String name, @NonNull TypeId typeId) { + super(interval, name, typeId); + } + + public void append() { + appendElement(counter++); + } + } + + @Test + public void testRuntime_DoubleSimpleConnection() { + Tester tester = new Tester(); + TestConnection connection0 = tester.createConsumedConnection(); + TestConnection connection1 = tester.createConsumedConnection(); + // + tester.check(""); + // + tester.check(""); + // + connection0.append(); + tester.check(""); + // + connection1.append(); + tester.check("900"); + // + tester.check("900"); + // + connection1.append(); + tester.check("900,901"); + // + connection1.append(); + tester.check("900,901,902"); + // + connection0.append(); + tester.check("900,901,902,910,911,912"); + // + connection1.append(); + tester.check("900,901,902,903,910,911,912,913"); + // + connection0.append(); + connection0.append(); + connection0.append(); + tester.check(); + // + connection1.append(); + connection1.append(); + tester.check(); + // + tester.check(); + // + tester.dispose(); + } + + @Test + public void testRuntime_RedundantDoubleSimpleConnection() { + Tester tester = new Tester(); + TestConnection connection0 = tester.createConsumedConnection(); + tester.addConsumedConnection(connection0); + // + tester.check(""); + // + tester.check(""); + // + connection0.append(); + tester.check("900"); + // + tester.check("900"); + // + connection0.append(); + tester.check("900,901,910,911"); + // + connection0.append(); + tester.check("900,901,902,910,911,912,920,921,922"); + // + connection0.append(); + tester.check(); + // + connection0.append(); + tester.check(); + // + connection0.append(); + connection0.append(); + connection0.append(); + tester.check(); + // + connection0.append(); + connection0.append(); + tester.check(); + // + tester.check(); + // + tester.dispose(); + } + + @Test + public void testRuntime_SingleSimpleConnection() { + Tester tester = new Tester(); + TestConnection connection0 = tester.createConsumedConnection(); + // + tester.check(""); + // + tester.check(""); + // + connection0.append(); + tester.check("90"); + // + tester.check("90"); + // + connection0.append(); + connection0.append(); + tester.check("90,91,92"); + // + connection0.append(); + tester.check("90,91,92,93"); + // + connection0.append(); + connection0.append(); + connection0.append(); + tester.check("90,91,92,93,94,95,96"); + // + tester.check(); + // + tester.dispose(); + } + + @Test + public void testRuntime_TripleSimpleConnection() { + Tester tester = new Tester(); + TestConnection connection0 = tester.createConsumedConnection(); + TestConnection connection1 = tester.createConsumedConnection(); + TestConnection connection2 = tester.createConsumedConnection(); + // + tester.check(""); + // + tester.check(""); + // + connection0.append(); + tester.check(""); + // + connection1.append(); + tester.check(""); + // + connection2.append(); + tester.check("9000"); + // + tester.check("9000"); + // + connection1.append(); + tester.check("9000,9010"); + // + connection1.append(); + tester.check("9000,9010,9020"); + // + connection0.append(); + tester.check("9000,9010,9020,9100,9110,9120"); + // + connection2.append(); + tester.check("9000,9001,9010,9011,9020,9021,9100,9101,9110,9111,9120,9121"); + // + connection0.append(); + connection1.append(); + connection0.append(); + tester.check(); + // + connection1.append(); + connection1.append(); + tester.check(); + // + connection2.append(); + connection2.append(); + tester.check(); + // + connection0.append(); + tester.check(); + // + tester.check(); + // + tester.dispose(); + } +} diff --git a/tests/org.eclipse.qvtd.xtext.qvtimperative.tests/src/org/eclipse/qvtd/xtext/qvtimperative/tests/Tree2TallTree/TallTreeValidate2.xmi b/tests/org.eclipse.qvtd.xtext.qvtimperative.tests/src/org/eclipse/qvtd/xtext/qvtimperative/tests/Tree2TallTree/TallTreeValidate2.xmi new file mode 100644 index 000000000..8f3351492 --- /dev/null +++ b/tests/org.eclipse.qvtd.xtext.qvtimperative.tests/src/org/eclipse/qvtd/xtext/qvtimperative/tests/Tree2TallTree/TallTreeValidate2.xmi @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="ASCII"?>
+<talltree:TallNode
+ xmi:version="2.0"
+ xmlns:xmi="http://www.omg.org/XMI"
+ xmlns:talltree="http://www.eclipse.org/qvt/examples/0.1/TallTree"
+ xsi:schemaLocation="http://www.eclipse.org/qvt/examples/0.1/TallTree TallTree.ecore"
+ height="2"
+ name="n1">
+ <children
+ height="1"
+ name="x1.1">
+ <children
+ height="0"
+ name="n1.1.1"/>
+ </children>
+</talltree:TallNode>
diff --git a/tests/org.eclipse.qvtd.xtext.qvtimperative.tests/src/org/eclipse/qvtd/xtext/qvtimperative/tests/Tree2TallTree/Tree2TallTree.qvti b/tests/org.eclipse.qvtd.xtext.qvtimperative.tests/src/org/eclipse/qvtd/xtext/qvtimperative/tests/Tree2TallTree/Tree2TallTree.qvti index 62ef003b6..e9e043b25 100644 --- a/tests/org.eclipse.qvtd.xtext.qvtimperative.tests/src/org/eclipse/qvtd/xtext/qvtimperative/tests/Tree2TallTree/Tree2TallTree.qvti +++ b/tests/org.eclipse.qvtd.xtext.qvtimperative.tests/src/org/eclipse/qvtd/xtext/qvtimperative/tests/Tree2TallTree/Tree2TallTree.qvti @@ -9,7 +9,8 @@ transformation Tree2TallTree { } map __root__ in Tree2TallTree { - buffer nodes := tree.objectsOfKind(Node)->sortedBy(name); +-- buffer nodes := tree.objectsOfKind(Node)->sortedBy(name); + buffer nodes := tree.objectsOfKind(Node); for node : tree::Node in nodes { call Node2MiddleNode { node iterates node; @@ -20,7 +21,8 @@ map __root__ in Tree2TallTree { node iterates node; } } - for node2tallNode : tree2talltree::Node2TallNode in tree2talltree.objectsOfKind(Node2TallNode)->sortedBy(name) { +-- for node2tallNode : tree2talltree::Node2TallNode in tree2talltree.objectsOfKind(Node2TallNode)->sortedBy(name) { + for node2tallNode : tree2talltree::Node2TallNode in tree2talltree.objectsOfKind(Node2TallNode) { call MiddleNode2TallNode { node2tallNode iterates node2tallNode; } diff --git a/tests/org.eclipse.qvtd.xtext.qvtimperative.tests/src/org/eclipse/qvtd/xtext/qvtimperative/tests/Tree2TallTree/Tree2TallTreeInstallManual.java b/tests/org.eclipse.qvtd.xtext.qvtimperative.tests/src/org/eclipse/qvtd/xtext/qvtimperative/tests/Tree2TallTree/Tree2TallTreeInstallManual.java deleted file mode 100644 index 576b59e54..000000000 --- a/tests/org.eclipse.qvtd.xtext.qvtimperative.tests/src/org/eclipse/qvtd/xtext/qvtimperative/tests/Tree2TallTree/Tree2TallTreeInstallManual.java +++ /dev/null @@ -1,504 +0,0 @@ -/******************************************************************************* - * «codeGenHelper.getCopyright(' * ')» - * - * This code is 100% auto-generated - * using: org.eclipse.qvtd.codegen.qvti.java.QVTiCodeGenerator - * - * Do not edit it. - ********************************************************************************/ - -package org.eclipse.qvtd.xtext.qvtimperative.tests.Tree2TallTree; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.eclipse.emf.ecore.EcorePackage; -import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.ocl.pivot.StandardLibrary; -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.DataTypeId; -import org.eclipse.ocl.pivot.ids.IdManager; -import org.eclipse.ocl.pivot.ids.IdResolver; -import org.eclipse.ocl.pivot.ids.NsURIPackageId; -import org.eclipse.ocl.pivot.ids.RootPackageId; -import org.eclipse.ocl.pivot.ids.TypeId; -import org.eclipse.ocl.pivot.internal.library.executor.ExecutorSingleIterationManager; -import org.eclipse.ocl.pivot.library.AbstractBinaryOperation; -import org.eclipse.ocl.pivot.library.LibraryIteration; -import org.eclipse.ocl.pivot.library.collection.CollectionAsSetOperation; -import org.eclipse.ocl.pivot.library.collection.CollectionExcludingOperation; -import org.eclipse.ocl.pivot.library.collection.CollectionMaxOperation; -import org.eclipse.ocl.pivot.library.collection.CollectionNotEmptyOperation; -import org.eclipse.ocl.pivot.library.numeric.NumericPlusOperation; -import org.eclipse.ocl.pivot.oclstdlib.OCLstdlibTables; -import org.eclipse.ocl.pivot.utilities.ClassUtil; -import org.eclipse.ocl.pivot.utilities.ValueUtil; -import org.eclipse.ocl.pivot.values.BagValue; -import org.eclipse.ocl.pivot.values.IntegerValue; -import org.eclipse.ocl.pivot.values.InvalidValueException; -import org.eclipse.ocl.pivot.values.OrderedSetValue; -import org.eclipse.ocl.pivot.values.SetValue; -import org.eclipse.qvtd.runtime.evaluation.AbstractInvocation; -import org.eclipse.qvtd.runtime.evaluation.AbstractTransformer; -import org.eclipse.qvtd.runtime.evaluation.Connection; -import org.eclipse.qvtd.runtime.evaluation.InvocationConstructor; -import org.eclipse.qvtd.runtime.evaluation.InvocationManager; -import org.eclipse.qvtd.runtime.evaluation.ObjectManager; -import org.eclipse.qvtd.runtime.evaluation.TransformationExecutor; -import org.eclipse.qvtd.runtime.internal.evaluation.AbstractInvocationConstructor; -import org.eclipse.qvtd.runtime.internal.evaluation.IncrementalInvocationManager; -import org.eclipse.qvtd.runtime.internal.evaluation.IncrementalObjectManager; -import org.eclipse.qvtd.runtime.library.model.ModelObjectsOfKindOperation; - -import tree2talltree.talltree.TallNode; -import tree2talltree.talltree.TalltreeFactory; -import tree2talltree.talltree.TalltreePackage; -import tree2talltree.tree.Node; -import tree2talltree.tree.TreePackage; -import tree2talltree.tree2talltree.Node2TallNode; -import tree2talltree.tree2talltree.Tree2talltreeFactory; -import tree2talltree.tree2talltree.Tree2talltreePackage; - -/** - * The Tree2TallTreeInstall transformation: - * <p> - * Construct with an evaluator - * <br> - * Populate each input model with {@link addRootObjects(String,List)} - * <br> - * {@link run()} - * <br> - * Extract each output model with {@link getRootObjects(String)} - */ -@SuppressWarnings("nls") -public class Tree2TallTreeInstallManual extends AbstractTransformer -{ - public static final /*@NonInvalid*/ @NonNull RootPackageId PACKid_$metamodel$ = IdManager.getRootPackageId("$metamodel$"); - public static final /*@NonInvalid*/ @NonNull NsURIPackageId PACKid_http_c_s_s_www_eclipse_org_s_emf_s_2002_s_Ecore = IdManager.getNsURIPackageId("http://www.eclipse.org/emf/2002/Ecore", null, EcorePackage.eINSTANCE); - public static final /*@NonInvalid*/ @NonNull NsURIPackageId PACKid_http_c_s_s_www_eclipse_org_s_qvt_s_2015_s_QVTbaseLibrary = IdManager.getNsURIPackageId("http://www.eclipse.org/qvt/2015/QVTbaseLibrary", "qvtbaselib", null); - public static final /*@NonInvalid*/ @NonNull NsURIPackageId PACKid_http_c_s_s_www_eclipse_org_s_qvt_s_examples_s_0_1_s_List2List = IdManager.getNsURIPackageId("http://www.eclipse.org/qvt/examples/0.1/List2List", null, Tree2talltreePackage.eINSTANCE); - public static final /*@NonInvalid*/ @NonNull NsURIPackageId PACKid_http_c_s_s_www_eclipse_org_s_qvt_s_examples_s_0_1_s_TallTree = IdManager.getNsURIPackageId("http://www.eclipse.org/qvt/examples/0.1/TallTree", null, TalltreePackage.eINSTANCE); - public static final /*@NonInvalid*/ @NonNull NsURIPackageId PACKid_http_c_s_s_www_eclipse_org_s_qvt_s_examples_s_0_1_s_Tree = IdManager.getNsURIPackageId("http://www.eclipse.org/qvt/examples/0.1/Tree", null, TreePackage.eINSTANCE); - public static final /*@NonInvalid*/ @NonNull ClassId CLSSid_Class = PACKid_$metamodel$.getClassId("Class", 0); - public static final /*@NonInvalid*/ @NonNull ClassId CLSSid_Model = PACKid_http_c_s_s_www_eclipse_org_s_qvt_s_2015_s_QVTbaseLibrary.getClassId("Model", 0); - public static final /*@NonInvalid*/ @NonNull ClassId CLSSid_Node = PACKid_http_c_s_s_www_eclipse_org_s_qvt_s_examples_s_0_1_s_Tree.getClassId("Node", 0); - public static final /*@NonInvalid*/ @NonNull ClassId CLSSid_Node2TallNode = PACKid_http_c_s_s_www_eclipse_org_s_qvt_s_examples_s_0_1_s_List2List.getClassId("Node2TallNode", 0); - public static final /*@NonInvalid*/ @NonNull ClassId CLSSid_TallNode = PACKid_http_c_s_s_www_eclipse_org_s_qvt_s_examples_s_0_1_s_TallTree.getClassId("TallNode", 0); - public static final /*@NonInvalid*/ @NonNull DataTypeId DATAid_EInt = PACKid_http_c_s_s_www_eclipse_org_s_emf_s_2002_s_Ecore.getDataTypeId("EInt", 0); - public static final /*@NonInvalid*/ @NonNull IntegerValue INT_0 = ValueUtil.integerValueOf("0"); - public static final /*@NonInvalid*/ @NonNull IntegerValue INT_1 = ValueUtil.integerValueOf("1"); - public static final /*@NonInvalid*/ @NonNull CollectionTypeId BAG_CLSSid_TallNode = TypeId.BAG.getSpecializedId(CLSSid_TallNode); - public static final /*@NonInvalid*/ @NonNull CollectionTypeId BAG_DATAid_EInt = TypeId.BAG.getSpecializedId(DATAid_EInt); - public static final /*@NonInvalid*/ @NonNull CollectionTypeId ORD_CLSSid_Node = TypeId.ORDERED_SET.getSpecializedId(CLSSid_Node); - public static final /*@NonInvalid*/ @NonNull CollectionTypeId SEQ_CLSSid_Node2TallNode = TypeId.SEQUENCE.getSpecializedId(CLSSid_Node2TallNode); - public static final /*@NonInvalid*/ @NonNull CollectionTypeId SET_CLSSid_Node = TypeId.SET.getSpecializedId(CLSSid_Node); - public static final /*@NonInvalid*/ @NonNull CollectionTypeId SET_CLSSid_Node2TallNode = TypeId.SET.getSpecializedId(CLSSid_Node2TallNode); - public static final /*@NonInvalid*/ @NonNull CollectionTypeId SET_CLSSid_TallNode = TypeId.SET.getSpecializedId(CLSSid_TallNode); - - /* - * Property-source to Property-target unnavigable navigation caches - */ - protected final @NonNull Map<Node,Node2TallNode> OPPOSITE_OF_Node2TallNode_node = new HashMap<Node,Node2TallNode>(); - - /* - * Array of the ClassIds of each class for which allInstances() may be invoked. Array index is the ClassIndex. - */ - private static final @NonNull ClassId[] classIndex2classId = new @NonNull ClassId[]{ - CLSSid_Node // 0 => Node - }; - - /* - * Mapping from each ClassIndex to all the ClassIndexes to which an object of the outer index - * may contribute results to an allInstances() invocation. - * Non trivial inner arrays arise when one ClassId is a derivation of another and so an - * instance of the derived classId contributes to derived and inherited ClassIndexes. - */ - private final static int @NonNull [] @NonNull [] classIndex2allClassIndexes = new int @NonNull [] @NonNull [] { - {0} // 0 : Node -> {Node} - }; - - protected final AbstractInvocationConstructor.@NonNull Incremental CTOR_Root = new AbstractInvocationConstructor.Incremental(invocationManager, "__root__", false) - { - @Override - public @NonNull MAP___root__ newInstance(@NonNull Object @NonNull [] values) { - return new MAP___root__(this, values); - } - }; - - protected final AbstractInvocationConstructor.@NonNull Incremental CTOR_Node2MiddleNode = new AbstractInvocationConstructor.Incremental(invocationManager, "Node2MiddleNode", false) - { - @Override - public @NonNull MAP_Node2MiddleNode newInstance(@NonNull Object @NonNull [] values) { - return new MAP_Node2MiddleNode(this, values); - } - }; - - protected final AbstractInvocationConstructor.@NonNull Incremental CTOR_Edge2MiddleEdge = new AbstractInvocationConstructor.Incremental(invocationManager, "Edge2MiddleEdge", false) - { - @Override - public @NonNull MAP_Edge2MiddleEdge newInstance(@NonNull Object @NonNull [] values) { - return new MAP_Edge2MiddleEdge(this, values); - } - }; - - protected final AbstractInvocationConstructor.@NonNull Incremental CTOR_MiddleNode2TallNode = new AbstractInvocationConstructor.Incremental(invocationManager, "MiddleNode2TallNode", false) - { - @Override - public @NonNull MAP_MiddleNode2TallNode newInstance(@NonNull Object @NonNull [] values) { - return new MAP_MiddleNode2TallNode(this, values); - } - }; - - public Tree2TallTreeInstallManual(final @NonNull TransformationExecutor executor) { - super(executor, new @NonNull String[] {"tree", "talltree", "tree2talltree"}, null, classIndex2classId, classIndex2allClassIndexes); - } - - @Override - protected @NonNull InvocationManager createInvocationManager() { - return new IncrementalInvocationManager(executor); - } - - @Override - protected @NonNull ObjectManager createObjectManager() { - return new IncrementalObjectManager((IncrementalInvocationManager)invocationManager); - } - - @Override - public boolean run() { - // CTOR_Root.connect(null, null); - CTOR_Root.invoke(); - // invocationManager.setWorkToDoAt(0); - return invocationManager.flush(); - } - - /** - * - * map __root__ in Tree2TallTreeInstall { - * - * nodes : OrderedSet(tree::Node)node2tallNodes : Sequence(tree2talltree::Node2TallNode)install Node2MiddleNode { - * node consumes nodes : OrderedSet(tree::Node); - * node2tallNodes appendsTo node2tallNodes; - * } - * install Edge2MiddleEdge { - * node consumes nodes : OrderedSet(tree::Node); - * } - * install MiddleNode2TallNode { - * node2tallNode consumes node2tallNodes : Sequence(tree2talltree::Node2TallNode); - * } - */ - protected class MAP___root__ extends AbstractInvocation.Incremental - { - public MAP___root__(InvocationConstructor.@NonNull Incremental constructor, @NonNull Object @NonNull [] boundValues) { - super(constructor); - } - - @Override - public boolean execute() { - try { - final /*@NonInvalid*/ @NonNull IdResolver idResolver = executor.getIdResolver(); - final /*@NonInvalid*/ org.eclipse.ocl.pivot.@NonNull Class TYP_tree_c_c_Node_0 = idResolver.getClass(CLSSid_Node, null); - final /*@NonInvalid*/ @NonNull StandardLibrary standardLibrary = idResolver.getStandardLibrary(); - // connection variables - final @NonNull Connection nodes = createConnection("nodes", ORD_CLSSid_Node, false); - final /*@NonInvalid*/ @NonNull SetValue objectsOfKind = ModelObjectsOfKindOperation.INSTANCE.evaluate(executor, SET_CLSSid_Node, models[0/*tree*/], TYP_tree_c_c_Node_0); - final org.eclipse.ocl.pivot.@NonNull Class TYPE_sortedBy_0 = executor.getStaticTypeOf(objectsOfKind); - final LibraryIteration.@NonNull LibraryIterationExtension IMPL_sortedBy_0 = (LibraryIteration.LibraryIterationExtension)TYPE_sortedBy_0.lookupImplementation(standardLibrary, OCLstdlibTables.Operations._Set__sortedBy); - final @NonNull Object ACC_sortedBy_0 = IMPL_sortedBy_0.createAccumulatorValue(executor, ORD_CLSSid_Node, TypeId.STRING); - /** - * Implementation of the iterator body. - */ - final @NonNull AbstractBinaryOperation BODY_sortedBy_0 = new AbstractBinaryOperation() - { - /** - * name - */ - @Override - public @Nullable Object evaluate(final @NonNull Executor executor, final @NonNull TypeId typeId, final @Nullable Object objectsOfKind, final /*@NonInvalid*/ @Nullable Object _1) { - final /*@NonInvalid*/ @Nullable Node symbol_4 = (Node)_1; - if (symbol_4 == null) { - throw new InvalidValueException("Null source for \'\'http://www.eclipse.org/qvt/examples/0.1/Tree\'::Node::name\'"); - } - @SuppressWarnings("null") - final /*@Thrown*/ @NonNull String name = symbol_4.getName(); - objectManager.got(MAP___root__.this, symbol_4, TreePackage.Literals.NODE__NAME, name); - return name; - } - }; - final @NonNull ExecutorSingleIterationManager MGR_sortedBy_0 = new ExecutorSingleIterationManager(executor, ORD_CLSSid_Node, BODY_sortedBy_0, objectsOfKind, ACC_sortedBy_0); - final /*@Thrown*/ @NonNull OrderedSetValue sortedBy = ClassUtil.nonNullState((OrderedSetValue)IMPL_sortedBy_0.evaluateIteration(MGR_sortedBy_0)); - for (@NonNull Node iterator : ValueUtil.typedIterable(Node.class, sortedBy)) { - nodes.append(iterator); - } - final Connection.@NonNull Incremental node2tallNodes_1 = createIncrementalConnection("node2tallNodes_1", SEQ_CLSSid_Node2TallNode, false); - // mapping statements - CTOR_Node2MiddleNode.addConsumedConnection(nodes); - CTOR_Node2MiddleNode.addAppendedConnection(node2tallNodes_1); - CTOR_Edge2MiddleEdge.addConsumedConnection(nodes); - CTOR_MiddleNode2TallNode.addConsumedConnection(node2tallNodes_1); - final /*@Thrown*/ @Nullable Boolean __root__ = ValueUtil.TRUE_VALUE; - return __root__; - } catch (Throwable e) { - return handleExecutionFailure("MAP___root__", e); - } - } - - @Override - public boolean isEqual(@NonNull IdResolver idResolver, @NonNull Object @NonNull [] thoseValues) { - return true; - } - } - - /** - * - * map Node2MiddleNode in Tree2TallTreeInstall { - * guard:tree node : tree::Node[?]; - * append node2tallNodes : Sequence(tree2talltree::Node2TallNode); - * new:tree2talltree node2tallNode : tree2talltree::Node2TallNode[?]; - * set node2tallNode.node := node; - * set node2tallNode.name := node.name; - * add node2tallNodes += node2tallNode; - * - */ - protected class MAP_Node2MiddleNode extends AbstractInvocation.Incremental - { - protected final /*@NonInvalid*/ @NonNull Node node; - protected final @NonNull Connection node2tallNodes; - - public MAP_Node2MiddleNode(InvocationConstructor.@NonNull Incremental constructor, @NonNull Object @NonNull [] boundValues) { - super(constructor); - node = (Node)boundValues[0]; - node2tallNodes = (Connection)boundValues[1]; - } - - @Override - public boolean execute() { - try { - // creations - final /*@Thrown*/ @Nullable Node2TallNode node2tallNode_0 = Tree2talltreeFactory.eINSTANCE.createNode2TallNode(); - assert node2tallNode_0 != null; - models[2/*tree2talltree*/].add(node2tallNode_0); - objectManager.created(this, node2tallNode_0); - // mapping statements - OPPOSITE_OF_Node2TallNode_node.put(node, node2tallNode_0); - node2tallNode_0.setNode(node); - objectManager.assigned(this, node2tallNode_0, Tree2talltreePackage.Literals.NODE2_TALL_NODE__NODE, node, null); - @SuppressWarnings("null") - final /*@Thrown*/ @NonNull String name = node.getName(); - objectManager.got(this, node, TreePackage.Literals.NODE__NAME, name); - node2tallNode_0.setName(name); - objectManager.assigned(this, node2tallNode_0, Tree2talltreePackage.Literals.NODE2_TALL_NODE__NAME, name, null); - node2tallNodes.append(node2tallNode_0); - final /*@Thrown*/ @Nullable Boolean Node2MiddleNode = ValueUtil.TRUE_VALUE; - return Node2MiddleNode; - } catch (Throwable e) { - return handleExecutionFailure("MAP_Node2MiddleNode", e); - } - } - - @Override - public boolean isEqual(@NonNull IdResolver idResolver, @NonNull Object @NonNull [] thoseValues) { - return idResolver.oclEquals(node, thoseValues[0]) - && idResolver.oclEquals(node2tallNodes, thoseValues[1]); - } - } - - /** - * - * map Edge2MiddleEdge in Tree2TallTreeInstall { - * guard:tree node : tree::Node[?]; - * var node2tallNode : tree2talltree::Node2TallNode[?] := node.Node2TallNode; - * check node.parent <> null; - * notify set node2tallNode.parent := node.parent.Node2TallNode; - * - */ - protected class MAP_Edge2MiddleEdge extends AbstractInvocation.Incremental - { - protected final /*@NonInvalid*/ @NonNull Node node_0; - - public MAP_Edge2MiddleEdge(InvocationConstructor.@NonNull Incremental constructor, @NonNull Object @NonNull [] boundValues) { - super(constructor); - node_0 = (Node)boundValues[0]; - } - - @Override - public boolean execute() { - try { - final /*@Thrown*/ @NonNull Node2TallNode Node2TallNode = ClassUtil.nonNullState (OPPOSITE_OF_Node2TallNode_node.get(node_0)); - objectManager.got(this, node_0, Tree2talltreePackage.Literals.NODE2_TALL_NODE__NODE, Node2TallNode); - final /*@Thrown*/ @Nullable Node parent = node_0.getParent(); - objectManager.got(this, node_0, TreePackage.Literals.NODE__PARENT, parent); - final /*@Thrown*/ boolean ne = parent != null; - /*@Thrown*/ @Nullable Boolean symbol_2; - if (ne) { - // mapping statements - if (parent == null) { - throw new InvalidValueException("Null source for \'\'http://www.eclipse.org/qvt/examples/0.1/Tree\'::Node::Node2TallNode\'"); - } - final /*@Thrown*/ @NonNull Node2TallNode Node2TallNode_0 = ClassUtil.nonNullState (OPPOSITE_OF_Node2TallNode_node.get(parent)); - objectManager.got(this, parent, Tree2talltreePackage.Literals.NODE2_TALL_NODE__NODE, Node2TallNode_0); - Node2TallNode.setParent(Node2TallNode_0); - objectManager.assigned(this, Node2TallNode, Tree2talltreePackage.Literals.NODE2_TALL_NODE__PARENT, Node2TallNode_0, null); - final /*@Thrown*/ @Nullable Boolean Edge2MiddleEdge = ValueUtil.TRUE_VALUE; - symbol_2 = Edge2MiddleEdge; - } - else { - symbol_2 = ValueUtil.FALSE_VALUE; - } - return symbol_2; - } catch (Throwable e) { - return handleExecutionFailure("MAP_Edge2MiddleEdge", e); - } - } - - @Override - public boolean isEqual(@NonNull IdResolver idResolver, @NonNull Object @NonNull [] thoseValues) { - return idResolver.oclEquals(node_0, thoseValues[0]); - } - } - - /** - * - * map MiddleNode2TallNode in Tree2TallTreeInstall { - * - * guard:tree2talltree node2tallNode : tree2talltree::Node2TallNode[?]; - * var tallNode_name : String[?] := node2tallNode.name; - * var tallNode_children : Set(talltree::TallNode) := node2tallNode.children?.tallNode->asSet() - * ; - * var tallNode_height : Integer[?] := if node2tallNode.children->notEmpty() - * then node2tallNode.children.tallNode.height->max() + 1 - * else 0 - * endif; - * new:talltree tallNode : talltree::TallNode[?]; - * notify set node2tallNode.tallNode := tallNode; - * set tallNode.name := tallNode_name; - * set tallNode.children := tallNode_children; - * notify set tallNode.height := tallNode_height; - * - */ - protected class MAP_MiddleNode2TallNode extends AbstractInvocation.Incremental - { - protected final /*@NonInvalid*/ @NonNull Node2TallNode node2tallNode; - - public MAP_MiddleNode2TallNode(InvocationConstructor.@NonNull Incremental constructor, @NonNull Object @NonNull [] boundValues) { - super(constructor); - node2tallNode = (Node2TallNode)boundValues[0]; - } - - @Override - public boolean execute() { - try { - final /*@NonInvalid*/ @NonNull IdResolver idResolver = executor.getIdResolver(); - @SuppressWarnings("null") - final /*@Thrown*/ @NonNull String name = node2tallNode.getName(); - objectManager.got(this, node2tallNode, Tree2talltreePackage.Literals.NODE2_TALL_NODE__NAME, name); - objectManager.getting(node2tallNode, Tree2talltreePackage.Literals.NODE2_TALL_NODE__CHILDREN, false); - @SuppressWarnings("null") - final /*@Thrown*/ @NonNull List<Node2TallNode> children_0 = node2tallNode.getChildren(); - objectManager.got(this, node2tallNode, Tree2talltreePackage.Literals.NODE2_TALL_NODE__CHILDREN, children_0); - final /*@Thrown*/ @NonNull SetValue BOXED_children_0 = idResolver.createSetOfAll(SET_CLSSid_Node2TallNode, children_0); - final /*@Thrown*/ @NonNull SetValue safe_collect_sources = (SetValue)CollectionExcludingOperation.INSTANCE.evaluate(BOXED_children_0, (Object)null); - /*@Thrown*/ BagValue.@NonNull Accumulator accumulator = ValueUtil.createBagAccumulatorValue(BAG_CLSSid_TallNode); - @NonNull Iterator<Object> ITERATOR__1 = safe_collect_sources.iterator(); - /*@Thrown*/ @NonNull BagValue collect; - while (true) { - if (!ITERATOR__1.hasNext()) { - collect = accumulator; - break; - } - @SuppressWarnings("null") - /*@NonInvalid*/ @NonNull Node2TallNode _1 = (Node2TallNode)ITERATOR__1.next(); - /** - * tallNode - */ - objectManager.getting(_1, Tree2talltreePackage.Literals.NODE2_TALL_NODE__TALL_NODE, false); - @SuppressWarnings("null") - final /*@Thrown*/ @NonNull TallNode tallNode_0 = _1.getTallNode(); - objectManager.got(this, _1, Tree2talltreePackage.Literals.NODE2_TALL_NODE__TALL_NODE, tallNode_0); - // - accumulator.add(tallNode_0); - } - final /*@Thrown*/ @NonNull SetValue asSet = CollectionAsSetOperation.INSTANCE.evaluate(collect); - final /*@Thrown*/ boolean notEmpty = CollectionNotEmptyOperation.INSTANCE.evaluate(BOXED_children_0).booleanValue(); - /*@Thrown*/ @NonNull IntegerValue symbol_0; - if (notEmpty) { - /*@Thrown*/ BagValue.@NonNull Accumulator accumulator_0 = ValueUtil.createBagAccumulatorValue(BAG_CLSSid_TallNode); - @NonNull Iterator<Object> ITERATOR__1_0 = BOXED_children_0.iterator(); - /*@Thrown*/ @NonNull BagValue collect_1; - while (true) { - if (!ITERATOR__1_0.hasNext()) { - collect_1 = accumulator_0; - break; - } - @SuppressWarnings("null") - /*@NonInvalid*/ @NonNull Node2TallNode _1_0 = (Node2TallNode)ITERATOR__1_0.next(); - /** - * tallNode - */ - objectManager.getting(_1_0, Tree2talltreePackage.Literals.NODE2_TALL_NODE__TALL_NODE, false); - @SuppressWarnings("null") - final /*@Thrown*/ @NonNull TallNode tallNode_1 = _1_0.getTallNode(); - objectManager.got(this, _1_0, Tree2talltreePackage.Literals.NODE2_TALL_NODE__TALL_NODE, tallNode_1); - // - accumulator_0.add(tallNode_1); - } - /*@Thrown*/ BagValue.@NonNull Accumulator accumulator_1 = ValueUtil.createBagAccumulatorValue(BAG_DATAid_EInt); - @NonNull Iterator<Object> ITERATOR__1_1 = collect_1.iterator(); - /*@Thrown*/ @NonNull BagValue collect_0; - while (true) { - if (!ITERATOR__1_1.hasNext()) { - collect_0 = accumulator_1; - break; - } - @SuppressWarnings("null") - /*@NonInvalid*/ @NonNull TallNode _1_1 = (TallNode)ITERATOR__1_1.next(); - /** - * height - */ - objectManager.getting(_1_1, TalltreePackage.Literals.TALL_NODE__HEIGHT, false); - final /*@Thrown*/ int height = _1_1.getHeight(); - objectManager.got(this, _1_1, TalltreePackage.Literals.TALL_NODE__HEIGHT, height); - final /*@Thrown*/ @NonNull IntegerValue BOXED_height = ValueUtil.integerValueOf(height); - // - accumulator_1.add(BOXED_height); - } - final /*@Thrown*/ @NonNull IntegerValue max = (IntegerValue)CollectionMaxOperation.INSTANCE.evaluate(collect_0); - final /*@Thrown*/ @NonNull IntegerValue sum = (IntegerValue)NumericPlusOperation.INSTANCE.evaluate(max, INT_1); - symbol_0 = sum; - } - else { - symbol_0 = INT_0; - } - // creations - final /*@Thrown*/ @Nullable TallNode tallNode = TalltreeFactory.eINSTANCE.createTallNode(); - assert tallNode != null; - models[1/*talltree*/].add(tallNode); - objectManager.created(this, tallNode); - // mapping statements - node2tallNode.setTallNode(tallNode); - objectManager.assigned(this, node2tallNode, Tree2talltreePackage.Literals.NODE2_TALL_NODE__TALL_NODE, tallNode, null); - tallNode.setName(name); - objectManager.assigned(this, tallNode, TalltreePackage.Literals.TALL_NODE__NAME, name, null); - final /*@Thrown*/ @NonNull List<TallNode> ECORE_asSet = ((IdResolver.IdResolverExtension)idResolver).ecoreValueOfAll(TallNode.class, asSet); - tallNode.getChildren().addAll(ECORE_asSet); - objectManager.assigned(this, tallNode, TalltreePackage.Literals.TALL_NODE__CHILDREN, ECORE_asSet, null); - final int ECORE_symbol_0 = ValueUtil.intValueOf(symbol_0); - tallNode.setHeight(ECORE_symbol_0); - objectManager.assigned(this, tallNode, TalltreePackage.Literals.TALL_NODE__HEIGHT, ECORE_symbol_0, null); - final /*@Thrown*/ @Nullable Boolean MiddleNode2TallNode = ValueUtil.TRUE_VALUE; - return MiddleNode2TallNode; - } catch (Throwable e) { - return handleExecutionFailure("MAP_MiddleNode2TallNode", e); - } - } - - @Override - public boolean isEqual(@NonNull IdResolver idResolver, @NonNull Object @NonNull [] thoseValues) { - return idResolver.oclEquals(node2tallNode, thoseValues[0]); - } - } -} |