diff options
author | Ed Willink | 2016-10-09 13:35:56 +0000 |
---|---|---|
committer | Ed Willink | 2016-10-30 11:37:23 +0000 |
commit | ba56020b91d0cc0f4391cc2b80b89bfe5eb47654 (patch) | |
tree | ac63bafd9af29f6cebade01bbe9047d21d2ac90e | |
parent | 42d12406c8517a62affc454fea29d6106b604d89 (diff) | |
download | org.eclipse.qvtd-ba56020b91d0cc0f4391cc2b80b89bfe5eb47654.tar.gz org.eclipse.qvtd-ba56020b91d0cc0f4391cc2b80b89bfe5eb47654.tar.xz org.eclipse.qvtd-ba56020b91d0cc0f4391cc2b80b89bfe5eb47654.zip |
[500962] Refactor out InvocationConstructor
31 files changed, 1441 insertions, 234 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 01fcc778d..ed0de1690 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 @@ -111,6 +111,7 @@ import org.eclipse.qvtd.runtime.evaluation.AbstractInvocation; import org.eclipse.qvtd.runtime.evaluation.AbstractTransformer; import org.eclipse.qvtd.runtime.evaluation.AbstractValueOccurrence; import org.eclipse.qvtd.runtime.evaluation.Invocation; +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; @@ -420,7 +421,9 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato js.pushIndentation(null); js.append("return new "); js.appendClassReference(IncrementalInvocationManager.class); - js.append("();\n"); + js.append("("); + js.append(JavaConstants.EXECUTOR_NAME); + js.append(");\n"); js.popIndentation(); js.append("}\n"); js.append("\n"); @@ -960,7 +963,7 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato js.append(getMappingName(cgMapping)); js.append("("); if (isIncremental) { - js.appendClassReference(true, isIncremental ? Invocation.Constructor.Incremental.class : Invocation.Constructor.class); + js.appendClassReference(true, isIncremental ? InvocationConstructor.Incremental.class : InvocationConstructor.class); js.append(" constructor, "); } js.appendIsRequired(true); @@ -969,10 +972,10 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato js.append(" [] boundValues) {\n"); js.pushIndentation(null); if (isIncremental) { - js.append("super(invocationManager.getDefaultInterval(), constructor);\n"); + js.append("super(invocationManager.getRootInterval(), constructor);\n"); } else { - js.append("super(invocationManager.getDefaultInterval());\n"); + js.append("super(invocationManager.getRootInterval());\n"); } int i = 0; for (@NonNull CGGuardVariable cgFreeVariable : cgFreeVariables) { @@ -1003,7 +1006,7 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato js.appendClassReference(true, constructorClass); js.append(" " + getMappingCtorName(cgMapping) + " = new "); js.appendClassReference(constructorClass); - js.append("(idResolver, "); + js.append("(invocationManager.getRootInterval(), "); js.appendString(QVTiCGUtil.getName(cgMapping)); js.append(")\n"); js.append("{\n"); @@ -1132,7 +1135,7 @@ public class QVTiCG2JavaVisitor extends CG2JavaVisitor<@NonNull QVTiCodeGenerato js.pushIndentation(null); if (isIncremental) { js.appendClassReference(Invocation.class); - js.append(" rootInvocation = " + getMappingCtorName(cgRootMapping) + ".newInstance(new @NonNull Object[0]);\n"); + js.append(" rootInvocation = " + getMappingCtorName(cgRootMapping) + ".getInstance(new @NonNull Object[0]);\n"); js.append("return rootInvocation.execute() && invocationManager.flush();\n"); } else { diff --git a/plugins/org.eclipse.qvtd.pivot.qvtbase/annotations/java/util/Arrays.eea b/plugins/org.eclipse.qvtd.pivot.qvtbase/annotations/java/util/Arrays.eea new file mode 100644 index 000000000..afeb20325 --- /dev/null +++ b/plugins/org.eclipse.qvtd.pivot.qvtbase/annotations/java/util/Arrays.eea @@ -0,0 +1,7 @@ +class java/util/Arrays +copyOf + <T:Ljava/lang/Object;>([TT;I)[TT; + <T:Ljava/lang/Object;>([1TT;I)[1TT; +copyOfRange + <T:Ljava/lang/Object;>([TT;II)[TT; + <T:Ljava/lang/Object;>([1TT;II)[1TT; diff --git a/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/Execution2GraphVisitor.java b/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/Execution2GraphVisitor.java index 7cec34d73..19fd86596 100644 --- a/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/Execution2GraphVisitor.java +++ b/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/Execution2GraphVisitor.java @@ -10,6 +10,8 @@ ******************************************************************************/ package org.eclipse.qvtd.pivot.qvtimperative.evaluation; +import java.io.IOException; +import java.io.OutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -17,12 +19,15 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.resource.URIConverter; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.qvtd.pivot.qvtbase.graphs.GraphMLStringBuilder; import org.eclipse.qvtd.pivot.qvtbase.graphs.GraphStringBuilder; import org.eclipse.qvtd.pivot.qvtbase.graphs.GraphStringBuilder.GraphEdge; import org.eclipse.qvtd.pivot.qvtbase.graphs.GraphStringBuilder.GraphNode; @@ -31,7 +36,10 @@ import org.eclipse.qvtd.pivot.qvtimperative.evaluationstatus.AttributeStatus; import org.eclipse.qvtd.pivot.qvtimperative.evaluationstatus.ClassStatus; import org.eclipse.qvtd.pivot.qvtimperative.evaluationstatus.PropertyStatus; import org.eclipse.qvtd.runtime.evaluation.AbstractExecutionVisitor; +import org.eclipse.qvtd.runtime.evaluation.Connection; +import org.eclipse.qvtd.runtime.evaluation.Interval; import org.eclipse.qvtd.runtime.evaluation.Invocation; +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.SlotState; @@ -46,16 +54,21 @@ public class Execution2GraphVisitor extends AbstractExecutionVisitor<@Nullable O private final @NonNull GraphNode sourceNode; private final @NonNull GraphNode targetNode; private final @NonNull String color; + private final @Nullable String style; - protected ExecutionEdge(@NonNull GraphNode sourceNode, @NonNull GraphNode targetNode, @NonNull String color) { + protected ExecutionEdge(@NonNull GraphNode sourceNode, @NonNull GraphNode targetNode, @NonNull String color, @Nullable String style) { this.sourceNode = sourceNode; this.targetNode = targetNode; this.color = color; + this.style = style; } @Override public void appendEdgeAttributes(@NonNull GraphStringBuilder s, @NonNull GraphNode source, @NonNull GraphNode target) { s.setColor(color); + if (style != null) { + s.setStyle(style); + } s.appendAttributedEdge(source, this, target); } @@ -72,11 +85,28 @@ public class Execution2GraphVisitor extends AbstractExecutionVisitor<@Nullable O protected static @NonNull String NULL_PLACEHOLDER = "\"<null>\""; //$NON-NLS-1$ + public static void writeGraphMLfile(Transformer tx, @NonNull URI graphmlURI) { + try { + OutputStream outputStream = URIConverter.INSTANCE.createOutputStream(graphmlURI); + GraphMLStringBuilder s = new GraphMLStringBuilder(); + Execution2GraphVisitor execution2GraphVisitor = new Execution2GraphVisitor(s); + tx.accept(execution2GraphVisitor); + outputStream.write(s.toString().getBytes()); + outputStream.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + protected final @NonNull GraphStringBuilder context; private Map<@NonNull AssociationStatus, @NonNull String> associationId = new HashMap<>(); private Map<@NonNull ClassStatus, @NonNull String> classId = new HashMap<>(); + private Map<@NonNull Connection, @NonNull GraphNode> connection2node = new HashMap<>(); + private Map<@NonNull Interval, @NonNull GraphNode> interval2node = new HashMap<>(); private Map<@NonNull Invocation, @NonNull GraphNode> invocation2node = new HashMap<>(); + private Map<@NonNull InvocationConstructor, @NonNull GraphNode> invocationConstructor2node = new HashMap<>(); private Map<@NonNull Object, @NonNull GraphNode> object2node = new HashMap<>(); private Map<@NonNull SlotState, @NonNull GraphNode> slot2node = new HashMap<>(); // private Map<@NonNull String, @NonNull String> propertyId2associationId = new HashMap<>(); @@ -86,8 +116,8 @@ public class Execution2GraphVisitor extends AbstractExecutionVisitor<@Nullable O this.context = s; } - protected void appendEdge(@NonNull GraphNode sourceNode, @NonNull GraphNode targetNode, @NonNull String color) { - context.appendEdge(sourceNode, new ExecutionEdge(sourceNode, targetNode, color), targetNode); + protected void appendEdge(@NonNull GraphNode sourceNode, @NonNull GraphNode targetNode, @NonNull String color, @Nullable String style) { + context.appendEdge(sourceNode, new ExecutionEdge(sourceNode, targetNode, color, style), targetNode); } protected @NonNull String getAssociationColor(@NonNull AssociationStatus associationStatus) { @@ -147,18 +177,79 @@ public class Execution2GraphVisitor extends AbstractExecutionVisitor<@Nullable O return id; } + protected @NonNull GraphNode getConnectionNode(@NonNull Connection object) { + GraphNode node = connection2node.get(object); + if (node == null) { + final String label = object.getName(); + node = new GraphNode() + { + @Override + public void appendNode(@NonNull GraphStringBuilder s, @NonNull String nodeName) { + s.setLabel(label); + s.setShape("ellipse"); + s.setColor("brown"); + s.appendAttributedNode(nodeName); + } + }; + connection2node.put(object, node); + context.appendNode(node); + } + return node; + } + + protected @NonNull GraphNode getIntervalNode(@NonNull Interval object) { + GraphNode node = interval2node.get(object); + if (node == null) { + final String label = " " + object.getName() + " "; + node = new GraphNode() + { + @Override + public void appendNode(@NonNull GraphStringBuilder s, @NonNull String nodeName) { + s.setLabel(label); + s.setShape("octagon"); + s.setColor("black"); + s.appendAttributedNode(nodeName); + } + }; + interval2node.put(object, node); + context.appendNode(node); + } + return node; + } + + protected @NonNull GraphNode getInvocationConstructorNode(@NonNull InvocationConstructor object) { + GraphNode node = invocationConstructor2node.get(object); + if (node == null) { + final String label = object.getName(); + node = new GraphNode() + { + @Override + public void appendNode(@NonNull GraphStringBuilder s, @NonNull String nodeName) { + s.setLabel(label); + s.setShape("hexagon"); + s.setColor("brown"); + s.appendAttributedNode(nodeName); + } + }; + invocationConstructor2node.put(object, node); + context.appendNode(node); + } + return node; + } + protected @NonNull GraphNode getInvocationNode(@NonNull Invocation object) { GraphNode node = invocation2node.get(object); if (node == null) { // id = object.getReferredMappingCall().getReferredMapping().getName() + "-" + (mappingId.size() + 1); - final String label; - if (object instanceof EObject) { - label = ((EObject)object).eClass().getName() + "-" + (invocation2node.size() + 1); - } - else { - label = object.toString().replace("@", "\n@"); - // label = object.getClass().getSimpleName() + "-" + (invocation2node.size() + 1); - } + final String label = object.getName(); + // final String label; + // if (object instanceof EObject) { + // label = ((EObject)object).eClass().getName() + "-" + (invocation2node.size() + 1); + // } + // else { + // label = object.toString().replace("@", "\n@"); + // label = object.getClass().getSimpleName() + "-" + (invocation2node.size() + 1); + // } node = new GraphNode() { @Override @@ -176,7 +267,7 @@ public class Execution2GraphVisitor extends AbstractExecutionVisitor<@Nullable O return node; } - protected @NonNull GraphNode getObjectNode(@NonNull Object object, @NonNull String color) { + protected @NonNull GraphNode getObjectNode(@NonNull Object object) { GraphNode node = object2node.get(object); if (node == null) { // id = object.getReferredMappingCall().getReferredMapping().getName() + "-" + (mappingId.size() + 1); @@ -194,7 +285,7 @@ public class Execution2GraphVisitor extends AbstractExecutionVisitor<@Nullable O public void appendNode(@NonNull GraphStringBuilder s, @NonNull String nodeName) { s.setLabel(label); s.setShape("rectangle"); - s.setColor(color); + s.setColor("blue"); s.appendAttributedNode(nodeName); } }; @@ -216,7 +307,7 @@ public class Execution2GraphVisitor extends AbstractExecutionVisitor<@Nullable O } } - protected @NonNull GraphNode getSlotNode(SlotState.@NonNull Incremental object, @NonNull String color) { + protected @NonNull GraphNode getSlotNode(SlotState.@NonNull Incremental object) { if (object.getValue() != null) { object = object.getPrimarySlotState(); } @@ -230,6 +321,14 @@ public class Execution2GraphVisitor extends AbstractExecutionVisitor<@Nullable O label += " / " + eOpposite.getName(); } } + else if (eFeature instanceof EAttribute) { + Object value = object.getValue(); // FIXME may be null for inputs, and some slots seem crooked + String stringValue = value != null ? value.toString() : "???"; + if (stringValue.length() > 20) { + stringValue = stringValue.substring(0, 17) + "..."; + } + label += " \n " + stringValue; + } final String finalLabel = label; node = new GraphNode() { @@ -240,7 +339,7 @@ public class Execution2GraphVisitor extends AbstractExecutionVisitor<@Nullable O if (eFeature instanceof EAttribute) { s.setStyle("rounded"); } - s.setColor(color); + s.setColor("blue"); s.appendAttributedNode(nodeName); } }; @@ -250,6 +349,31 @@ public class Execution2GraphVisitor extends AbstractExecutionVisitor<@Nullable O return node; } + @Override + public @Nullable Object visitConnection(@NonNull Connection object) { + GraphNode connectionNode = getConnectionNode(object); + for (@NonNull InvocationConstructor producer : object.getAppenders()) { + GraphNode producerNode = getInvocationConstructorNode(producer); + appendEdge(producerNode, connectionNode, "brown", null); + } + for (@NonNull InvocationConstructor consumer : object.getConsumers()) { + GraphNode consumerNode = getInvocationConstructorNode(consumer); + appendEdge(connectionNode, consumerNode, "brown", null); + } + int iMax = object.getValues(); + for (int i = 0; i < iMax; i++) { + Object value = object.getValue(i); + if (value != null) { + GraphNode objectNode = getObjectNode(value); + appendEdge(connectionNode, objectNode, "brown", "dotted"); + // for (@NonNull Invocation invocation : object.getConsumers(i)) { + // GraphNode consumerNode = getInvocationNode(invocation); + // } + } + } + return null; + } + /* @Override public String visiting(@NonNull EvaluationElement visitable) { // append(visitable.getClass().getName()); @@ -312,50 +436,74 @@ public class Execution2GraphVisitor extends AbstractExecutionVisitor<@Nullable O } */ @Override + public @Nullable Object visitInterval(@NonNull Interval object) { + GraphNode intervalNode = getIntervalNode(object); + for (@NonNull Connection connection : object.getConnections()) { + connection.accept(this); + GraphNode connectionNode = getConnectionNode(connection); + appendEdge(connectionNode, intervalNode, "black", "dashed"); + } + return null; + } + + @Override public @Nullable String visitInvocation(@NonNull Invocation object) { @SuppressWarnings("unused") GraphNode invocationNode = getInvocationNode(object); /* context.appendNode(mappingId, "hexagon", "#ffcc00", 30, 150, mappingId.replace("-", "\n")); - for (ElementStatus inputStatus : object.getInputs()) { - if (inputStatus instanceof ClassStatus) { - ClassStatus classStatus = (ClassStatus)inputStatus; - String classId = getClassId(classStatus); - context.appendEdge(classId, mappingId, "#000000", "line","none", "standard"); - } - else if (inputStatus instanceof PropertyStatus) { - PropertyStatus propertyStatus = (PropertyStatus)inputStatus; - String propertyId = getPropertyId(propertyStatus); - context.appendEdge(propertyId, mappingId, "#000000", "dashed","none", "standard"); + for (ElementStatus inputStatus : object.getInputs()) { + if (inputStatus instanceof ClassStatus) { + ClassStatus classStatus = (ClassStatus)inputStatus; + String classId = getClassId(classStatus); + context.appendEdge(classId, mappingId, "#000000", "line","none", "standard"); + } + else if (inputStatus instanceof PropertyStatus) { + PropertyStatus propertyStatus = (PropertyStatus)inputStatus; + String propertyId = getPropertyId(propertyStatus); + context.appendEdge(propertyId, mappingId, "#000000", "dashed","none", "standard"); + } } + for (ElementStatus outputStatus : object.getOutputs()) { + if (outputStatus instanceof ClassStatus) { + ClassStatus classStatus = (ClassStatus)outputStatus; + String classId = getClassId(classStatus); + context.appendEdge(mappingId, classId, "#000000", "line","none", "standard"); + } + else if (outputStatus instanceof PropertyStatus) { + PropertyStatus propertyStatus = (PropertyStatus)outputStatus; + String propertyId = getPropertyId(propertyStatus); + context.appendEdge(mappingId, propertyId, "#000000", "dashed","none", "standard"); + } + } */ + return null; + } + + @Override + public @Nullable Object visitInvocationConstructor(@NonNull InvocationConstructor object) { + GraphNode invokerNode = getInvocationConstructorNode(object); + GraphNode intervalNode = getIntervalNode(object.getInterval()); + appendEdge(invokerNode, intervalNode, "black", "dashed"); + for (@NonNull Invocation invocation : object.getInvocations()) { + GraphNode invocationNode = getInvocationNode(invocation); + appendEdge(invokerNode, invocationNode, "orange", "dotted"); } - for (ElementStatus outputStatus : object.getOutputs()) { - if (outputStatus instanceof ClassStatus) { - ClassStatus classStatus = (ClassStatus)outputStatus; - String classId = getClassId(classStatus); - context.appendEdge(mappingId, classId, "#000000", "line","none", "standard"); - } - else if (outputStatus instanceof PropertyStatus) { - PropertyStatus propertyStatus = (PropertyStatus)outputStatus; - String propertyId = getPropertyId(propertyStatus); - context.appendEdge(mappingId, propertyId, "#000000", "dashed","none", "standard"); - } - } */ return null; } @Override public @Nullable String visitInvocationManager(@NonNull InvocationManager object) { - // context.open(); - // for (ClassStatus classStatus : object.getOwnedClassStatuses()) { - // classStatus.accept(this); - // } - // for (MappingStatus mappingStatus : object.getOwnedMappingStatuses()) { - // mappingStatus.accept(this); - // } - // for (AssociationStatus associationStatus : object.getOwnedAssociationStatuses()) { - // associationStatus.accept(this); - // } - // context.close(); + GraphNode previousNode = null; + for (@NonNull InvocationConstructor invoker : object.getInvokers()) { + invoker.accept(this); + } + for (@NonNull Interval interval : object.getIntervals()) { + interval.accept(this); + GraphNode nextNode = getIntervalNode(interval); + if (previousNode != null) { + appendEdge(previousNode, nextNode, "black", null); + } + previousNode = nextNode; + } return null; } @@ -383,29 +531,29 @@ public class Execution2GraphVisitor extends AbstractExecutionVisitor<@Nullable O invocation.accept(this); GraphNode invocationNode = getInvocationNode(invocation); for (@NonNull Object createdObject : invocation.getCreatedObjects()) { - GraphNode objectNode = getObjectNode(createdObject, "green"); - appendEdge(invocationNode, objectNode, "green"); + GraphNode objectNode = getObjectNode(createdObject); + appendEdge(invocationNode, objectNode, "green", null); } } for (SlotState.@NonNull Incremental slotState : allSlots) { - GraphNode slotNode = getSlotNode(slotState, "green"); + GraphNode slotNode = getSlotNode(slotState); slotState.accept(this); for (@NonNull Invocation invocation : slotState.getSources()) { - appendEdge(getInvocationNode(invocation), slotNode, "green"); + appendEdge(getInvocationNode(invocation), slotNode, "green", null); } for (@NonNull Invocation invocation : slotState.getTargets()) { - appendEdge(slotNode, getInvocationNode(invocation), "cyan"); + appendEdge(slotNode, getInvocationNode(invocation), "cyan", null); } Iterables.addAll(allInvocations, slotState.getTargets()); } for (@NonNull Object object : objectManager.getObjects()) { - GraphNode objectNode = getObjectNode(object, "blue"); + GraphNode objectNode = getObjectNode(object); List<SlotState.@NonNull Incremental> slots = object2slots.get(object); if (slots != null) { for (SlotState.@NonNull Incremental slotState : slots) { - GraphNode slotNode = getSlotNode(slotState, "blue"); + GraphNode slotNode = getSlotNode(slotState); slotState.accept(this); - appendEdge(objectNode, slotNode, "blue"); + appendEdge(objectNode, slotNode, "blue", null); } } } @@ -419,7 +567,9 @@ public class Execution2GraphVisitor extends AbstractExecutionVisitor<@Nullable O } @Override - public @Nullable String visitTransformer(@NonNull Transformer object) { + public @Nullable String visitTransformer(@NonNull Transformer transformer) { + transformer.getInvocationManager().accept(this); + transformer.getObjectManager().accept(this); return null; } diff --git a/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/QVTiIncrementalExecutor.java b/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/QVTiIncrementalExecutor.java index afb96a50c..8b115b01b 100644 --- a/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/QVTiIncrementalExecutor.java +++ b/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/QVTiIncrementalExecutor.java @@ -27,6 +27,7 @@ import org.eclipse.ocl.pivot.Property; import org.eclipse.ocl.pivot.evaluation.EvaluationVisitor; import org.eclipse.ocl.pivot.ids.IdResolver; import org.eclipse.ocl.pivot.utilities.ClassUtil; +import org.eclipse.ocl.pivot.utilities.LabelUtil; import org.eclipse.ocl.pivot.utilities.PivotUtil; import org.eclipse.ocl.pivot.utilities.ValueUtil; import org.eclipse.ocl.pivot.values.InvalidValueException; @@ -44,6 +45,7 @@ import org.eclipse.qvtd.runtime.evaluation.AbstractInvocation; import org.eclipse.qvtd.runtime.evaluation.AbstractTransformer; import org.eclipse.qvtd.runtime.evaluation.Computation; import org.eclipse.qvtd.runtime.evaluation.Invocation; +import org.eclipse.qvtd.runtime.evaluation.InvocationConstructor; import org.eclipse.qvtd.runtime.evaluation.InvocationFailedException; import org.eclipse.qvtd.runtime.evaluation.InvocationManager; import org.eclipse.qvtd.runtime.evaluation.ObjectManager; @@ -78,7 +80,7 @@ public class QVTiIncrementalExecutor extends BasicQVTiExecutor protected final @NonNull InvocationManager invocationManager; protected final @NonNull ObjectManager objectManager; private Invocation.@Nullable Incremental currentInvocation = null; - private @Nullable Map<@NonNull Mapping, Invocation.@NonNull Constructor> mapping2invocationConstructor = null; + private @Nullable Map<@NonNull Mapping, @NonNull InvocationConstructor> mapping2invocationConstructor = null; private @Nullable Map<@NonNull Operation, Computation.@NonNull Constructor> operation2computationConstructor = null; public QVTiIncrementalExecutor(@NonNull QVTiEnvironmentFactory environmentFactory, @NonNull ImperativeTransformation transformation, @NonNull Mode mode) { @@ -86,7 +88,7 @@ public class QVTiIncrementalExecutor extends BasicQVTiExecutor this.mode = mode; this.transformationAnalysis = getModelManager().getTransformationAnalysis(); boolean isLazy = mode == Mode.LAZY; - this.invocationManager = isLazy ? new LazyInvocationManager() : new IncrementalInvocationManager(); + this.invocationManager = isLazy ? new LazyInvocationManager(this) : new IncrementalInvocationManager(this); this.objectManager = isLazy ? new LazyObjectManager((LazyInvocationManager)invocationManager) : new IncrementalObjectManager((IncrementalInvocationManager)invocationManager); } @@ -157,17 +159,17 @@ public class QVTiIncrementalExecutor extends BasicQVTiExecutor return super.internalExecuteMappingCall(mappingCall, boundValues, undecoratedVisitor); } } - Map<@NonNull Mapping, Invocation.@NonNull Constructor> mapping2invocationConstructor2 = mapping2invocationConstructor; + Map<@NonNull Mapping, @NonNull InvocationConstructor> mapping2invocationConstructor2 = mapping2invocationConstructor; if (mapping2invocationConstructor2 == null) { mapping2invocationConstructor = mapping2invocationConstructor2 = new HashMap<>(); } - Invocation.Constructor invocationConstructor = mapping2invocationConstructor2.get(asMapping); + InvocationConstructor invocationConstructor = mapping2invocationConstructor2.get(asMapping); if (invocationConstructor == null) { - invocationConstructor = new AbstractInvocationConstructor.Incremental(idResolver, QVTimperativeUtil.getName(asMapping)) + invocationConstructor = new AbstractInvocationConstructor.Incremental(invocationManager.getRootInterval(), QVTimperativeUtil.getName(asMapping)) { @Override public @NonNull Invocation newInstance(@NonNull Object @NonNull [] theseValues) { - Invocation.Incremental invocation = new AbstractInvocation.Incremental(invocationManager.getDefaultInterval(), this) + Invocation.Incremental invocation = new AbstractInvocation.Incremental(invocationManager.getRootInterval(), this) { protected Object returnStatus; @@ -253,7 +255,7 @@ public class QVTiIncrementalExecutor extends BasicQVTiExecutor objectManager.getting(sourceValue, eFeature, isOpposite); ecoreValue = super.internalExecuteNavigationCallExp(navigationCallExp, referredProperty, sourceValue); if (debugInvocations) { - AbstractTransformer.INVOCATIONS.println("got " + eFeature.getEContainingClass().getName() + "::" + eFeature.getName() + " for " + sourceValue + " = " + ecoreValue); + AbstractTransformer.INVOCATIONS.println("got " + eFeature.getEContainingClass().getName() + "::" + eFeature.getName() + " for " + LabelUtil.getLabel(sourceValue) + " = " + LabelUtil.getLabel(ecoreValue)); } } else { diff --git a/plugins/org.eclipse.qvtd.runtime/.options b/plugins/org.eclipse.qvtd.runtime/.options index e0294cf01..5ef141ff5 100644 --- a/plugins/org.eclipse.qvtd.runtime/.options +++ b/plugins/org.eclipse.qvtd.runtime/.options @@ -3,6 +3,9 @@ # Trace transformation connection appends org.eclipse.qvtd.runtime/tx/appends=false +# Trace transformation connection consumes +org.eclipse.qvtd.runtime/tx/consumes=false + # Trace transformation exceptions org.eclipse.qvtd.runtime/tx/exceptions=false diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/AbstractExecutionVisitor.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/AbstractExecutionVisitor.java index faab92923..138922dbb 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/AbstractExecutionVisitor.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/AbstractExecutionVisitor.java @@ -48,12 +48,12 @@ public /*abstract*/ class AbstractExecutionVisitor<R> implements ExecutionVisito } @Override - public R visitInvocationManager(@NonNull InvocationManager object) { + public R visitInvocationConstructor(@NonNull InvocationConstructor object) { return visiting(object); } @Override - public R visitInvoker(@NonNull Invoker object) { + public R visitInvocationManager(@NonNull InvocationManager object) { return visiting(object); } 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 d833b2fa3..b1b7d64b2 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 @@ -28,14 +28,14 @@ public abstract class AbstractInvocation extends AbstractInvocationInternal public static final @NonNull List<@NonNull Object> EMPTY_OBJECT_LIST = Collections.emptyList(); public static final @NonNull List<SlotState.@NonNull Incremental> EMPTY_SLOT_LIST = Collections.emptyList(); - protected final Invocation.@NonNull Constructor constructor; + protected final @NonNull InvocationConstructor constructor; protected final int sequence; private Set<@NonNull Object> createdObjects = null; private Set<SlotState.@NonNull Incremental> readSlots = null; private Set<SlotState.@NonNull Incremental> writeSlots = null; - protected Incremental(@NonNull Interval interval, Invocation.Constructor.@NonNull Incremental constructor) { + protected Incremental(@NonNull Interval interval, InvocationConstructor.@NonNull Incremental constructor) { super(interval); this.constructor = constructor; this.sequence = constructor.nextSequence(); @@ -101,4 +101,9 @@ public abstract class AbstractInvocation extends AbstractInvocationInternal public <R> R accept(@NonNull ExecutionVisitor<R> visitor) { return visitor.visitInvocation(this); } + + @Override + public @NonNull String getName() { + return toString().replace("@", "\n@"); + } }
\ No newline at end of file diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/AbstractTransformer.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/AbstractTransformer.java index 7fffbaa34..c8298563b 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/AbstractTransformer.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/AbstractTransformer.java @@ -26,6 +26,7 @@ public abstract class AbstractTransformer extends AbstractTransformerInternal { public static final @NonNull String PLUGIN_ID = "org.eclipse.qvtd.runtime"; public static final @NonNull TracingOption APPENDS = new TracingOption(PLUGIN_ID, "tx/appends"); + public static final @NonNull TracingOption CONSUMES = new TracingOption(PLUGIN_ID, "tx/consumes"); public static final @NonNull TracingOption EXCEPTIONS = new TracingOption(PLUGIN_ID, "tx/exceptions"); public static final @NonNull TracingOption INVOCATIONS = new TracingOption(PLUGIN_ID, "tx/invocations"); 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 455e6249d..201ea85c6 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 @@ -27,9 +27,9 @@ import org.eclipse.ocl.pivot.utilities.Nameable; */ public interface Connection extends ExecutionVisitable, Nameable { - void addConsumer(@NonNull Invoker consumingInvoker); + void addAppender(@NonNull InvocationConstructor appendingInvoker); - void addProducer(@NonNull Invoker producingInvoker); + void addConsumer(@NonNull InvocationConstructor consumingInvoker); /** * Append aValue to the contents, enforcing uniqueness if necessary, and waking up the overall @@ -46,14 +46,14 @@ public interface Connection extends ExecutionVisitable, Nameable void consume(int elementIndex, @NonNull Invocation mapping); + @NonNull Iterable<@NonNull InvocationConstructor> getAppenders(); + int getCapacity(); - @NonNull Iterable<@NonNull Invoker> getConsumers(); + @NonNull Iterable<@NonNull InvocationConstructor> getConsumers(); // @NonNull Iterable<@NonNull Invocation> getConsumers(int i); - @NonNull Iterable<@NonNull Invoker> getProducers(); - @Nullable Object getValue(int i); int getValues(); diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/Invoker.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/DefaultInterval.java index 3ddc218a3..f01089baa 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/Invoker.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/DefaultInterval.java @@ -11,18 +11,14 @@ package org.eclipse.qvtd.runtime.evaluation; import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.ocl.pivot.utilities.Nameable; +import org.eclipse.qvtd.runtime.internal.evaluation.AbstractIntervalInternal; /** - * An Invoker marshalls the arguments to invoke a mapping Invocation. - * - * @noimplement clients should derive from AbstractInvoker + * DefaultInterval provides the standard implementation of the scheduling interval manager. */ -public interface Invoker extends ExecutionVisitable, Nameable +public class DefaultInterval extends AbstractIntervalInternal { - @NonNull Interval getInterval(); - - @NonNull Iterable<@NonNull Invocation> getInvocations(); - - void propagate(); -}
\ No newline at end of file + public DefaultInterval(@NonNull InvocationManager invocationManager, int intervalIndex) { + super(invocationManager, intervalIndex); + } +} diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/ExecutionVisitor.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/ExecutionVisitor.java index c1db83d2b..7b6127ba1 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/ExecutionVisitor.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/ExecutionVisitor.java @@ -29,8 +29,8 @@ public interface ExecutionVisitor<R> R visitConnection(@NonNull Connection object); R visitInterval(@NonNull Interval object); R visitInvocation(@NonNull Invocation object); + R visitInvocationConstructor(@NonNull InvocationConstructor object); R visitInvocationManager(@NonNull InvocationManager object); - R visitInvoker(@NonNull Invoker object); R visitObjectManager(@NonNull ObjectManager object); R visitSlotState(@NonNull SlotState object); R visitTransformer(@NonNull Transformer object); diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/Interval.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/Interval.java index aa81794a5..b1e7feb16 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/Interval.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/Interval.java @@ -11,6 +11,7 @@ package org.eclipse.qvtd.runtime.evaluation; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.ocl.pivot.ids.CollectionTypeId; import org.eclipse.ocl.pivot.utilities.Nameable; /** @@ -21,8 +22,12 @@ import org.eclipse.ocl.pivot.utilities.Nameable; */ public interface Interval extends ExecutionVisitable, Nameable { + @NonNull Connection createConnection(@NonNull String name, @NonNull CollectionTypeId typeId, boolean isEnforced); + boolean flush(); + @NonNull Iterable<@NonNull Connection> getConnections(); + int getIndex(); @NonNull InvocationManager getInvocationManager(); @@ -32,6 +37,10 @@ public interface Interval extends ExecutionVisitable, Nameable void invoke(@NonNull Invocation invocation, boolean doFlush); + boolean isFlushed(); + + void queue(@NonNull Connection connection); + void queue(@NonNull Invocation consumer); void unblock(@NonNull Invocation invocation); diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/Invocation.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/Invocation.java index f6b72e80d..a0768dcd8 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/Invocation.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/Invocation.java @@ -11,7 +11,6 @@ package org.eclipse.qvtd.runtime.evaluation; import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.jdt.annotation.Nullable; import org.eclipse.ocl.pivot.ids.IdResolver; import org.eclipse.ocl.pivot.utilities.Nameable; @@ -20,7 +19,7 @@ import org.eclipse.ocl.pivot.utilities.Nameable; * * @noimplement clients should derive from AbstractInvocation */ -public interface Invocation extends ExecutionVisitable +public interface Invocation extends ExecutionVisitable, Nameable { /** * Execute the mapping invocation, returning true if successfully executed, or false if some predicate failed. @@ -40,6 +39,7 @@ public interface Invocation extends ExecutionVisitable */ boolean isEqual(@NonNull IdResolver idResolver, @NonNull Object @NonNull [] thoseValues); + void queue(); /** * Remove this Invocation from the blocked or waiting invocations linked list. @@ -48,29 +48,7 @@ public interface Invocation extends ExecutionVisitable void unblock(); - public interface Constructor extends Nameable - { - public interface Incremental extends Constructor - { - int nextSequence(); - } - - /** - * Return the first invocation of this constructor with argValues, using newInstance(argValues) to - * create a new invocation instance if necessary. Returns null if an instance already created. - */ - @Nullable Invocation getFirstInvocation(@NonNull Object @NonNull [] argValues); - - @Override - @NonNull String getName(); - - /** - * Create the invocation identified by this constructor and values. - */ - @NonNull Invocation newInstance(@NonNull Object @NonNull [] values); - } - - public interface Incremental extends Invocation, Nameable + public interface Incremental extends Invocation { void addCreatedObject(@NonNull Object createdObject); void addReadSlot(SlotState.@NonNull Incremental readSlot); diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/InvocationConstructor.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/InvocationConstructor.java new file mode 100644 index 000000000..1643fea97 --- /dev/null +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/InvocationConstructor.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2013, 2016 Willink Transformations and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * E.D.Willink - Initial API and implementation + *******************************************************************************/ +package org.eclipse.qvtd.runtime.evaluation; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.ocl.pivot.utilities.Nameable; + +/** + * An Invocation identifies a unique invocation of a Mapping and the objects/values bound to its guard variables. + * + * @noimplement clients should derive from AbstractInvocation + */ +public interface InvocationConstructor extends ExecutionVisitable, Nameable +{ + public interface Incremental extends InvocationConstructor + { + int nextSequence(); + } + + void addAppendedConnection(@NonNull Connection connection); + + void addConsumedConection(@NonNull Connection connection); + + /** + * Return the first invocation of this constructor with argValues, using newInstance(argValues) to + * create a new invocation instance if necessary. Returns null if an instance already created. + */ + @Nullable Invocation getFirstInvocation(@NonNull Object @NonNull [] argValues); + + /** + * Create the invocation identified by this constructor and values. + */ + @NonNull Invocation getInstance(@NonNull Object @NonNull [] values); + + @NonNull Interval getInterval(); + + @NonNull Iterable<@NonNull Invocation> getInvocations(); + + @Override + @NonNull String getName(); + + void propagate(); +}
\ No newline at end of file diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/InvocationManager.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/InvocationManager.java index 91995113b..7fc08384a 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/InvocationManager.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/InvocationManager.java @@ -11,6 +11,7 @@ package org.eclipse.qvtd.runtime.evaluation; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.ocl.pivot.evaluation.Executor; /** * An InvocationManager supervises the invocations of mappings, inhibiting re-executions and @@ -21,7 +22,14 @@ import org.eclipse.jdt.annotation.NonNull; */ public interface InvocationManager extends ExecutionVisitable { + void addInvoker(@NonNull InvocationConstructor constructor); @NonNull Interval createInterval(); + // @NonNull InvocationConstructor createInvoker(@NonNull InvocationConstructor constructor, int consumedConnections, @NonNull Interval interval, @NonNull Connection @NonNull ... connections); boolean flush(); - @NonNull Interval getDefaultInterval(); + @NonNull Executor getExecutor(); + @NonNull Iterable<@NonNull Interval> getIntervals(); + @NonNull Iterable<@NonNull InvocationConstructor> getInvokers(); + @NonNull Interval getRootInterval(); + // @Nullable Transformer getTransformer(); + void setWorkToDoAt(int intervalIndex); } 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 d5927662e..9af54fd6b 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 @@ -16,12 +16,13 @@ import java.util.List; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.ocl.pivot.ids.CollectionTypeId; +import org.eclipse.ocl.pivot.utilities.LabelUtil; import org.eclipse.qvtd.runtime.evaluation.AbstractTransformer; import org.eclipse.qvtd.runtime.evaluation.Connection; import org.eclipse.qvtd.runtime.evaluation.ExecutionVisitor; import org.eclipse.qvtd.runtime.evaluation.Interval; import org.eclipse.qvtd.runtime.evaluation.Invocation; -import org.eclipse.qvtd.runtime.evaluation.Invoker; +import org.eclipse.qvtd.runtime.evaluation.InvocationConstructor; /** * An AbstractConnection maintains the values between one or more sources, typically Mappings, that @@ -32,26 +33,37 @@ import org.eclipse.qvtd.runtime.evaluation.Invoker; * * Incremental update is supported by a revoke() or an append(), or a replace() of an appended value. */ -public abstract class AbstractConnectionInternal extends ConnectionLinkage implements Connection +public abstract class AbstractConnectionInternal implements Connection { protected static final int VALUE_INDEX = 0; protected static final int INDEX_INDEX = 1; protected static final int COUNT_INDEX = 2; protected final boolean debugAppends = AbstractTransformer.APPENDS.isActive(); + protected final boolean debugConsumes = AbstractTransformer.CONSUMES.isActive(); protected final @NonNull Interval interval; protected final @NonNull String name; protected final @NonNull CollectionTypeId typeId; /** + * Singly linked list element of connections awaiting propagation from their interval, null when last/unlinked. + */ + private @Nullable AbstractConnectionInternal nextConnection = null; + + /** + * True when this connection is part of the interval's list of connections awaiting propagation. + */ + private boolean isQueued = false; + + /** * The consumers of each appended value. */ - protected final @NonNull List<@NonNull Invoker> consumers = new ArrayList<>(); + protected final @NonNull List<@NonNull InvocationConstructor> consumers = new ArrayList<>(); /** - * The producers of values. + * The appenders of values. */ - protected final @NonNull List<@NonNull Invoker> producers = new ArrayList<>(); + protected final @NonNull List<@NonNull InvocationConstructor> appenders = new ArrayList<>(); /** * The earlist interval at which a consumer can execute. @@ -81,7 +93,14 @@ public abstract class AbstractConnectionInternal extends ConnectionLinkage imple } @Override - public void addConsumer(@NonNull Invoker consumer) { + public void addAppender(@NonNull InvocationConstructor appender) { + if (!appenders.contains(appender)) { + appenders.add(appender); + } + } + + @Override + public void addConsumer(@NonNull InvocationConstructor consumer) { // assert listOfValueAndConsumingInvocations.isEmpty() || listOfValueAndConsumingInvocations.get(0).; if (!consumers.contains(consumer)) { consumers.add(consumer); @@ -91,13 +110,6 @@ public abstract class AbstractConnectionInternal extends ConnectionLinkage imple } } - @Override - public void addProducer(@NonNull Invoker producer) { - if (!producers.contains(producer)) { - producers.add(producer); - } - } - /** * Remove the revoked entries and update the internal indexes accordingly. */ @@ -124,6 +136,14 @@ public abstract class AbstractConnectionInternal extends ConnectionLinkage imple valueAndConsumingInvocations.add(invocation); // FIXME empty status if all consumers at final index // invocationManager.dequeue(this); + if (debugConsumes) { + AbstractTransformer.CONSUMES.println(this + " => " + LabelUtil.getLabel(valueAndConsumingInvocations.get(VALUE_INDEX))); + } + } + + @Override + public @NonNull Iterable<@NonNull InvocationConstructor> getAppenders() { + return appenders; } @Override @@ -132,7 +152,7 @@ public abstract class AbstractConnectionInternal extends ConnectionLinkage imple } @Override - public @NonNull Iterable<@NonNull Invoker> getConsumers() { + public @NonNull Iterable<@NonNull InvocationConstructor> getConsumers() { return consumers; } @@ -141,9 +161,8 @@ public abstract class AbstractConnectionInternal extends ConnectionLinkage imple return name; } - @Override - public @NonNull Iterable<@NonNull Invoker> getProducers() { - return producers; + final @Nullable AbstractConnectionInternal getNextConnection() { + return nextConnection; } @Override @@ -152,24 +171,6 @@ public abstract class AbstractConnectionInternal extends ConnectionLinkage imple return valueAndConsumingInvocations != null ? valueAndConsumingInvocations.get(VALUE_INDEX) : null; } - /* @Override - public void insertAfter(@NonNull Interval predecessor) { - @NonNull AbstractIntervalInternal castPredecessor = (AbstractIntervalInternal)predecessor; - @NonNull AbstractIntervalInternal successor = castPredecessor.next; - successor.prev = this; - next = successor; - castPredecessor.next = this; - prev = castPredecessor; - } */ - - /* @Override - public void remove() { - prev.next = next; - next.prev = prev; - prev = this; - next = this; - } */ - @Override public int getValues() { return listOfValueAndConsumingInvocations.size(); @@ -177,32 +178,41 @@ public abstract class AbstractConnectionInternal extends ConnectionLinkage imple @Override public void propagate() { - for (@NonNull Invoker consumer : consumers) { + for (@NonNull InvocationConstructor consumer : consumers) { consumer.propagate(); } } - protected void queue() { - throw new UnsupportedOperationException(); - // if (nextConnection == this) { - // interval.queue(this); - // } + protected final void queue() { + if (!isQueued) { + isQueued = true; + interval.queue(this); + } + } + + void resetQueued() { + isQueued = false; + this.nextConnection = null; + } + + void setNextConnection(@NonNull AbstractConnectionInternal nextConnection) { + assert nextConnection != this; + assert isQueued; + this.nextConnection = nextConnection; } @Override public String toString() { StringBuilder s = new StringBuilder(); + s.append("<"); s.append(interval.getIndex()); - s.append(": "); + s.append(">"); s.append(name); - s.append(" : "); - s.append(typeId); - s.append(": "); - int i = 0; - for (@NonNull ConnectionLinkage nextConnectionLinkage = nextConnection; nextConnectionLinkage != this; nextConnectionLinkage = nextConnectionLinkage.nextConnection) { - i++; - } - s.append(i); + // s.append(" : "); + // s.append(typeId); + s.append("["); + s.append(listOfValueAndConsumingInvocations.size()); + s.append("]"); return s.toString(); } }
\ No newline at end of file diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractEnforcedConnectionInternal.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractEnforcedConnectionInternal.java index efbd493e9..9327e1820 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractEnforcedConnectionInternal.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractEnforcedConnectionInternal.java @@ -17,6 +17,7 @@ import java.util.Map; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.ocl.pivot.ids.CollectionTypeId; +import org.eclipse.ocl.pivot.utilities.LabelUtil; import org.eclipse.qvtd.runtime.evaluation.AbstractInvocation; import org.eclipse.qvtd.runtime.evaluation.AbstractTransformer; import org.eclipse.qvtd.runtime.evaluation.Interval; @@ -47,7 +48,7 @@ public abstract class AbstractEnforcedConnectionInternal extends AbstractConnect @Override public synchronized @NonNull Object append(@NonNull Object aValue) { if (debugAppends) { - AbstractTransformer.APPENDS.println(this + " - " + aValue); + AbstractTransformer.APPENDS.println(this + " <= " + LabelUtil.getLabel(aValue)); } List<@NonNull Object> valueAndConsumingInvocations = uniqueValues2valueAndConsumingInvocations.get(aValue); if (valueAndConsumingInvocations == null) { diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractIntervalInternal.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractIntervalInternal.java index 48a84f48e..ab3ca7713 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractIntervalInternal.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractIntervalInternal.java @@ -10,26 +10,50 @@ *******************************************************************************/ package org.eclipse.qvtd.runtime.internal.evaluation; +import java.util.ArrayList; +import java.util.List; + import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.ocl.pivot.ids.CollectionTypeId; import org.eclipse.qvtd.runtime.evaluation.AbstractTransformer; +import org.eclipse.qvtd.runtime.evaluation.Connection; +import org.eclipse.qvtd.runtime.evaluation.EnforcedConnection; import org.eclipse.qvtd.runtime.evaluation.ExecutionVisitor; 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.SlotState; +import org.eclipse.qvtd.runtime.evaluation.UnenforcedConnection; /** * AbstractIntervalInternal provides the shared implementation of the intrusive blocked/waiting linked list functionality. */ -public abstract class AbstractIntervalInternal extends ConnectionLinkage implements Interval +public abstract class AbstractIntervalInternal implements Interval { protected final boolean debugInvocations = AbstractTransformer.INVOCATIONS.isActive(); protected final @NonNull InvocationManager invocationManager; protected final int intervalIndex; + // public @Nullable SlotState debug_blockedBy = null; + + /** + * Head of a singly linked list element of connections awaiting propagation, null when empty. + */ + private @Nullable AbstractConnectionInternal headConnection = null; + + /** + * Tail of a singly linked list element of connections awaiting propagation, null when empty. + */ + private @Nullable AbstractConnectionInternal tailConnection = null; + + /** + * Head of doubly linked list of blocked invocations. + */ + private @NonNull List<@NonNull Connection> connections = new ArrayList<>(); + /** * Head of doubly linked list of blocked invocations. */ @@ -69,23 +93,36 @@ public abstract class AbstractIntervalInternal extends ConnectionLinkage impleme } @Override - public boolean flush() { - flushInternal(); - AbstractInvocationInternal blockedInvocation = blockedInvocations; - if (blockedInvocation == null) { - return true; + public @NonNull Connection createConnection(@NonNull String name, @NonNull CollectionTypeId typeId, boolean isEnforced) { + Connection connection; + if (isEnforced) { + connection = new EnforcedConnection(this, name, typeId); } - do { - if (debugInvocations) { - AbstractTransformer.INVOCATIONS.println("still blocked " + blockedInvocation + " by " + blockedInvocation.debug_blockedBy); - } - blockedInvocation = blockedInvocation.next; + else { + connection = new UnenforcedConnection(this, name, typeId); } - while (blockedInvocation != blockedInvocations); - return false; + connections.add(connection); + return connection; } - private void flushInternal() { + @Override + public boolean flush() { + while (headConnection != null) { + AbstractConnectionInternal nextConnection2; + synchronized(this) { + nextConnection2 = headConnection; + if (nextConnection2 != null) { + headConnection = nextConnection2.getNextConnection(); + if (headConnection == null) { + tailConnection = null; + } + nextConnection2.resetQueued(); + } + } + if (nextConnection2 != null) { + nextConnection2.propagate(); + } + } while (waitingInvocations != null) { AbstractInvocationInternal invocation = null; synchronized (this) { @@ -106,6 +143,23 @@ public abstract class AbstractIntervalInternal extends ConnectionLinkage impleme invoke(invocation, false); } } + AbstractInvocationInternal blockedInvocation = blockedInvocations; + if (blockedInvocation == null) { + return true; + } + do { + if (debugInvocations) { + AbstractTransformer.INVOCATIONS.println("still blocked " + blockedInvocation + " by " + blockedInvocation.debug_blockedBy); + } + blockedInvocation = blockedInvocation.next; + } + while (blockedInvocation != blockedInvocations); + return false; + } + + @Override + public @NonNull Iterable<@NonNull Connection> getConnections() { + return connections; } @Override @@ -131,7 +185,26 @@ public abstract class AbstractIntervalInternal extends ConnectionLinkage impleme AbstractTransformer.INVOCATIONS.println("done " + invocation); } if (doFlush) { - flushInternal(); + while (waitingInvocations != null) { + AbstractInvocationInternal invocation2 = null; + synchronized (this) { + AbstractInvocationInternal waitingInvocations2 = waitingInvocations; + if (waitingInvocations2 != null) { + invocation2 = waitingInvocations2; + waitingInvocations = waitingInvocations2.next; + if (waitingInvocations == invocation2) { + waitingInvocations = null; + } + invocation2.remove(); + } + } + if (invocation2 != null) { + if (debugInvocations) { + AbstractTransformer.INVOCATIONS.println("re-invoke " + invocation2); + } + invoke(invocation2, false); + } + } } } catch (InvocationFailedException e) { @@ -140,6 +213,42 @@ public abstract class AbstractIntervalInternal extends ConnectionLinkage impleme } @Override + public boolean isFlushed() { + if (tailConnection != null) { + return false; + } + // assert each connection fully propagatred + if (blockedInvocations != null) { + return false; + } + if (waitingInvocations != null) { + return false; + } + return true; + } + + public void queue() { + invocationManager.setWorkToDoAt(intervalIndex); + } + + @Override + public synchronized void queue(@NonNull Connection connection) { + AbstractConnectionInternal connection2 = (AbstractConnectionInternal)connection; + AbstractConnectionInternal tailConnection2 = tailConnection; + if (tailConnection2 == null) { // Empty list + assert headConnection == null; + assert connection2.getNextConnection() == null; + headConnection = connection2; + } + else { // New element + assert headConnection != null; + tailConnection2.setNextConnection(connection2); + } + tailConnection = connection2; + queue(); + } + + @Override public synchronized void queue(@NonNull Invocation invocation) { if (debugInvocations) { AbstractTransformer.INVOCATIONS.println("queue " + invocation); @@ -160,13 +269,45 @@ public abstract class AbstractIntervalInternal extends ConnectionLinkage impleme @Override public String toString() { StringBuilder s = new StringBuilder(); + s.append("<"); s.append(intervalIndex); - // s.append(": "); - // int i = 0; - // for (@NonNull ConnectionLinkage nextConnectionLinkage = nextConnection; nextConnectionLinkage != this; nextConnectionLinkage = nextConnectionLinkage.nextConnection) { - // i++; - // } - // s.append(i); + s.append("> "); + int i = 0; + for (AbstractConnectionInternal aConnection = headConnection; aConnection != null; aConnection = aConnection.getNextConnection()) { + i++; + if (i > 100) { + i = 999999; + break; + } + } + s.append(i); + s.append(" connections, "); + int j = 0; + for (AbstractInvocationInternal anInvocation = blockedInvocations; anInvocation != null; anInvocation = anInvocation.next) { + j++; + if (j > 100) { + j = 999999; + break; + } + if (anInvocation == blockedInvocations) { + break; + } + } + s.append(j); + s.append(" blocked, "); + int k = 0; + for (AbstractInvocationInternal anInvocation = waitingInvocations; anInvocation != null; anInvocation = anInvocation.next) { + k++; + if (k > 100) { + k = 999999; + break; + } + if (anInvocation == waitingInvocations) { + break; + } + } + s.append(k); + s.append(" waiting"); return s.toString(); } diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractInvocationConstructor.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractInvocationConstructor.java index b28271192..84a8f4112 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractInvocationConstructor.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractInvocationConstructor.java @@ -17,17 +17,38 @@ import java.util.Map; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.ocl.pivot.evaluation.Executor; import org.eclipse.ocl.pivot.ids.IdResolver; +import org.eclipse.qvtd.runtime.evaluation.Connection; +import org.eclipse.qvtd.runtime.evaluation.ExecutionVisitor; +import org.eclipse.qvtd.runtime.evaluation.Interval; import org.eclipse.qvtd.runtime.evaluation.Invocation; +import org.eclipse.qvtd.runtime.evaluation.InvocationConstructor; +import org.eclipse.qvtd.runtime.evaluation.InvocationManager; -public abstract class AbstractInvocationConstructor implements Invocation.Constructor +public abstract class AbstractInvocationConstructor implements InvocationConstructor { - public static abstract class Incremental extends AbstractInvocationConstructor implements Invocation.Constructor.Incremental + public static abstract class Incremental extends AbstractInvocationConstructor implements InvocationConstructor.Incremental { protected int sequence = 0; - public Incremental(@NonNull IdResolver idResolver, @NonNull String name) { - super(idResolver, name); + public Incremental(@NonNull Interval interval, @NonNull String name) { + super(interval, name); + } + + public void connect(@NonNull Connection @Nullable [] consumedConnections, @NonNull Connection @Nullable [] appendedConnections) { + if (consumedConnections != null) { + for (@NonNull Connection consumedConnection : consumedConnections) { + consumedConnection.addConsumer(this); + addConsumedConection(consumedConnection); + } + } + if (appendedConnections != null) { + for (@NonNull Connection appendedConnection : appendedConnections) { + appendedConnection.addAppender(this); + addAppendedConnection(appendedConnection); + } + } } @Override @@ -36,6 +57,7 @@ public abstract class AbstractInvocationConstructor implements Invocation.Constr } } + protected final @NonNull Interval interval; protected final IdResolver.@NonNull IdResolverExtension idResolver; protected final @NonNull String name; @@ -45,11 +67,50 @@ public abstract class AbstractInvocationConstructor implements Invocation.Constr * <br> * This map is used to inhibit repeated invocations. */ - private final @NonNull Map<@NonNull Integer, @NonNull Object> hashCode2invocations = new HashMap<@NonNull Integer, @NonNull Object>(); + private final @NonNull Map<@NonNull Integer, @NonNull Object> hashCode2invocations = new HashMap<>(); + + private final @NonNull List<@NonNull Invocation> debugInvocations = new ArrayList<>(); - protected AbstractInvocationConstructor(@NonNull IdResolver idResolver, @NonNull String name) { - this.idResolver = (IdResolver.IdResolverExtension)idResolver; + private final @NonNull List<@NonNull Connection> consumedConnections = new ArrayList<>(); + private final @NonNull List<@NonNull Connection> appendedConnections = new ArrayList<>(); + private int /*@LazyNonNull*/ [] oldConsumedIndexes = null; + + protected AbstractInvocationConstructor(@NonNull Interval interval, @NonNull String name) { + this.interval = interval; + InvocationManager invocationManager = interval.getInvocationManager(); + // TransformationExecutor executor = ClassUtil.nonNullState(invocationManager.getTransformer()).getExecutor(); + Executor executor = invocationManager.getExecutor(); + this.idResolver = (IdResolver.IdResolverExtension)executor.getIdResolver(); // FIXME null Transformer this.name = name; + invocationManager.addInvoker(this); + } + /* protected AbstractInvokerN(@NonNull Interval interval, @NonNull InvocationConstructor constructor, @NonNull Connection @NonNull [] consumedConnections, @NonNull Connection @NonNull [] appendedConnections) { + super(interval, constructor, appendedConnections); + this.consumedConnections = consumedConnections; + int consumedConnectionsSize = consumedConnections.length; + oldConsumedIndexes = new int[consumedConnectionsSize]; + for (int i = 0; i < consumedConnectionsSize; i++) { + oldConsumedIndexes[i] = 0; + } + } */ + + + @Override + public <R> R accept(@NonNull ExecutionVisitor<R> visitor) { + return visitor.visitInvocationConstructor(this); + } + + @Override + public void addAppendedConnection(@NonNull Connection connection) { + assert oldConsumedIndexes == null; + assert !appendedConnections.contains(connection); + appendedConnections.add(connection); + } + + @Override + public void addConsumedConection(@NonNull Connection connection) { + assert !consumedConnections.contains(connection); + consumedConnections.add(connection); } @Override @@ -78,6 +139,7 @@ public abstract class AbstractInvocationConstructor implements Invocation.Constr } } Invocation theInvocation = newInstance(argValues); + debugInvocations.add(theInvocation); if (zeroOrMoreInvocations == null) { hashCode2invocations.put(hashCode, theInvocation); } @@ -96,7 +158,97 @@ public abstract class AbstractInvocationConstructor implements Invocation.Constr } @Override + public @NonNull Invocation getInstance(@NonNull Object @NonNull [] values) { + // FIXME Move invokeOnce to constructor + Invocation theInvocation = newInstance(values); + // theInvocation.queue(); + debugInvocations.add(theInvocation); + return theInvocation; + } + + @Override + public @NonNull Interval getInterval() { + return interval; + } + + + @Override + public @NonNull Iterable<@NonNull Invocation> getInvocations() { + /* List<@NonNull Invocation> allInvocations = new ArrayList<>(); // FIXME provide a lazy iterable + for (Object zeroOrMoreInvocations : hashCode2invocations.values()) { + if (zeroOrMoreInvocations instanceof Invocation) { + allInvocations.add((Invocation)zeroOrMoreInvocations); + } + else if (zeroOrMoreInvocations instanceof List<?>) { + @SuppressWarnings("unchecked")@NonNull List<@NonNull Invocation> zeroOrMoreInvocations2 = (List<@NonNull Invocation>)zeroOrMoreInvocations; + allInvocations.addAll(zeroOrMoreInvocations2); + } + } */ + return debugInvocations; + } + + @Override public @NonNull String getName() { return name; } + + protected abstract @NonNull Invocation newInstance(@NonNull Object @NonNull [] values); + + @Override + public void propagate() { + int consumedConnectionsSize = consumedConnections.size(); + if (oldConsumedIndexes == null) { + oldConsumedIndexes = new int[consumedConnectionsSize]; + for (int i = 0; i < consumedConnectionsSize; i++) { + oldConsumedIndexes[i] = 0; + } + } + int @NonNull [] newConsumedIndexes = new int[consumedConnectionsSize]; + boolean hasWork = false; + for (int i = 0; i < consumedConnectionsSize; i++) { + Connection consumedConnection = consumedConnections.get(i); + newConsumedIndexes[i] = consumedConnection.getCapacity(); + if (newConsumedIndexes[i] > oldConsumedIndexes[i]) { + hasWork = true; + } + } + if (hasWork) { + int appendedConnectionsSize = appendedConnections.size(); + @NonNull Object @NonNull [] boundValues = new @NonNull Object[consumedConnectionsSize + appendedConnectionsSize]; + for (int i = 0; i < appendedConnectionsSize; i++) { + boundValues[consumedConnectionsSize+i] = appendedConnections.get(i); + } + int @NonNull [] consumeIndexes = new int[consumedConnectionsSize]; + propagate(0, newConsumedIndexes, consumeIndexes, boundValues); + for (int i = 0; i < consumedConnectionsSize; i++) { + oldConsumedIndexes[i] = newConsumedIndexes[i]; + } + } + } + private void propagate(int depth, int @NonNull [] newConsumedIndexes, int @NonNull [] consumeIndexes, @NonNull Object @NonNull [] boundValues) { + int consumedConnectionsSize = consumedConnections.size(); + if (depth < consumedConnectionsSize) { + Connection consumedConnection = consumedConnections.get(depth); + for (int i = oldConsumedIndexes[depth]; i < newConsumedIndexes[depth]; i++) { + consumeIndexes[depth] = i; + Object value = consumedConnection.getValue(i); + if (value != null) { // Revoked value may be null. + boundValues[depth] = value; + propagate(depth+1, newConsumedIndexes, consumeIndexes, boundValues); + } + } + } + else { + Invocation mappingInstance = getInstance(boundValues); + for (int i = 0; i < consumedConnectionsSize; i++) { + Connection consumedConnection = consumedConnections.get(i); + consumedConnection.consume(consumeIndexes[i], mappingInstance); + } + } + } + + @Override + public @NonNull String toString() { + return getName(); + } }
\ No newline at end of file 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 03e10f5f3..342198ada 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 @@ -47,6 +47,11 @@ public abstract class AbstractInvocationInternal implements Invocation } @Override + public void queue() { + interval.queue(this); + } + + @Override public void remove() { prev.next = next; next.prev = prev; diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractInvocationManagerInternal.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractInvocationManagerInternal.java index 7b071490b..127591bba 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractInvocationManagerInternal.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractInvocationManagerInternal.java @@ -14,13 +14,16 @@ import java.util.ArrayList; import java.util.List; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.ocl.pivot.evaluation.Executor; import org.eclipse.qvtd.runtime.evaluation.AbstractInvocationManager; +import org.eclipse.qvtd.runtime.evaluation.DefaultInterval; import org.eclipse.qvtd.runtime.evaluation.Interval; +import org.eclipse.qvtd.runtime.evaluation.InvocationConstructor; /** * InvocationManager supervises and provides thread safety for the lists of blocked and waiting invocations. */ -public class AbstractInvocationManagerInternal extends AbstractInvocationManager +public abstract class AbstractInvocationManagerInternal extends AbstractInvocationManager { /** * The distinct intervals of the schedule. Wherever possible work for earlier intervals is completed before that @@ -28,28 +31,92 @@ public class AbstractInvocationManagerInternal extends AbstractInvocationManager */ private final @NonNull List<@NonNull Interval> intervals = new ArrayList<>(); + /** + * The invokers that create invocations. + */ + private final @NonNull List<@NonNull InvocationConstructor> invokers = new ArrayList<>(); + + private volatile int nextIndex = Integer.MAX_VALUE; + + protected final @NonNull Executor executor; - private /*@LazyNonNull*/ Interval defaultInterval = null; + protected AbstractInvocationManagerInternal(@NonNull Executor executor) { + this.executor = executor; + } + + @Override + public void addInvoker(@NonNull InvocationConstructor constructor) { + assert !invokers.contains(constructor); + invokers.add(constructor); + } @Override public @NonNull Interval createInterval() { - assert defaultInterval == null; - Interval interval = new AbstractIntervalInternal(this, intervals.size()) {}; + Interval interval = new DefaultInterval(this, intervals.size()); intervals.add(interval); return interval; } + /* @Override + public @NonNull InvocationConstructor createInvoker(@NonNull InvocationConstructor constructor, int consumedConnections, @NonNull Interval interval, @NonNull Connection @NonNull ... connections) { + InvocationConstructor invoker; + if (consumedConnections == 1) { + invoker = new AbstractInvoker1(interval, constructor, connections[0], Arrays.copyOfRange(connections, 1, connections.length)); + } + else { + invoker = new AbstractInvokerN(interval, constructor, Arrays.copyOf(connections, consumedConnections), Arrays.copyOfRange(connections, consumedConnections, connections.length)); + } + invokers.add(invoker); + return invoker; + } */ + @Override public boolean flush() { - return getDefaultInterval().flush(); + for (int index = nextIndex; index < intervals.size(); index = nextIndex) { + nextIndex = index+1; + Interval nextInterval = intervals.get(index); + nextInterval.flush(); // May set nextIndex back to 'same' or even earlier + } + for (@NonNull Interval interval : intervals) { + if (!interval.isFlushed()) { + return false; + } + } + return true; } @Override - public @NonNull Interval getDefaultInterval() { - Interval defaultInterval2 = defaultInterval; - if (defaultInterval2 == null) { - defaultInterval2 = defaultInterval = createInterval(); + public @NonNull Executor getExecutor() { + return executor; + } + + @Override + public @NonNull Iterable<@NonNull Interval> getIntervals() { + return intervals; + } + + @Override + public @NonNull Iterable<@NonNull InvocationConstructor> getInvokers() { + return invokers; + } + + @Override + public @NonNull Interval getRootInterval() { + if (intervals.size() <= 0) { + createInterval(); + } + return intervals.get(0); + } + + // @Override + // public @Nullable Transformer getTransformer() { + // return transformer; + // } + + @Override + public void setWorkToDoAt(int intervalIndex) { + if (intervalIndex < nextIndex) { + nextIndex = intervalIndex; } - return defaultInterval2; } }
\ No newline at end of file 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 f4b6aecb7..e644dfb98 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 @@ -48,6 +48,7 @@ import org.eclipse.qvtd.runtime.evaluation.AbstractTransformer; import org.eclipse.qvtd.runtime.evaluation.AbstractTypedModelInstance; import org.eclipse.qvtd.runtime.evaluation.ExecutionVisitable; import org.eclipse.qvtd.runtime.evaluation.Invocation; +import org.eclipse.qvtd.runtime.evaluation.InvocationConstructor; import org.eclipse.qvtd.runtime.evaluation.InvocationFailedException; import org.eclipse.qvtd.runtime.evaluation.InvocationManager; import org.eclipse.qvtd.runtime.evaluation.ObjectManager; @@ -539,7 +540,7 @@ public abstract class AbstractTransformerInternal extends AbstractModelManager i * Create the InvocationManager. Creates a LazyInvocationManager by default. */ protected @NonNull InvocationManager createInvocationManager() { - return new LazyInvocationManager(); + return new LazyInvocationManager(executor); } protected SetValue.@NonNull Accumulator createUnenforcedSetAccumulatorValue(@NonNull CollectionTypeId typeId) { @@ -723,12 +724,26 @@ public abstract class AbstractTransformerInternal extends AbstractModelManager i return false; } + /* protected void install(@NonNull InvocationConstructor constructor, int consumedConnections, @NonNull Connection @NonNull ... connections) { + // InvocationConstructor invoker = invocationManager.createInvoker(constructor, consumedConnections, interval, connections); + for (int i = 0; i < consumedConnections; i++) { + Connection consumedConnection = connections[i]; + consumedConnection.addConsumer(constructor); + constructor.addConsumedConection(consumedConnection); + } + for (int i = consumedConnections; i < connections.length; i++) { + Connection appendedConnection = connections[i]; + appendedConnection.addProducer(constructor); + constructor.addAppendedConnection(appendedConnection); + } + } */ + /** * Invoke a mapping with the given constructor with a given set of boundValues once. This shortform of invokeOnce * should only be used when it is known that recursive invocation is impossible. */ - public <@Nullable T extends Invocation> void invoke(Invocation.@NonNull Constructor constructor, @NonNull Object @NonNull ... boundValues) { - @NonNull Invocation invocation = constructor.newInstance(boundValues); + public <@Nullable T extends Invocation> void invoke(@NonNull InvocationConstructor constructor, @NonNull Object @NonNull ... boundValues) { + @NonNull Invocation invocation = constructor.getInstance(boundValues); if (debugInvocations) { AbstractTransformer.INVOCATIONS.println("invoke " + invocation); } @@ -738,7 +753,7 @@ public abstract class AbstractTransformerInternal extends AbstractModelManager i /** * Invoke a mapping with the given constructor with a given set of boundValues once. Repeated invocation attempts are ignored. */ - public void invokeOnce(Invocation.@NonNull Constructor constructor, @NonNull Object @NonNull ... boundValues) { + public void invokeOnce(@NonNull InvocationConstructor constructor, @NonNull Object @NonNull ... boundValues) { @Nullable Invocation invocation = constructor.getFirstInvocation(boundValues); if (invocation != null) { if (debugInvocations) { diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractUnenforcedConnectionInternal.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractUnenforcedConnectionInternal.java index 018dc3097..b1d1011f8 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractUnenforcedConnectionInternal.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractUnenforcedConnectionInternal.java @@ -15,6 +15,7 @@ import java.util.List; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.ocl.pivot.ids.CollectionTypeId; +import org.eclipse.ocl.pivot.utilities.LabelUtil; import org.eclipse.qvtd.runtime.evaluation.AbstractInvocation; import org.eclipse.qvtd.runtime.evaluation.AbstractTransformer; import org.eclipse.qvtd.runtime.evaluation.Interval; @@ -42,7 +43,7 @@ public abstract class AbstractUnenforcedConnectionInternal extends AbstractConne @Override public synchronized @NonNull Object append(@NonNull Object aValue) { if (debugAppends) { - AbstractTransformer.APPENDS.println(this + " - " + aValue); + AbstractTransformer.APPENDS.println(this + " <= " + LabelUtil.getLabel(aValue)); } List<@NonNull Object> valueAndConsumingInvocations = new ArrayList<>(); valueAndConsumingInvocations.add(aValue); // VALUE_INDEX diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/ConnectionLinkage.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/ConnectionLinkage.java deleted file mode 100644 index f1ecc3817..000000000 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/ConnectionLinkage.java +++ /dev/null @@ -1,18 +0,0 @@ -/******************************************************************************* - * 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.runtime.internal.evaluation; - -import org.eclipse.jdt.annotation.NonNull; - -class ConnectionLinkage -{ - @NonNull ConnectionLinkage nextConnection = this; -}
\ No newline at end of file diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/IncrementalInvocationManager.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/IncrementalInvocationManager.java index e5391629c..c5fa434bf 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/IncrementalInvocationManager.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/IncrementalInvocationManager.java @@ -10,9 +10,15 @@ *******************************************************************************/ package org.eclipse.qvtd.runtime.internal.evaluation; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.ocl.pivot.evaluation.Executor; + /** * InvocationManager supervises and provides thread safety for the lists of blocked and waiting invocations. */ public class IncrementalInvocationManager extends AbstractInvocationManagerInternal { + public IncrementalInvocationManager(@NonNull Executor executor) { + super(executor); + } }
\ 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 c4be78867..8fce944fa 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 @@ -22,6 +22,7 @@ import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.ocl.pivot.oclstdlib.OCLstdlibPackage; +import org.eclipse.ocl.pivot.utilities.LabelUtil; import org.eclipse.qvtd.runtime.evaluation.AbstractObjectManager; import org.eclipse.qvtd.runtime.evaluation.AbstractSlotState; import org.eclipse.qvtd.runtime.evaluation.AbstractTransformer; @@ -631,7 +632,7 @@ public class IncrementalObjectManager extends AbstractObjectManager public synchronized void assigned(@NonNull Object eObject, /*@NonNull*/ EStructuralFeature eFeature, @Nullable Object ecoreValue, @Nullable Object childKey) { assert eFeature != null; if (debugInvocations) { - AbstractTransformer.INVOCATIONS.println("assigned " + eFeature.getEContainingClass().getName() + "::" + eFeature.getName() + " for " + eObject + " = " + ecoreValue); + AbstractTransformer.INVOCATIONS.println("assigned " + eFeature.getEContainingClass().getName() + "::" + eFeature.getName() + " for " + LabelUtil.getLabel(eObject) + " = " + LabelUtil.getLabel(ecoreValue)); } Map<EStructuralFeature, BasicSlotState> objectState = getObjectState(eObject); BasicSlotState slotState = objectState.get(eFeature); @@ -821,7 +822,7 @@ public class IncrementalObjectManager extends AbstractObjectManager public synchronized void getting(@NonNull Object eObject, /*@NonNull*/ EStructuralFeature eFeature, boolean isOpposite) { assert eFeature != null; if (debugInvocations) { - AbstractTransformer.INVOCATIONS.println("getting " + eFeature.getEContainingClass().getName() + "::" + eFeature.getName() + " for " + eObject); + AbstractTransformer.INVOCATIONS.println("getting " + eFeature.getEContainingClass().getName() + "::" + eFeature.getName() + " for " + LabelUtil.getLabel(eObject)); } SlotState slotState = getSlotState(eObject, eFeature); slotState.getting(eObject, eFeature); diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/LazyInvocationManager.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/LazyInvocationManager.java index 9ec164b11..3f768a968 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/LazyInvocationManager.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/LazyInvocationManager.java @@ -10,9 +10,15 @@ *******************************************************************************/ package org.eclipse.qvtd.runtime.internal.evaluation; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.ocl.pivot.evaluation.Executor; + /** * InvocationManager supervises and provides thread safety for the lists of blocked and waiting invocations. */ public class LazyInvocationManager extends AbstractInvocationManagerInternal { + public LazyInvocationManager(@NonNull Executor executor) { + super(executor); + } }
\ No newline at end of file diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/LazyObjectManager.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/LazyObjectManager.java index 15705ceda..84beab98d 100644 --- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/LazyObjectManager.java +++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/LazyObjectManager.java @@ -32,6 +32,7 @@ import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.ocl.pivot.internal.utilities.PivotConstantsInternal; import org.eclipse.ocl.pivot.oclstdlib.OCLstdlibPackage; +import org.eclipse.ocl.pivot.utilities.LabelUtil; import org.eclipse.ocl.pivot.utilities.ValueUtil; import org.eclipse.ocl.pivot.values.IntegerValue; import org.eclipse.ocl.pivot.values.UnlimitedNaturalValue; @@ -723,7 +724,7 @@ public class LazyObjectManager extends AbstractObjectManager public synchronized void assigned(@NonNull Object eObject, /*@NonNull*/ EStructuralFeature eFeature, @Nullable Object ecoreValue, @Nullable Object childKey) { assert eFeature != null; if (debugInvocations) { - AbstractTransformer.INVOCATIONS.println("assigned " + eFeature.getEContainingClass().getName() + "::" + eFeature.getName() + " for " + eObject + " = " + ecoreValue); + AbstractTransformer.INVOCATIONS.println("assigned " + eFeature.getEContainingClass().getName() + "::" + eFeature.getName() + " for " + LabelUtil.getLabel(eObject) + " = " + LabelUtil.getLabel(ecoreValue)); } Map<@NonNull EStructuralFeature, @NonNull SlotState> objectState = getObjectState(eObject); SlotState slotState = objectState.get(eFeature); @@ -1003,7 +1004,7 @@ public class LazyObjectManager extends AbstractObjectManager public synchronized void getting(@NonNull Object eObject, /*@NonNull*/ EStructuralFeature eFeature, boolean isOpposite) { assert eFeature != null; if (debugInvocations) { - AbstractTransformer.INVOCATIONS.println("getting " + eFeature.getEContainingClass().getName() + "::" + eFeature.getName() + (isOpposite ? "<opposite> " : "") + " for " + eObject); + AbstractTransformer.INVOCATIONS.println("getting " + eFeature.getEContainingClass().getName() + "::" + eFeature.getName() + (isOpposite ? "<opposite> " : "") + " for " + LabelUtil.getLabel(eObject)); } if (isOpposite) { eFeature = getEOppositeReference((EReference) eFeature); 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 54e612ba3..d4fda4589 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 @@ -49,7 +49,6 @@ import org.eclipse.qvtd.xtext.qvtbase.tests.LoadTestCase; 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 junit.framework.TestCase; /** @@ -319,4 +318,44 @@ public class QVTiCompilerTests extends LoadTestCase myQVT.saveOutput(tx, "talltree", outputModelURI, referenceModelURI, null); myQVT.dispose(); } + + /* 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 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 = myQVT.generateCode(asTransformation, true); + Transformer tx = myQVT.createTransformer(txClass); + myQVT.loadInput(tx, "tree", inputModelURI); + tx.run(); + myQVT.saveOutput(tx, "talltree", outputModelURI, referenceModelURI, null); + myQVT.dispose(); + } */ + + /* public void testCG_Tree2TallTreeInstallManual_qvti() throws Exception { + AbstractTransformer.APPENDS.setState(true); + AbstractTransformer.CONSUMES.setState(true); + AbstractTransformer.EXCEPTIONS.setState(true); + AbstractTransformer.INVOCATIONS.setState(true); + MyQVT myQVT = createQVT(); + // 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; + 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/Tree2TallTree/Tree2TallTreeInstall.qvti b/tests/org.eclipse.qvtd.xtext.qvtimperative.tests/src/org/eclipse/qvtd/xtext/qvtimperative/tests/Tree2TallTree/Tree2TallTreeInstall.qvti new file mode 100644 index 000000000..f4e53f6de --- /dev/null +++ b/tests/org.eclipse.qvtd.xtext.qvtimperative.tests/src/org/eclipse/qvtd/xtext/qvtimperative/tests/Tree2TallTree/Tree2TallTreeInstall.qvti @@ -0,0 +1,55 @@ +import 'Tree.ecore'::tree; +import 'TallTree.ecore'::talltree; +import 'Tree2TallTree.ecore'::tree2talltree; + +transformation Tree2TallTreeInstall { + check tree imports tree; + enforce talltree imports talltree; + tree2talltree imports tree2talltree; +} + +map __root__ in Tree2TallTreeInstall { + buffer nodes := tree.objectsOfKind(Node)->sortedBy(name); + buffer node2tallNodes : Sequence(tree2talltree::Node2TallNode); + install Node2MiddleNode { + node consumes nodes; + node2tallNodes appendsTo node2tallNodes; + } + install Edge2MiddleEdge { + node consumes nodes; + } + install MiddleNode2TallNode { + node2tallNode consumes node2tallNodes; + } +} + +map Node2MiddleNode in Tree2TallTreeInstall { + guard:tree node : Node; + append node2tallNodes : Sequence(tree2talltree::Node2TallNode); + new:tree2talltree node2tallNode : Node2TallNode; + set node2tallNode.node := node; + set node2tallNode.name := node.name; + add node2tallNodes += node2tallNode; +} + +map Edge2MiddleEdge in Tree2TallTreeInstall { + guard:tree node : Node; + var node2tallNode : Node2TallNode := node.Node2TallNode; + check node.parent <> null; + notify set node2tallNode.parent := node.parent.Node2TallNode; +-- node2tallNode.name := node.name; +} + +map MiddleNode2TallNode in Tree2TallTreeInstall { + guard:tree2talltree node2tallNode : Node2TallNode; + var tallNode_name : String := node2tallNode.name; + observe Node2TallNode::children, Node2TallNode::tallNode + var tallNode_children : Set(TallNode) := node2tallNode.children?.tallNode->asSet(); + observe Node2TallNode::children, Node2TallNode::tallNode, TallNode::height + var tallNode_height : Integer := if node2tallNode.children->notEmpty() then node2tallNode.children.tallNode.height->max() + 1 else 0 endif; + new:talltree tallNode : TallNode; + notify set node2tallNode.tallNode := tallNode; + set tallNode.name := tallNode_name; + set tallNode.children := tallNode_children; + notify set tallNode.height := tallNode_height; +} 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 new file mode 100644 index 000000000..cfee5f673 --- /dev/null +++ b/tests/org.eclipse.qvtd.xtext.qvtimperative.tests/src/org/eclipse/qvtd/xtext/qvtimperative/tests/Tree2TallTree/Tree2TallTreeInstallManual.java @@ -0,0 +1,511 @@ +/******************************************************************************* + * «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.Map; + +import org.eclipse.emf.ecore.EcorePackage; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.ocl.pivot.evaluation.Executor; +import org.eclipse.ocl.pivot.ids.ClassId; +import org.eclipse.ocl.pivot.ids.IdManager; +import org.eclipse.ocl.pivot.ids.IdResolver; +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.Interval; +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*/ org.eclipse.ocl.pivot.ids.@org.eclipse.jdt.annotation.NonNull RootPackageId PACKid_$metamodel$ = IdManager.getRootPackageId("$metamodel$"); + public static final /*@NonInvalid*/ org.eclipse.ocl.pivot.ids.@org.eclipse.jdt.annotation.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*/ org.eclipse.ocl.pivot.ids.@org.eclipse.jdt.annotation.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*/ org.eclipse.ocl.pivot.ids.@org.eclipse.jdt.annotation.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*/ org.eclipse.ocl.pivot.ids.@org.eclipse.jdt.annotation.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*/ org.eclipse.ocl.pivot.ids.@org.eclipse.jdt.annotation.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*/ org.eclipse.ocl.pivot.ids.@org.eclipse.jdt.annotation.NonNull ClassId CLSSid_Class = PACKid_$metamodel$.getClassId("Class", 0); + public static final /*@NonInvalid*/ org.eclipse.ocl.pivot.ids.@org.eclipse.jdt.annotation.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*/ org.eclipse.ocl.pivot.ids.@org.eclipse.jdt.annotation.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*/ org.eclipse.ocl.pivot.ids.@org.eclipse.jdt.annotation.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*/ org.eclipse.ocl.pivot.ids.@org.eclipse.jdt.annotation.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*/ org.eclipse.ocl.pivot.ids.@org.eclipse.jdt.annotation.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*/ org.eclipse.ocl.pivot.values.@org.eclipse.jdt.annotation.NonNull IntegerValue INT_0 = ValueUtil.integerValueOf("0"); + public static final /*@NonInvalid*/ org.eclipse.ocl.pivot.values.@org.eclipse.jdt.annotation.NonNull IntegerValue INT_1 = ValueUtil.integerValueOf("1"); + public static final /*@NonInvalid*/ org.eclipse.ocl.pivot.ids.@org.eclipse.jdt.annotation.NonNull CollectionTypeId BAG_CLSSid_TallNode = TypeId.BAG.getSpecializedId(CLSSid_TallNode); + public static final /*@NonInvalid*/ org.eclipse.ocl.pivot.ids.@org.eclipse.jdt.annotation.NonNull CollectionTypeId BAG_DATAid_EInt = TypeId.BAG.getSpecializedId(DATAid_EInt); + public static final /*@NonInvalid*/ org.eclipse.ocl.pivot.ids.@org.eclipse.jdt.annotation.NonNull CollectionTypeId ORD_CLSSid_Node = TypeId.ORDERED_SET.getSpecializedId(CLSSid_Node); + public static final /*@NonInvalid*/ org.eclipse.ocl.pivot.ids.@org.eclipse.jdt.annotation.NonNull CollectionTypeId SEQ_CLSSid_Node2TallNode = TypeId.SEQUENCE.getSpecializedId(CLSSid_Node2TallNode); + public static final /*@NonInvalid*/ org.eclipse.ocl.pivot.ids.@org.eclipse.jdt.annotation.NonNull CollectionTypeId SET_CLSSid_Node = TypeId.SET.getSpecializedId(CLSSid_Node); + public static final /*@NonInvalid*/ org.eclipse.ocl.pivot.ids.@org.eclipse.jdt.annotation.NonNull CollectionTypeId SET_CLSSid_Node2TallNode = TypeId.SET.getSpecializedId(CLSSid_Node2TallNode); + public static final /*@NonInvalid*/ org.eclipse.ocl.pivot.ids.@org.eclipse.jdt.annotation.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; + protected final AbstractInvocationConstructor.@NonNull Incremental CTOR_Node2MiddleNode; + protected final AbstractInvocationConstructor.@NonNull Incremental CTOR_Edge2MiddleEdge; + protected final AbstractInvocationConstructor.@NonNull Incremental CTOR_MiddleNode2TallNode; + + protected final @NonNull Interval interval0; + protected final @NonNull Interval interval1; + protected final @NonNull Interval interval2; + protected final @NonNull Interval interval3; + + public Tree2TallTreeInstallManual(final @NonNull TransformationExecutor executor) { + super(executor, new @NonNull String[] {"tree", "talltree", "tree2talltree"}, null, classIndex2classId, classIndex2allClassIndexes); + interval0 = invocationManager.createInterval(); + interval1 = invocationManager.createInterval(); + interval2 = invocationManager.createInterval(); + interval3 = invocationManager.createInterval(); + CTOR_Root = new AbstractInvocationConstructor.Incremental(interval0, "__root__") + { + @Override + public @NonNull MAP___root__ newInstance(@NonNull Object @NonNull [] values) { + return new MAP___root__(interval, this, values); + } + }; + CTOR_Node2MiddleNode = new AbstractInvocationConstructor.Incremental(interval1, "Node2MiddleNode") + { + @Override + public @NonNull MAP_Node2MiddleNode newInstance(@NonNull Object @NonNull [] values) { + return new MAP_Node2MiddleNode(interval, this, values); + } + }; + CTOR_Edge2MiddleEdge = new AbstractInvocationConstructor.Incremental(interval2, "Edge2MiddleEdge") + { + @Override + public @NonNull MAP_Edge2MiddleEdge newInstance(@NonNull Object @NonNull [] values) { + return new MAP_Edge2MiddleEdge(interval, this, values); + } + }; + CTOR_MiddleNode2TallNode = new AbstractInvocationConstructor.Incremental(interval3, "MiddleNode2TallNode") + { + @Override + public @NonNull MAP_MiddleNode2TallNode newInstance(@NonNull Object @NonNull [] values) { + return new MAP_MiddleNode2TallNode(interval, this, values); + } + }; + } + + @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.getInstance(new @NonNull Object[]{}); + // new MAP___root__(new @NonNull Object[0]); + // 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 + { + protected final @NonNull Connection nodes; + + public MAP___root__(@NonNull Interval interval, InvocationConstructor.@org.eclipse.jdt.annotation.NonNull Incremental constructor, @NonNull Object @NonNull [] boundValues) { + super(interval, constructor); + nodes = interval.createConnection("nodes", ORD_CLSSid_Node, false); + } + + @Override + public boolean execute() { + try { + final /*@NonInvalid*/ org.eclipse.ocl.pivot.ids.@org.eclipse.jdt.annotation.NonNull IdResolver idResolver = executor.getIdResolver(); + final /*@NonInvalid*/ org.eclipse.ocl.pivot.@org.eclipse.jdt.annotation.NonNull Class TYP_tree_c_c_Node_0 = idResolver.getClass(CLSSid_Node, null); + final /*@NonInvalid*/ org.eclipse.ocl.pivot.@org.eclipse.jdt.annotation.NonNull StandardLibrary standardLibrary = idResolver.getStandardLibrary(); + // connection variables + final /*@NonInvalid*/ org.eclipse.ocl.pivot.values.@org.eclipse.jdt.annotation.NonNull SetValue objectsOfKind = ModelObjectsOfKindOperation.INSTANCE.evaluate(executor, SET_CLSSid_Node, models[0/*tree*/], TYP_tree_c_c_Node_0); + final org.eclipse.ocl.pivot.@org.eclipse.jdt.annotation.NonNull Class TYPE_sortedBy_0 = executor.getStaticTypeOf(objectsOfKind); + final LibraryIteration.@org.eclipse.jdt.annotation.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*/ java.lang.@org.eclipse.jdt.annotation.Nullable Object _1) { + final /*@NonInvalid*/ tree2talltree.tree.@org.eclipse.jdt.annotation.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*/ java.lang.@org.eclipse.jdt.annotation.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*/ org.eclipse.ocl.pivot.values.@org.eclipse.jdt.annotation.NonNull OrderedSetValue sortedBy = ClassUtil.nonNullState((OrderedSetValue)IMPL_sortedBy_0.evaluateIteration(MGR_sortedBy_0)); + for (tree2talltree.tree.@org.eclipse.jdt.annotation.NonNull Node iterator : ValueUtil.typedIterable(Node.class, sortedBy)) { + nodes.append(iterator); + } + final @NonNull Connection node2tallNodes_1 = interval2.createConnection("node2tallNodes_1", SEQ_CLSSid_Node2TallNode, false); + // mapping statements + CTOR_Node2MiddleNode.connect(new @NonNull Connection[]{nodes}, new @NonNull Connection[]{node2tallNodes_1}); + CTOR_Edge2MiddleEdge.connect(new @NonNull Connection[]{nodes}, null); + CTOR_MiddleNode2TallNode.connect(new @NonNull Connection[]{node2tallNodes_1}, null); + final /*@Thrown*/ java.lang.@org.eclipse.jdt.annotation.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*/ tree2talltree.tree.@org.eclipse.jdt.annotation.NonNull Node node; + protected final @NonNull Connection node2tallNodes; + + public MAP_Node2MiddleNode(@NonNull Interval interval, InvocationConstructor.@org.eclipse.jdt.annotation.NonNull Incremental constructor, @NonNull Object @NonNull [] boundValues) { + super(interval, constructor); + node = (Node)boundValues[0]; + node2tallNodes = (Connection)boundValues[1]; + } + + @Override + public boolean execute() { + try { + // creations + final /*@Thrown*/ tree2talltree.tree2talltree.@org.eclipse.jdt.annotation.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*/ java.lang.@org.eclipse.jdt.annotation.NonNull String name = node.getName(); + objectManager.got(MAP_Node2MiddleNode.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*/ java.lang.@org.eclipse.jdt.annotation.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*/ tree2talltree.tree.@org.eclipse.jdt.annotation.NonNull Node node_0; + + public MAP_Edge2MiddleEdge(@NonNull Interval interval, InvocationConstructor.@org.eclipse.jdt.annotation.NonNull Incremental constructor, @NonNull Object @NonNull [] boundValues) { + super(interval, constructor); + node_0 = (Node)boundValues[0]; + } + + @Override + public boolean execute() { + try { + final /*@Thrown*/ tree2talltree.tree2talltree.@org.eclipse.jdt.annotation.NonNull Node2TallNode Node2TallNode = ClassUtil.nonNullState (OPPOSITE_OF_Node2TallNode_node.get(node_0)); + objectManager.got(MAP_Edge2MiddleEdge.this, node_0, Tree2talltreePackage.Literals.NODE2_TALL_NODE__NODE, Node2TallNode); + final /*@Thrown*/ tree2talltree.tree.@org.eclipse.jdt.annotation.Nullable Node parent = node_0.getParent(); + objectManager.got(MAP_Edge2MiddleEdge.this, node_0, TreePackage.Literals.NODE__PARENT, parent); + final /*@Thrown*/ boolean ne = parent != null; + /*@Thrown*/ java.lang.@org.eclipse.jdt.annotation.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*/ tree2talltree.tree2talltree.@org.eclipse.jdt.annotation.NonNull Node2TallNode Node2TallNode_0 = ClassUtil.nonNullState (OPPOSITE_OF_Node2TallNode_node.get(parent)); + objectManager.got(MAP_Edge2MiddleEdge.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*/ java.lang.@org.eclipse.jdt.annotation.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*/ tree2talltree.tree2talltree.@org.eclipse.jdt.annotation.NonNull Node2TallNode node2tallNode; + + public MAP_MiddleNode2TallNode(@NonNull Interval interval, InvocationConstructor.@org.eclipse.jdt.annotation.NonNull Incremental constructor, @NonNull Object @NonNull [] boundValues) { + super(interval, constructor); + node2tallNode = (Node2TallNode)boundValues[0]; + } + + @Override + public boolean execute() { + try { + final /*@NonInvalid*/ org.eclipse.ocl.pivot.ids.@org.eclipse.jdt.annotation.NonNull IdResolver idResolver = executor.getIdResolver(); + @SuppressWarnings("null") + final /*@Thrown*/ java.lang.@org.eclipse.jdt.annotation.NonNull String name = node2tallNode.getName(); + objectManager.got(MAP_MiddleNode2TallNode.this, node2tallNode, Tree2talltreePackage.Literals.NODE2_TALL_NODE__NAME, name); + objectManager.getting(node2tallNode, Tree2talltreePackage.Literals.NODE2_TALL_NODE__CHILDREN, false); + @SuppressWarnings("null") + final /*@Thrown*/ java.util.@org.eclipse.jdt.annotation.NonNull List<Node2TallNode> children_0 = node2tallNode.getChildren(); + objectManager.got(MAP_MiddleNode2TallNode.this, node2tallNode, Tree2talltreePackage.Literals.NODE2_TALL_NODE__CHILDREN, children_0); + final /*@Thrown*/ org.eclipse.ocl.pivot.values.@org.eclipse.jdt.annotation.NonNull SetValue BOXED_children_0 = idResolver.createSetOfAll(SET_CLSSid_Node2TallNode, children_0); + final /*@Thrown*/ org.eclipse.ocl.pivot.values.@org.eclipse.jdt.annotation.NonNull SetValue safe_collect_sources = (SetValue)CollectionExcludingOperation.INSTANCE.evaluate(BOXED_children_0, (Object)null); + /*@Thrown*/ BagValue.@org.eclipse.jdt.annotation.NonNull Accumulator accumulator = ValueUtil.createBagAccumulatorValue(BAG_CLSSid_TallNode); + @NonNull Iterator<Object> ITERATOR__1 = safe_collect_sources.iterator(); + /*@Thrown*/ org.eclipse.ocl.pivot.values.@org.eclipse.jdt.annotation.NonNull BagValue collect; + while (true) { + if (!ITERATOR__1.hasNext()) { + collect = accumulator; + break; + } + @SuppressWarnings("null") + /*@NonInvalid*/ tree2talltree.tree2talltree.@org.eclipse.jdt.annotation.NonNull Node2TallNode _1 = (Node2TallNode)ITERATOR__1.next(); + /** + * tallNode + */ + objectManager.getting(_1, Tree2talltreePackage.Literals.NODE2_TALL_NODE__TALL_NODE, false); + @SuppressWarnings("null") + final /*@Thrown*/ tree2talltree.talltree.@org.eclipse.jdt.annotation.NonNull TallNode tallNode_0 = _1.getTallNode(); + objectManager.got(MAP_MiddleNode2TallNode.this, _1, Tree2talltreePackage.Literals.NODE2_TALL_NODE__TALL_NODE, tallNode_0); + // + accumulator.add(tallNode_0); + } + final /*@Thrown*/ org.eclipse.ocl.pivot.values.@org.eclipse.jdt.annotation.NonNull SetValue asSet = CollectionAsSetOperation.INSTANCE.evaluate(collect); + final /*@Thrown*/ boolean notEmpty = CollectionNotEmptyOperation.INSTANCE.evaluate(BOXED_children_0).booleanValue(); + /*@Thrown*/ org.eclipse.ocl.pivot.values.@org.eclipse.jdt.annotation.NonNull IntegerValue symbol_0; + if (notEmpty) { + /*@Thrown*/ BagValue.@org.eclipse.jdt.annotation.NonNull Accumulator accumulator_0 = ValueUtil.createBagAccumulatorValue(BAG_CLSSid_TallNode); + @NonNull Iterator<Object> ITERATOR__1_0 = BOXED_children_0.iterator(); + /*@Thrown*/ org.eclipse.ocl.pivot.values.@org.eclipse.jdt.annotation.NonNull BagValue collect_1; + while (true) { + if (!ITERATOR__1_0.hasNext()) { + collect_1 = accumulator_0; + break; + } + @SuppressWarnings("null") + /*@NonInvalid*/ tree2talltree.tree2talltree.@org.eclipse.jdt.annotation.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*/ tree2talltree.talltree.@org.eclipse.jdt.annotation.NonNull TallNode tallNode_1 = _1_0.getTallNode(); + objectManager.got(MAP_MiddleNode2TallNode.this, _1_0, Tree2talltreePackage.Literals.NODE2_TALL_NODE__TALL_NODE, tallNode_1); + // + accumulator_0.add(tallNode_1); + } + /*@Thrown*/ BagValue.@org.eclipse.jdt.annotation.NonNull Accumulator accumulator_1 = ValueUtil.createBagAccumulatorValue(BAG_DATAid_EInt); + @NonNull Iterator<Object> ITERATOR__1_1 = collect_1.iterator(); + /*@Thrown*/ org.eclipse.ocl.pivot.values.@org.eclipse.jdt.annotation.NonNull BagValue collect_0; + while (true) { + if (!ITERATOR__1_1.hasNext()) { + collect_0 = accumulator_1; + break; + } + @SuppressWarnings("null") + /*@NonInvalid*/ tree2talltree.talltree.@org.eclipse.jdt.annotation.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(MAP_MiddleNode2TallNode.this, _1_1, TalltreePackage.Literals.TALL_NODE__HEIGHT, height); + final /*@Thrown*/ org.eclipse.ocl.pivot.values.@org.eclipse.jdt.annotation.NonNull IntegerValue BOXED_height = ValueUtil.integerValueOf(height); + // + accumulator_1.add(BOXED_height); + } + final /*@Thrown*/ org.eclipse.ocl.pivot.values.@org.eclipse.jdt.annotation.NonNull IntegerValue max = (IntegerValue)CollectionMaxOperation.INSTANCE.evaluate(collect_0); + final /*@Thrown*/ org.eclipse.ocl.pivot.values.@org.eclipse.jdt.annotation.NonNull IntegerValue sum = (IntegerValue)NumericPlusOperation.INSTANCE.evaluate(max, INT_1); + symbol_0 = sum; + } + else { + symbol_0 = INT_0; + } + // creations + final /*@Thrown*/ tree2talltree.talltree.@org.eclipse.jdt.annotation.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*/ java.util.@org.eclipse.jdt.annotation.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*/ java.lang.@org.eclipse.jdt.annotation.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]); + } + } +} |