Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEd Willink2017-01-28 09:14:33 +0000
committerEd Willink2017-02-01 07:21:38 +0000
commitf903d69885827e22e20a2c4cc1792e65d6c21af5 (patch)
treedda247228dc883ff57f4a1d7ece480c915af089c
parent5e6d63baf702a55e9ed017254b368a4b74b0174f (diff)
downloadorg.eclipse.qvtd-f903d69885827e22e20a2c4cc1792e65d6c21af5.tar.gz
org.eclipse.qvtd-f903d69885827e22e20a2c4cc1792e65d6c21af5.tar.xz
org.eclipse.qvtd-f903d69885827e22e20a2c4cc1792e65d6c21af5.zip
[495621] More comprehensive UMLX support
-rw-r--r--plugins/org.eclipse.qvtd.umlx.design/description/umlx.odesign33
-rw-r--r--plugins/org.eclipse.qvtd.umlx/plugin.xml8
-rw-r--r--plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/labels/RelDomainNodeLabelGenerator.java33
-rw-r--r--plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/labels/RelPatternClassNodeLabelGenerator.java31
-rw-r--r--plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/labels/RelPatternEdgeLabelGenerator.java36
-rw-r--r--plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/labels/UMLXModelLabelGenerator.java33
-rw-r--r--plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/labels/UMLXNamedElementLabelGenerator.java31
-rw-r--r--plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/qvtr2umlx/QVTr2UMLX.java437
-rw-r--r--plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/resource/UMLX2XMIidVisitor.java34
-rw-r--r--plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/umlx2qvtr/PatternForest.java778
-rw-r--r--plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/umlx2qvtr/UMLX2QVTr.java783
-rw-r--r--plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/utilities/UMLXServices.java196
-rw-r--r--plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/utilities/UMLXStandaloneSetup.java8
-rw-r--r--plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/utilities/UMLXToStringVisitor.java101
-rw-r--r--plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/utilities/UMLXUtil.java35
-rw-r--r--tests/org.eclipse.qvtd.all.tests/src/org/eclipse/qvtd/all/tests/AllQVTdTests.java4
-rw-r--r--tests/org.eclipse.qvtd.umlx.tests/META-INF/MANIFEST.MF3
-rw-r--r--tests/org.eclipse.qvtd.umlx.tests/src-gen/.gitignore1
-rw-r--r--tests/org.eclipse.qvtd.umlx.tests/src/org/eclipse/qvtd/umlx/tests/AllUMLXTests.java42
-rw-r--r--tests/org.eclipse.qvtd.umlx.tests/src/org/eclipse/qvtd/umlx/tests/UMLXSerializeTests.java (renamed from tests/org.eclipse.qvtd.umlx.tests/src/org/eclipse/qvtd/umlx/tests/UMLXTests.java)171
20 files changed, 1913 insertions, 885 deletions
diff --git a/plugins/org.eclipse.qvtd.umlx.design/description/umlx.odesign b/plugins/org.eclipse.qvtd.umlx.design/description/umlx.odesign
index 30e54ae93..c70366d64 100644
--- a/plugins/org.eclipse.qvtd.umlx.design/description/umlx.odesign
+++ b/plugins/org.eclipse.qvtd.umlx.design/description/umlx.odesign
@@ -265,6 +265,21 @@
<foregroundColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='white']"/>
</style>
</containerMappings>
+ <containerMappings name="TxQueryContainer" semanticCandidatesExpression="feature:ownedTxQueryNodes" domainClass="umlx.TxQueryNode" childrenPresentation="List">
+ <subNodeMappings name="TxParameterNode" semanticCandidatesExpression="feature:ownedTxParameterNodes" domainClass="umlx.TxParameterNode">
+ <style xsi:type="style:SquareDescription" borderSizeComputationExpression="2" labelExpression="service: umlxLabel" iconPath="/org.eclipse.qvtd.xtext.qvtbase.ui/icons/FunctionParameter.gif" labelAlignment="LEFT" tooltipExpression="service: umlxTooltipExpression" sizeComputationExpression="0" labelPosition="node" resizeKind="EAST_WEST">
+ <borderColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='light_orange']"/>
+ <labelColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='black']"/>
+ <color xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='white']"/>
+ </style>
+ </subNodeMappings>
+ <style xsi:type="style:FlatContainerStyleDescription" borderSizeComputationExpression="2" labelExpression="service:umlxLabel" iconPath="/org.eclipse.qvtd.xtext.qvtbase.ui/icons/Function.gif" tooltipExpression="service: umlxTooltipExpression">
+ <borderColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='blue']"/>
+ <labelColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='black']"/>
+ <backgroundColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='white']"/>
+ <foregroundColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='white']"/>
+ </style>
+ </containerMappings>
<toolSections name="TxNodesId" label="Nodes">
<ownedTools xsi:type="tool:ContainerCreationDescription" name="Import" containerMappings="//@ownedViewpoints[name='umlx-viewpoint-id']/@ownedRepresentations[name='UMLX%20Transformation%20Diagram']/@defaultLayer/@containerMappings[name='TxImportContainer']" iconPath="/org.eclipse.uml2.uml.edit/icons/full/obj16/PackageImport.gif">
<variable name="container"/>
@@ -295,6 +310,24 @@
</firstModelOperations>
</initialOperation>
</ownedTools>
+ <ownedTools xsi:type="tool:ContainerCreationDescription" name="Query" containerMappings="//@ownedViewpoints[name='umlx-viewpoint-id']/@ownedRepresentations[name='UMLX%20Transformation%20Diagram']/@defaultLayer/@containerMappings[name='TxQueryContainer']" iconPath="/org.eclipse.qvtd.xtext.qvtbase.ui/icons/Function.gif">
+ <variable name="container"/>
+ <viewVariable name="containerView"/>
+ <initialOperation>
+ <firstModelOperations xsi:type="tool_1:ChangeContext" browseExpression="var:container">
+ <subModelOperations xsi:type="tool_1:CreateInstance" typeName="umlx.TxQueryNode" referenceName="ownedTxQueryNodes"/>
+ </firstModelOperations>
+ </initialOperation>
+ </ownedTools>
+ <ownedTools xsi:type="tool:NodeCreationDescription" name="Query Parameter" nodeMappings="//@ownedViewpoints[name='umlx-viewpoint-id']/@ownedRepresentations[name='UMLX%20Transformation%20Diagram']/@defaultLayer/@containerMappings[name='TxQueryContainer']/@subNodeMappings[name='TxParameterNode']" iconPath="/org.eclipse.qvtd.xtext.qvtbase.ui/icons/FunctionParameter.gif">
+ <variable name="container"/>
+ <viewVariable name="containerView"/>
+ <initialOperation>
+ <firstModelOperations xsi:type="tool_1:ChangeContext">
+ <subModelOperations xsi:type="tool_1:CreateInstance" typeName="umlx.TxParameterNode" referenceName="ownedTxParameterNodes"/>
+ </firstModelOperations>
+ </initialOperation>
+ </ownedTools>
<ownedTools xsi:type="tool:ContainerCreationDescription" name="Relation" containerMappings="//@ownedViewpoints[name='umlx-viewpoint-id']/@ownedRepresentations[name='UMLX%20Transformation%20Diagram']/@defaultLayer/@containerMappings[name='TxRelDiagramContainer']" iconPath="/org.eclipse.qvtd.umlx.design/icons/UMLXRelation.gif">
<variable name="container"/>
<viewVariable name="containerView"/>
diff --git a/plugins/org.eclipse.qvtd.umlx/plugin.xml b/plugins/org.eclipse.qvtd.umlx/plugin.xml
index 97e454132..f404016c5 100644
--- a/plugins/org.eclipse.qvtd.umlx/plugin.xml
+++ b/plugins/org.eclipse.qvtd.umlx/plugin.xml
@@ -19,8 +19,16 @@
</extension>
<extension point="org.eclipse.ocl.pivot.label_generator">
+ <generator for="org.eclipse.qvtd.umlx.RelDomainNode"
+ class="org.eclipse.qvtd.umlx.labels.RelDomainNodeLabelGenerator"/>
<generator for="org.eclipse.qvtd.umlx.RelPatternEdge"
class="org.eclipse.qvtd.umlx.labels.RelPatternEdgeLabelGenerator"/>
+ <generator for="org.eclipse.qvtd.umlx.RelPatternClassNode"
+ class="org.eclipse.qvtd.umlx.labels.RelPatternClassNodeLabelGenerator"/>
+ <generator for="org.eclipse.qvtd.umlx.UMLXModel"
+ class="org.eclipse.qvtd.umlx.labels.UMLXModelLabelGenerator"/>
+ <generator for="org.eclipse.qvtd.umlx.UMLXNamedElement"
+ class="org.eclipse.qvtd.umlx.labels.UMLXNamedElementLabelGenerator"/>
</extension>
</plugin>
diff --git a/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/labels/RelDomainNodeLabelGenerator.java b/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/labels/RelDomainNodeLabelGenerator.java
new file mode 100644
index 000000000..a3f47d23a
--- /dev/null
+++ b/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/labels/RelDomainNodeLabelGenerator.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2017 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.umlx.labels;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.ocl.pivot.labels.AbstractLabelGenerator;
+import org.eclipse.qvtd.umlx.RelDomainNode;
+import org.eclipse.qvtd.umlx.TxTypedModelNode;
+
+public final class RelDomainNodeLabelGenerator extends AbstractLabelGenerator<@NonNull RelDomainNode>
+{
+ public static void initialize(@NonNull Registry registry) {
+ registry.install(RelDomainNode.class, new RelDomainNodeLabelGenerator());
+ }
+
+ public RelDomainNodeLabelGenerator() {
+ super(RelDomainNode.class);
+ }
+
+ @Override
+ public void buildLabelFor(@NonNull Builder labelBuilder, @NonNull RelDomainNode object) {
+ TxTypedModelNode txTypedModelNode = object.getReferredTxTypedModelNode();
+ labelBuilder.appendString(txTypedModelNode != null ? txTypedModelNode.getName() : null);
+ }
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/labels/RelPatternClassNodeLabelGenerator.java b/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/labels/RelPatternClassNodeLabelGenerator.java
new file mode 100644
index 000000000..00814d93b
--- /dev/null
+++ b/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/labels/RelPatternClassNodeLabelGenerator.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2017 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.umlx.labels;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.ocl.pivot.labels.AbstractLabelGenerator;
+import org.eclipse.qvtd.umlx.RelPatternClassNode;
+
+public final class RelPatternClassNodeLabelGenerator extends AbstractLabelGenerator<@NonNull RelPatternClassNode>
+{
+ public static void initialize(@NonNull Registry registry) {
+ registry.install(RelPatternClassNode.class, new RelPatternClassNodeLabelGenerator());
+ }
+
+ public RelPatternClassNodeLabelGenerator() {
+ super(RelPatternClassNode.class);
+ }
+
+ @Override
+ public void buildLabelFor(@NonNull Builder labelBuilder, @NonNull RelPatternClassNode object) {
+ labelBuilder.appendString(object.getName());
+ }
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/labels/RelPatternEdgeLabelGenerator.java b/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/labels/RelPatternEdgeLabelGenerator.java
index 33e1f2305..c22c3fa7c 100644
--- a/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/labels/RelPatternEdgeLabelGenerator.java
+++ b/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/labels/RelPatternEdgeLabelGenerator.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2014 Willink Transformations and others.
+ * Copyright (c) 2017 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
@@ -10,15 +10,16 @@
*******************************************************************************/
package org.eclipse.qvtd.umlx.labels;
-import org.eclipse.emf.ecore.EGenericType;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.ocl.pivot.labels.AbstractLabelGenerator;
+import org.eclipse.qvtd.umlx.RelPatternClassNode;
import org.eclipse.qvtd.umlx.RelPatternEdge;
+import org.eclipse.qvtd.umlx.RelPatternNode;
-public final class RelPatternEdgeLabelGenerator extends AbstractLabelGenerator<RelPatternEdge>
+public final class RelPatternEdgeLabelGenerator extends AbstractLabelGenerator<@NonNull RelPatternEdge>
{
public static void initialize(@NonNull Registry registry) {
- registry.install(EGenericType.class, new RelPatternEdgeLabelGenerator());
+ registry.install(RelPatternEdge.class, new RelPatternEdgeLabelGenerator());
}
public RelPatternEdgeLabelGenerator() {
@@ -27,25 +28,12 @@ public final class RelPatternEdgeLabelGenerator extends AbstractLabelGenerator<R
@Override
public void buildLabelFor(@NonNull Builder labelBuilder, @NonNull RelPatternEdge object) {
- // EClassifier eClassifier = object.getEClassifier();
- // if (eClassifier != null) {
- // labelBuilder.appendObject(eClassifier);
- // }
- // else {
- // ETypeParameter eTypeParameter = object.getETypeParameter();
- // labelBuilder.appendObject(eTypeParameter);
- // }
- // List<EGenericType> eTypeArguments = object.getETypeArguments();
- // int size = eTypeArguments.size();
- // if (size > 0) {
- labelBuilder.appendString("<");
- // for (int i = 0; i < size; i++) {
- // if (i > 0) {
- // labelBuilder.appendString(",");
- // }
- // labelBuilder.appendObject(eTypeArguments.get(0));
- // }
- labelBuilder.appendString(">");
- // }
+ RelPatternClassNode source = object.getSource();
+ RelPatternNode target = object.getTarget();
+ labelBuilder.appendString(source != null ? source.getName() : null);
+ labelBuilder.appendString(" -> ");
+ if (target instanceof RelPatternClassNode) {
+ labelBuilder.appendString(((RelPatternClassNode)target).getName());
+ }
}
} \ No newline at end of file
diff --git a/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/labels/UMLXModelLabelGenerator.java b/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/labels/UMLXModelLabelGenerator.java
new file mode 100644
index 000000000..345ea0fe8
--- /dev/null
+++ b/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/labels/UMLXModelLabelGenerator.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2017 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.umlx.labels;
+
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.ocl.pivot.labels.AbstractLabelGenerator;
+import org.eclipse.qvtd.umlx.UMLXModel;
+
+public final class UMLXModelLabelGenerator extends AbstractLabelGenerator<@NonNull UMLXModel>
+{
+ public static void initialize(@NonNull Registry registry) {
+ registry.install(UMLXModel.class, new UMLXModelLabelGenerator());
+ }
+
+ public UMLXModelLabelGenerator() {
+ super(UMLXModel.class);
+ }
+
+ @Override
+ public void buildLabelFor(@NonNull Builder labelBuilder, @NonNull UMLXModel object) {
+ Resource eResource = object.eResource();
+ labelBuilder.appendString(eResource != null ? String.valueOf(eResource.getURI()) : null);
+ }
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/labels/UMLXNamedElementLabelGenerator.java b/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/labels/UMLXNamedElementLabelGenerator.java
new file mode 100644
index 000000000..07831d8ba
--- /dev/null
+++ b/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/labels/UMLXNamedElementLabelGenerator.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2017 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.umlx.labels;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.ocl.pivot.labels.AbstractLabelGenerator;
+import org.eclipse.qvtd.umlx.UMLXNamedElement;
+
+public final class UMLXNamedElementLabelGenerator extends AbstractLabelGenerator<@NonNull UMLXNamedElement>
+{
+ public static void initialize(@NonNull Registry registry) {
+ registry.install(UMLXNamedElement.class, new UMLXNamedElementLabelGenerator());
+ }
+
+ public UMLXNamedElementLabelGenerator() {
+ super(UMLXNamedElement.class);
+ }
+
+ @Override
+ public void buildLabelFor(@NonNull Builder labelBuilder, @NonNull UMLXNamedElement object) {
+ labelBuilder.appendString(object.getName());
+ }
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/qvtr2umlx/QVTr2UMLX.java b/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/qvtr2umlx/QVTr2UMLX.java
index 08da4ee72..e1bd45132 100644
--- a/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/qvtr2umlx/QVTr2UMLX.java
+++ b/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/qvtr2umlx/QVTr2UMLX.java
@@ -10,6 +10,8 @@
*******************************************************************************/
package org.eclipse.qvtd.umlx.qvtr2umlx;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -40,14 +42,18 @@ import org.eclipse.ocl.pivot.StandardLibrary;
import org.eclipse.ocl.pivot.Type;
import org.eclipse.ocl.pivot.TypedElement;
import org.eclipse.ocl.pivot.Variable;
+import org.eclipse.ocl.pivot.VariableDeclaration;
import org.eclipse.ocl.pivot.VariableExp;
import org.eclipse.ocl.pivot.internal.prettyprint.PrettyPrinter;
import org.eclipse.ocl.pivot.util.Visitable;
import org.eclipse.ocl.pivot.utilities.EnvironmentFactory;
+import org.eclipse.ocl.pivot.utilities.NameUtil;
import org.eclipse.ocl.pivot.utilities.PivotConstants;
import org.eclipse.ocl.pivot.utilities.PivotUtil;
import org.eclipse.ocl.pivot.utilities.TreeIterable;
import org.eclipse.qvtd.compiler.CompilerChainException;
+import org.eclipse.qvtd.pivot.qvtbase.Function;
+import org.eclipse.qvtd.pivot.qvtbase.FunctionParameter;
import org.eclipse.qvtd.pivot.qvtbase.Pattern;
import org.eclipse.qvtd.pivot.qvtbase.Predicate;
import org.eclipse.qvtd.pivot.qvtbase.TypedModel;
@@ -66,36 +72,36 @@ import org.eclipse.qvtd.pivot.qvttemplate.CollectionTemplateExp;
import org.eclipse.qvtd.pivot.qvttemplate.ObjectTemplateExp;
import org.eclipse.qvtd.pivot.qvttemplate.PropertyTemplateItem;
import org.eclipse.qvtd.pivot.qvttemplate.TemplateExp;
-import org.eclipse.qvtd.umlx.RelPatternExpressionNode;
import org.eclipse.qvtd.umlx.RelDiagram;
import org.eclipse.qvtd.umlx.RelDomainNode;
import org.eclipse.qvtd.umlx.RelInvocationEdge;
import org.eclipse.qvtd.umlx.RelInvocationNode;
-import org.eclipse.qvtd.umlx.RelPatternNode;
-import org.eclipse.qvtd.umlx.RelPatternEdge;
import org.eclipse.qvtd.umlx.RelPatternClassNode;
+import org.eclipse.qvtd.umlx.RelPatternEdge;
+import org.eclipse.qvtd.umlx.RelPatternExpressionNode;
+import org.eclipse.qvtd.umlx.RelPatternNode;
import org.eclipse.qvtd.umlx.TxDiagram;
import org.eclipse.qvtd.umlx.TxImportNode;
import org.eclipse.qvtd.umlx.TxKeyNode;
import org.eclipse.qvtd.umlx.TxPackageNode;
+import org.eclipse.qvtd.umlx.TxParameterNode;
import org.eclipse.qvtd.umlx.TxPartNode;
+import org.eclipse.qvtd.umlx.TxQueryNode;
import org.eclipse.qvtd.umlx.TxTypedModelNode;
import org.eclipse.qvtd.umlx.UMLXElement;
import org.eclipse.qvtd.umlx.UMLXFactory;
import org.eclipse.qvtd.umlx.UMLXModel;
+import org.eclipse.qvtd.umlx.UMLXTypedElement;
import org.eclipse.qvtd.umlx.utilities.UMLXUtil;
import com.google.common.collect.Iterables;
public class QVTr2UMLX
{
- protected static class CreateVisitor extends AbstractExtendingQVTrelationVisitor<@Nullable UMLXElement, @NonNull QVTr2UMLX>
+ protected static abstract class AbstractVisitor extends AbstractExtendingQVTrelationVisitor<@Nullable UMLXElement, @NonNull QVTr2UMLX>
{
- protected final @NonNull UMLXModel umlxModel;
-
- public CreateVisitor(@NonNull QVTr2UMLX context, @NonNull UMLXModel umlxModel) {
+ public AbstractVisitor(@NonNull QVTr2UMLX context) {
super(context);
- this.umlxModel = umlxModel;
}
protected <T1 extends Element, T2 extends UMLXElement> @Nullable T2 create(@Nullable T1 source) {
@@ -115,30 +121,18 @@ public class QVTr2UMLX
}
}
- protected @NonNull RelPatternClassNode createRelPatternClassNode(@NonNull TypedElement qvtrTypedElement) {
- RelPatternClassNode relPatternClassNode = UMLXFactory.eINSTANCE.createRelPatternClassNode();
- context.install(qvtrTypedElement, relPatternClassNode);
- boolean isImplicit = (qvtrTypedElement instanceof Variable) && ((Variable)qvtrTypedElement).isIsImplicit();
- if (isImplicit) {
- relPatternClassNode.setIsAnon(true);
- relPatternClassNode.setName("");
- }
- else {
- relPatternClassNode.setIsAnon(false);
- relPatternClassNode.setName(qvtrTypedElement.getName());
- }
- relPatternClassNode.setIsRequired(qvtrTypedElement.isIsRequired());
+ protected void setReferredEType(@NonNull UMLXTypedElement umlxTypedElement, @NonNull TypedElement qvtrTypedElement) {
+ umlxTypedElement.setIsRequired(qvtrTypedElement.isIsRequired());
Type qvtrType = PivotUtil.getType(qvtrTypedElement);
if (qvtrType instanceof CollectionType) {
CollectionType qvtrCollectionType = (CollectionType)qvtrType;
- relPatternClassNode.setIsMany(true);
- relPatternClassNode.setIsNullFree(qvtrCollectionType.isIsNullFree());
- relPatternClassNode.setIsOrdered(qvtrCollectionType.isOrdered());
- relPatternClassNode.setIsUnique(qvtrCollectionType.isUnique());
+ umlxTypedElement.setIsMany(true);
+ umlxTypedElement.setIsNullFree(qvtrCollectionType.isIsNullFree());
+ umlxTypedElement.setIsOrdered(qvtrCollectionType.isOrdered());
+ umlxTypedElement.setIsUnique(qvtrCollectionType.isUnique());
qvtrType = PivotUtil.getElementalType(qvtrCollectionType);
}
- relPatternClassNode.setReferredEClassifier(context.getEcoreOf(qvtrType));
- return relPatternClassNode;
+ umlxTypedElement.setReferredEClassifier(context.getEcoreOf(qvtrType));
}
protected <T extends UMLXElement> @NonNull T visit(@NonNull Class<T> umlxClass, @NonNull Element qvtrElement) {
@@ -153,61 +147,151 @@ public class QVTr2UMLX
return castElement;
}
- @Override
- public @Nullable UMLXElement visitImport(@NonNull Import asImport) {
- TxImportNode txImportNode = UMLXFactory.eINSTANCE.createTxImportNode();
- context.install(asImport, txImportNode);
- txImportNode.setName(asImport.getName());
- txImportNode.setUri(EcoreUtil.getURI(asImport.getImportedNamespace().getESObject()).toString());
- return txImportNode;
- }
-
- @Override
- public @Nullable UMLXElement visitKey(@NonNull Key qvtrKey) {
- TxKeyNode txKeyNode = UMLXFactory.eINSTANCE.createTxKeyNode();
- context.install(qvtrKey, txKeyNode);
- txKeyNode.setReferredEClass((EClass) context.getEcoreOf(QVTrelationUtil.getIdentifies(qvtrKey)));
- for (Property qvtrPart : QVTrelationUtil.getOwnedParts(qvtrKey)) {
- TxPartNode txPartNode = UMLXFactory.eINSTANCE.createTxPartNode();
- // context.addTrace(usedPackage, txPartNode);
- txPartNode.setReferredEStructuralFeature(context.getEcoreOf(qvtrPart));
- txKeyNode.getOwnedTxPartNodes().add(txPartNode);
- }
- for (@NonNull Property qvtrPart : QVTrelationUtil.getOwnedOppositeParts(qvtrKey)) {
- TxPartNode txPartNode = UMLXFactory.eINSTANCE.createTxPartNode();
- // context.addTrace(usedPackage, txPartNode);
- txPartNode.setReferredEStructuralFeature(context.getEcoreOf(qvtrPart));
- txPartNode.setIsOpposite(true);
- txKeyNode.getOwnedTxPartNodes().add(txPartNode);
- }
- return txKeyNode;
- }
+ // @Override
+ // public @Nullable String visitOCLExpression(@NonNull OCLExpression qvtrExpression) {
+ // return PrettyPrinter.print(qvtrExpression);
+ // }
@Override
public @Nullable UMLXElement visitOCLExpression(@NonNull OCLExpression qvtrExpression) {
RelDomainNode relDomainNode = context.getContainingRelDomainNode(qvtrExpression);
RelPatternExpressionNode relPatternExpressionNode = UMLXFactory.eINSTANCE.createRelPatternExpressionNode();
context.install(qvtrExpression, relPatternExpressionNode);
- relPatternExpressionNode.setExpression(PrettyPrinter.print(qvtrExpression));
+ for (String line : PrettyPrinter.print(qvtrExpression).split("\\n")) {
+ relPatternExpressionNode.getInitExpressionLines().add(line);
+ }
relDomainNode.getOwnedRelPatternNodes().add(relPatternExpressionNode);
return relPatternExpressionNode;
}
@Override
- public @Nullable UMLXElement visitPackage(org.eclipse.ocl.pivot.@NonNull Package qvtrPackage) {
- if (PivotConstants.ORPHANAGE_URI.equals(qvtrPackage.getURI())) {
- return null;
+ public @Nullable RelPatternClassNode visitVariableExp(@NonNull VariableExp qvtrVariableExp) {
+ RelPatternClassNode relPatternNode = context.getUMLXElement(RelPatternClassNode.class, PivotUtil.getReferredVariable(qvtrVariableExp));
+ return relPatternNode;
+ }
+
+ @Override
+ public @Nullable UMLXElement visiting(@NonNull Visitable visitable) {
+ // System.out.println("Unsupported " + visitable.eClass().getName() + " for " + getClass().getSimpleName());
+ // return null;
+ throw new IllegalArgumentException("Unsupported " + visitable.eClass().getName() + " for " + getClass().getSimpleName());
+ }
+ }
+
+ protected static class CreateRelationVisitor extends AbstractVisitor
+ {
+ protected final @NonNull Relation qvtrRelation;
+ private final @NonNull Map<@NonNull VariableDeclaration, @NonNull List<@NonNull RelationDomain>> variable2domains = new HashMap<>();
+ private @Nullable List<@NonNull RelPatternNode> ownedPrimitiveNodes = null;
+ private final @NonNull RelDiagram relDiagram;
+
+ public CreateRelationVisitor(@NonNull QVTr2UMLX context, @NonNull Relation qvtrRelation) {
+ super(context);
+ this.qvtrRelation = qvtrRelation;
+ for (@NonNull RelationDomain rDomain : QVTrelationUtil.getOwnedDomains(qvtrRelation)) {
+ analyzeTree(rDomain, rDomain);
+ }
+ Pattern rWhen = qvtrRelation.getWhen();
+ if (rWhen != null) {
+ analyzeTree(rWhen, null);
+ }
+ Pattern rWhere = qvtrRelation.getWhere();
+ if (rWhere != null) {
+ analyzeTree(rWhere, null);
+ }
+ for (@NonNull Variable rVariable : QVTrelationUtil.getOwnedVariables(qvtrRelation)) {
+ OCLExpression rExpression = rVariable.getOwnedInit();
+ if (rExpression != null) {
+ List<@NonNull RelationDomain> referencedDomains = analyzeTree(rExpression, null);
+ for (@NonNull RelationDomain rDomain : referencedDomains) {
+ add(rVariable, rDomain);
+ }
+ }
}
- // Package umlxPackage = context.createPackage(qvtrPackage);
- createAll(PivotUtil.getOwnedClasses(qvtrPackage), null); //pOut.getOwnedClasses());
- createAll(PivotUtil.getOwnedPackages(qvtrPackage), null); //pOut.getOwnedPackages());
- // createAll(qvtrPackage.getOwnedComments(), pOut.getOwnedComments());
- return null;
+ this.relDiagram = UMLXFactory.eINSTANCE.createRelDiagram();
+ }
+
+ private @NonNull List<@NonNull RelationDomain> add(@NonNull VariableDeclaration variable, @Nullable RelationDomain rDomain) {
+ List<@NonNull RelationDomain> domains = variable2domains.get(variable);
+ if (domains == null) {
+ domains = new ArrayList<>();
+ variable2domains.put(variable, domains);
+ }
+ if ((rDomain != null) && !domains.contains(rDomain)) { // FIXME null can be resolved from RelationCallExp arg
+ domains.add(rDomain);
+ }
+ return domains;
+ }
+
+ private @NonNull List<@NonNull RelationDomain> analyzeTree(@NonNull Element rElement, @Nullable RelationDomain rDomain) {
+ List<@NonNull RelationDomain> referencedDomains = new ArrayList<>();
+ for (EObject eObject : new TreeIterable(rElement, true)) {
+ VariableDeclaration variable =null;
+ if (eObject instanceof VariableExp) {
+ variable = PivotUtil.getReferredVariable((VariableExp)eObject);
+ }
+ else if (eObject instanceof TemplateExp) {
+ variable = QVTrelationUtil.getBindsTo((TemplateExp)eObject);
+ }
+ if (variable != null) {
+ for (@NonNull RelationDomain domain : add(variable, rDomain)) {
+ if (!referencedDomains.contains(domain)) {
+ referencedDomains.add(domain);
+ }
+ }
+ }
+ }
+ return referencedDomains;
+ }
+
+ protected @NonNull RelPatternClassNode createRelPatternClassNode(@NonNull TypedElement qvtrTypedElement) {
+ RelPatternClassNode relPatternClassNode = UMLXFactory.eINSTANCE.createRelPatternClassNode();
+ context.install(qvtrTypedElement, relPatternClassNode);
+ boolean isImplicit = (qvtrTypedElement instanceof Variable) && ((Variable)qvtrTypedElement).isIsImplicit();
+ if (isImplicit) {
+ relPatternClassNode.setIsAnon(true);
+ relPatternClassNode.setName("");
+ }
+ else {
+ relPatternClassNode.setIsAnon(false);
+ relPatternClassNode.setName(qvtrTypedElement.getName());
+ }
+ setReferredEType(relPatternClassNode, qvtrTypedElement);
+ return relPatternClassNode;
+ }
+
+ private @NonNull List<@NonNull RelPatternNode> getPrimitiveNodes() {
+ List<@NonNull RelPatternNode> ownedPrimitiveNodes2 = ownedPrimitiveNodes;
+ if (ownedPrimitiveNodes2 == null) {
+ RelDomainNode relDomainNode = context.getPrimitiveRelDomainNode(relDiagram);
+ ownedPrimitiveNodes = ownedPrimitiveNodes2 = UMLXUtil.Internal.getOwnedRelPatternNodesList(relDomainNode);
+ }
+ return ownedPrimitiveNodes2;
+ }
+
+ @Override
+ public @NonNull String toString() {
+ StringBuilder s = new StringBuilder();
+ s.append(qvtrRelation.getName());
+ List<@NonNull VariableDeclaration> variables = new ArrayList<>(variable2domains.keySet());
+ Collections.sort(variables, NameUtil.NAMEABLE_COMPARATOR);
+ for (@NonNull VariableDeclaration variable : variables) {
+ List<@NonNull RelationDomain> domains = variable2domains.get(variable);
+ assert domains != null;
+ s.append("\n\t'");
+ s.append(variable.getName());
+ s.append("' =>");
+ for (@NonNull RelationDomain domain : domains) {
+ s.append(" '");
+ s.append(domain.getName());
+ s.append("'");
+ }
+ }
+ return s.toString();
}
@Override
public @Nullable UMLXElement visitRelation(@NonNull Relation qvtrRelation) {
- RelDiagram relDiagram = UMLXFactory.eINSTANCE.createRelDiagram();
context.install(qvtrRelation, relDiagram);
relDiagram.setIsTop(qvtrRelation.isIsTopLevel());
relDiagram.setName(qvtrRelation.getName());
@@ -218,14 +302,29 @@ public class QVTr2UMLX
//
// Create the primitive domain and its variables
//
- List<RelPatternNode> ownedNodes = null;
- for (@NonNull Variable qvtrVariable : QVTrelationUtil.getOwnedVariable(qvtrRelation)) {
+ for (@NonNull Variable qvtrVariable : QVTrelationUtil.getOwnedVariables(qvtrRelation)) {
RelPatternClassNode relPatternClassNode = context.basicGetUMLXElement(RelPatternClassNode.class, qvtrVariable);
if (relPatternClassNode == null) {
relPatternClassNode = createRelPatternClassNode(qvtrVariable);
+ OCLExpression ownedInit = qvtrVariable.getOwnedInit();
+ if (ownedInit != null) {
+ for (String line : PrettyPrinter.print(ownedInit).split("\\n")) {
+ relPatternClassNode.getInitExpressionLines().add(line);
+ }
+ }
+ List<@NonNull RelPatternNode> ownedNodes = null;
+ List<@NonNull RelationDomain> qvtrDomains = variable2domains.get(qvtrVariable);
+ if (qvtrDomains == null) {
+ System.out.println("Dead variable " + qvtrRelation.getName() + "." + qvtrVariable.getName());
+ }
+ else if (qvtrDomains.size() == 1) {
+ RelationDomain qvtrDomain = qvtrDomains.get(0);
+ RelDomainNode relDomainNode = context.basicGetUMLXElement(RelDomainNode.class, qvtrDomain);
+ assert relDomainNode != null;
+ ownedNodes = UMLXUtil.Internal.getOwnedRelPatternNodesList(relDomainNode);
+ }
if (ownedNodes == null) {
- RelDomainNode relDomainNode = context.getPrimitiveRelDomainNode(relDiagram);
- ownedNodes = relDomainNode.getOwnedRelPatternNodes();
+ ownedNodes = getPrimitiveNodes();
}
ownedNodes.add(relPatternClassNode);
}
@@ -285,12 +384,25 @@ public class QVTr2UMLX
if (qvtrRelationDomain.isIsEnforceable()) {
tyTypedModelNode.setEnforce(true);
}
- List<RelPatternNode> ownedNodes = relDomainNode.getOwnedRelPatternNodes();
for (@NonNull EObject eObject : new TreeIterable(qvtrRelationDomain, false)) {
if (eObject instanceof TemplateExp) {
TemplateExp qvtrTemplateExp = (TemplateExp)eObject;
RelPatternClassNode relPatternClassNode = createRelPatternClassNode(QVTrelationUtil.getBindsTo(qvtrTemplateExp));
context.install(qvtrTemplateExp, relPatternClassNode);
+
+
+ Variable qvtrVariable = qvtrTemplateExp.getBindsTo();
+ List<@NonNull RelPatternNode> ownedNodes = null;
+ List<@NonNull RelationDomain> qvtrDomains = variable2domains.get(qvtrVariable);
+ if (qvtrDomains == null) {
+ System.out.println("Dead variable " + qvtrRelation.getName() + "." + qvtrVariable.getName());
+ }
+ else if (qvtrDomains.size() == 1) {
+ ownedNodes = UMLXUtil.Internal.getOwnedRelPatternNodesList(relDomainNode);
+ }
+ if (ownedNodes == null) {
+ ownedNodes = getPrimitiveNodes();
+ }
ownedNodes.add(relPatternClassNode);
if (eObject instanceof CollectionTemplateExp) {
CollectionTemplateExp qvtrCollectionTemplateExp = (CollectionTemplateExp)eObject;
@@ -305,6 +417,89 @@ public class QVTr2UMLX
context.addReference(qvtrRelationDomain);
return relDomainNode;
}
+ }
+
+ protected static class CreateTransformationVisitor extends AbstractVisitor
+ {
+ protected final @NonNull UMLXModel umlxModel;
+
+ public CreateTransformationVisitor(@NonNull QVTr2UMLX context, @NonNull UMLXModel umlxModel) {
+ super(context);
+ this.umlxModel = umlxModel;
+ }
+
+ @Override
+ public @Nullable UMLXElement visitFunction(@NonNull Function asFunction) {
+ TxQueryNode txQueryNode = UMLXFactory.eINSTANCE.createTxQueryNode();
+ context.install(asFunction, txQueryNode);
+ txQueryNode.setName(asFunction.getName());
+ setReferredEType(txQueryNode, asFunction);
+ OCLExpression bodyExpression = asFunction.getQueryExpression();
+ if (bodyExpression != null) {
+ for (String line : PrettyPrinter.print(bodyExpression).split("\\n")) {
+ txQueryNode.getInitExpressionLines().add(line);
+ }
+ }
+ createAll(QVTrelationUtil.getOwnedParameters(asFunction), txQueryNode.getOwnedTxParameterNodes());
+ return txQueryNode;
+ }
+
+ @Override
+ public @Nullable UMLXElement visitFunctionParameter(@NonNull FunctionParameter asFunctionParameter) {
+ TxParameterNode txParameterNode = UMLXFactory.eINSTANCE.createTxParameterNode();
+ context.install(asFunctionParameter, txParameterNode);
+ txParameterNode.setName(asFunctionParameter.getName());
+ setReferredEType(txParameterNode, asFunctionParameter);
+ return txParameterNode;
+ }
+
+ @Override
+ public @Nullable UMLXElement visitImport(@NonNull Import asImport) {
+ TxImportNode txImportNode = UMLXFactory.eINSTANCE.createTxImportNode();
+ context.install(asImport, txImportNode);
+ txImportNode.setName(asImport.getName());
+ txImportNode.setUri(EcoreUtil.getURI(asImport.getImportedNamespace().getESObject()).toString());
+ return txImportNode;
+ }
+
+ @Override
+ public @Nullable UMLXElement visitKey(@NonNull Key qvtrKey) {
+ TxKeyNode txKeyNode = UMLXFactory.eINSTANCE.createTxKeyNode();
+ context.install(qvtrKey, txKeyNode);
+ txKeyNode.setReferredEClass((EClass) context.getEcoreOf(QVTrelationUtil.getIdentifies(qvtrKey)));
+ for (Property qvtrPart : QVTrelationUtil.getOwnedParts(qvtrKey)) {
+ TxPartNode txPartNode = UMLXFactory.eINSTANCE.createTxPartNode();
+ // context.addTrace(usedPackage, txPartNode);
+ txPartNode.setReferredEStructuralFeature(context.getEcoreOf(qvtrPart));
+ txKeyNode.getOwnedTxPartNodes().add(txPartNode);
+ }
+ for (@NonNull Property qvtrPart : QVTrelationUtil.getOwnedOppositeParts(qvtrKey)) {
+ TxPartNode txPartNode = UMLXFactory.eINSTANCE.createTxPartNode();
+ // context.addTrace(usedPackage, txPartNode);
+ txPartNode.setReferredEStructuralFeature(context.getEcoreOf(qvtrPart));
+ txPartNode.setIsOpposite(true);
+ txKeyNode.getOwnedTxPartNodes().add(txPartNode);
+ }
+ return txKeyNode;
+ }
+
+ @Override
+ public @Nullable UMLXElement visitPackage(org.eclipse.ocl.pivot.@NonNull Package qvtrPackage) {
+ if (PivotConstants.ORPHANAGE_URI.equals(qvtrPackage.getURI())) {
+ return null;
+ }
+ // Package umlxPackage = context.createPackage(qvtrPackage);
+ createAll(PivotUtil.getOwnedClasses(qvtrPackage), null); //pOut.getOwnedClasses());
+ createAll(PivotUtil.getOwnedPackages(qvtrPackage), null); //pOut.getOwnedPackages());
+ // createAll(qvtrPackage.getOwnedComments(), pOut.getOwnedComments());
+ return null;
+ }
+
+ @Override
+ public @Nullable UMLXElement visitRelation(@NonNull Relation qvtrRelation) {
+ CreateRelationVisitor createRelationVisitor = new CreateRelationVisitor(context, qvtrRelation);
+ return qvtrRelation.accept(createRelationVisitor);
+ }
@Override
public @Nullable UMLXElement visitRelationModel(@NonNull RelationModel qvtrModel) {
@@ -337,6 +532,7 @@ public class QVTr2UMLX
createAll(QVTrelationUtil.getModelParameters(qvtrTransformation), txDiagram.getOwnedTxTypedModelNodes());
createAll(QVTrelationUtil.getOwnedKey(qvtrTransformation), txDiagram.getOwnedTxKeyNodes());
createAll(QVTrelationUtil.getRule(qvtrTransformation), txDiagram.getOwnedRelDiagrams());
+ createAll(QVTrelationUtil.getOwnedOperations(qvtrTransformation), txDiagram.getOwnedTxQueryNodes());
// doRules(qvtrTransformation, txTransformationNode);
// createAll(qvtrTransformation.getOwnedComments(), txTransformationNode.getOwnedComments());
umlxModel.getOwnedTxDiagrams().add(txDiagram);
@@ -356,52 +552,14 @@ public class QVTr2UMLX
}
return txTypedModelNode;
}
-
- @Override
- public @Nullable UMLXElement visitVariableExp(@NonNull VariableExp qvtrVariableExp) {
- RelPatternClassNode relPatternNode = context.getUMLXElement(RelPatternClassNode.class, PivotUtil.getReferredVariable(qvtrVariableExp));
- return relPatternNode;
- }
-
- @Override
- public @Nullable UMLXElement visiting(@NonNull Visitable visitable) {
- // System.out.println("Unsupported " + visitable.eClass().getName() + " for " + getClass().getSimpleName());
- // return null;
- throw new IllegalArgumentException("Unsupported " + visitable.eClass().getName() + " for " + getClass().getSimpleName());
- }
}
- protected static class ReferenceVisitor extends AbstractExtendingQVTrelationVisitor<@Nullable UMLXElement, @NonNull QVTr2UMLX>
+ protected static class ReferenceVisitor extends AbstractVisitor
{
public ReferenceVisitor(@NonNull QVTr2UMLX context) {
super(context);
}
- protected <T1 extends Element, T2 extends UMLXElement> @Nullable T2 create(@Nullable T1 source) {
- if (source == null) {
- return null;
- }
- @SuppressWarnings("unchecked") @Nullable T2 target = (T2) source.accept(this);
- return target;
- }
-
- protected <T extends UMLXElement> @NonNull T visit(@NonNull Class<T> umlxClass, @NonNull Element qvtrElement) {
- UMLXElement umlxElement = qvtrElement.accept(this);
- if (umlxElement == null) {
- throw new IllegalArgumentException("Missing UMLX element for " + qvtrElement);
- }
- if (!umlxClass.isAssignableFrom(umlxElement.getClass())) {
- throw new ClassCastException("UMLX element " + umlxElement + " cannot be cast to " + umlxClass);
- }
- @SuppressWarnings("unchecked")T castElement = (T)umlxElement;
- return castElement;
- }
-
- @Override
- public @Nullable UMLXElement visiting(@NonNull Visitable visitable) {
- throw new IllegalArgumentException("Unsupported " + visitable.eClass().getName() + " for " + getClass().getSimpleName());
- }
-
@Override
public @Nullable UMLXElement visitCollectionTemplateExp(@NonNull CollectionTemplateExp qvtrCollectionTemplateExp) {
RelPatternClassNode relPatternNode = context.getUMLXElement(RelPatternClassNode.class, qvtrCollectionTemplateExp);
@@ -429,20 +587,15 @@ public class QVTr2UMLX
relPatternEdge.setTarget(relRestPatternNode);
relRestPatternNode.getOwningRelDomainNode().getOwnedRelPatternEdges().add(relPatternEdge);
}
+ OCLExpression qvtrWhere = qvtrCollectionTemplateExp.getWhere();
+ if (qvtrWhere != null) {
+ RelPatternNode relWherePatternNode = (RelPatternNode) qvtrWhere.accept(this);
+ relPatternNode.getOwningRelDomainNode().getOwnedRelPatternNodes().add(relWherePatternNode);
+ }
return relPatternNode;
}
@Override
- public @Nullable UMLXElement visitOCLExpression(@NonNull OCLExpression qvtrExpression) {
- RelDomainNode relDomainNode = context.getContainingRelDomainNode(qvtrExpression);
- RelPatternExpressionNode relPatternExpressionNode = UMLXFactory.eINSTANCE.createRelPatternExpressionNode();
- context.install(qvtrExpression, relPatternExpressionNode);
- relPatternExpressionNode.setExpression(PrettyPrinter.print(qvtrExpression));
- relDomainNode.getOwnedRelPatternNodes().add(relPatternExpressionNode);
- return relPatternExpressionNode;
- }
-
- @Override
public @Nullable UMLXElement visitObjectTemplateExp(@NonNull ObjectTemplateExp qvtrObjectTemplateExp) {
RelPatternClassNode relPatternNode = context.getUMLXElement(RelPatternClassNode.class, qvtrObjectTemplateExp);
for (@NonNull PropertyTemplateItem qvtrPropertyTemplateItem : QVTrelationUtil.getOwnedParts(qvtrObjectTemplateExp)) {
@@ -451,7 +604,7 @@ public class QVTr2UMLX
RelPatternNode relPartPatternNode = visit(RelPatternNode.class, partValue);
RelPatternEdge relPatternEdge = UMLXFactory.eINSTANCE.createRelPatternEdge();
Property oppositeProperty = partProperty.getOpposite();
- if (partProperty.isIsComposite()) {
+ if (partProperty.isIsComposite()) { // FIXME direction only needs to avoid a null/implicit EReference
// relPatternEdge.setIsOpposite(false);
relPatternEdge.setReferredEStructuralFeature(context.getEcoreOf(partProperty));
relPatternEdge.setSource(relPatternNode);
@@ -477,6 +630,11 @@ public class QVTr2UMLX
}
relPartPatternNode.getOwningRelDomainNode().getOwnedRelPatternEdges().add(relPatternEdge);
}
+ OCLExpression qvtrWhere = qvtrObjectTemplateExp.getWhere();
+ if (qvtrWhere != null) {
+ RelPatternNode relWherePatternNode = (RelPatternNode) qvtrWhere.accept(this);
+ relPatternNode.getOwningRelDomainNode().getOwnedRelPatternNodes().add(relWherePatternNode);
+ }
return relPatternNode;
}
@@ -520,12 +678,6 @@ public class QVTr2UMLX
RelPatternClassNode relPatternNode = context.getUMLXElement(RelPatternClassNode.class, qvtrSharedVariable);
return relPatternNode;
}
-
- @Override
- public @Nullable UMLXElement visitVariableExp(@NonNull VariableExp qvtrVariableExp) {
- RelPatternClassNode relPatternNode = context.getUMLXElement(RelPatternClassNode.class, PivotUtil.getReferredVariable(qvtrVariableExp));
- return relPatternNode;
- }
}
protected final @NonNull EnvironmentFactory environmentFactory;
@@ -557,15 +709,28 @@ public class QVTr2UMLX
}
protected @NonNull RelDomainNode getContainingRelDomainNode(@NonNull OCLExpression qvtrExpression) {
- RelationDomain qvtrRelationDomain = QVTrelationUtil.basicGetContainingRelationDomain(qvtrExpression);
- if (qvtrRelationDomain != null) {
- return getUMLXElement(RelDomainNode.class, qvtrRelationDomain);
- }
- else {
- Relation qvtrRelation = QVTrelationUtil.getContainingRelation(qvtrExpression);
- RelDiagram relDiagram = getUMLXElement(RelDiagram.class, qvtrRelation);
- return getPrimitiveRelDomainNode(relDiagram);
+ for (EObject eObject = qvtrExpression, eContainer; (eContainer = eObject.eContainer()) != null; eObject = eContainer) {
+ if (eContainer instanceof RelationCallExp) {
+ RelationCallExp qvtrRelationCallExp = (RelationCallExp) eContainer;
+ int argumentIndex = qvtrRelationCallExp.getArgument().indexOf(eObject);
+ assert argumentIndex >= 0;
+ // Relation referredRelation = QVTrelationUtil.getReferredRelation(qvtrRelationCallExp);
+ RelationDomain referredDomain = QVTrelationUtil.getRelationCallExpArgumentDomain(qvtrRelationCallExp, argumentIndex);
+ for (EObject eObject2 = qvtrRelationCallExp, eContainer2; (eContainer2 = eObject2.eContainer()) != null; eObject2 = eContainer2) {
+ if (eContainer2 instanceof Relation) {
+ Relation qvtrRelation = (Relation) eContainer2;
+ RelationDomain rRelationDomain = QVTrelationUtil.getRelationDomain(qvtrRelation, QVTrelationUtil.getTypedModel(referredDomain));
+ return getUMLXElement(RelDomainNode.class, rRelationDomain);
+ }
+ }
+ }
+ if (eContainer instanceof RelationDomain) {
+ return getUMLXElement(RelDomainNode.class, (RelationDomain) eContainer);
+ }
}
+ Relation qvtrRelation = QVTrelationUtil.getContainingRelation(qvtrExpression);
+ RelDiagram relDiagram = getUMLXElement(RelDiagram.class, qvtrRelation);
+ return getPrimitiveRelDomainNode(relDiagram);
}
public @Nullable EStructuralFeature getEcoreOf(@NonNull Property qvtrProperty) {
@@ -662,7 +827,7 @@ public class QVTr2UMLX
for (EObject eObject : qvtrResource.getContents()) {
if (eObject instanceof RelationModel) {
UMLXModel umlxModel = UMLXFactory.eINSTANCE.createUMLXModel();
- ((Element)eObject).accept(new CreateVisitor(this, umlxModel));
+ ((Element)eObject).accept(new CreateTransformationVisitor(this, umlxModel));
umlxResource.getContents().add(umlxModel);
}
}
diff --git a/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/resource/UMLX2XMIidVisitor.java b/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/resource/UMLX2XMIidVisitor.java
index 38a6baf6f..27d5f9bb5 100644
--- a/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/resource/UMLX2XMIidVisitor.java
+++ b/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/resource/UMLX2XMIidVisitor.java
@@ -29,7 +29,9 @@ import org.eclipse.qvtd.umlx.TxDiagram;
import org.eclipse.qvtd.umlx.TxImportNode;
import org.eclipse.qvtd.umlx.TxKeyNode;
import org.eclipse.qvtd.umlx.TxPackageNode;
+import org.eclipse.qvtd.umlx.TxParameterNode;
import org.eclipse.qvtd.umlx.TxPartNode;
+import org.eclipse.qvtd.umlx.TxQueryNode;
import org.eclipse.qvtd.umlx.TxTypedModelNode;
import org.eclipse.qvtd.umlx.UMLXElement;
import org.eclipse.qvtd.umlx.UMLXModel;
@@ -81,8 +83,10 @@ public class UMLX2XMIidVisitor extends AbstractExtendingUMLXVisitor<Boolean, UML
public static final @NonNull String TX_DIAGRAM_PREFIX = "T."; //$NON-NLS-1$
public static final @NonNull String TX_IMPORT_PREFIX = "I."; //$NON-NLS-1$
public static final @NonNull String TX_KEY_PREFIX = "K."; //$NON-NLS-1$
- public static final @NonNull String TX_KEY_PART_PREFIX = "P."; //$NON-NLS-1$
- public static final @NonNull String TX_MODEL_PARAMETER_PREFIX = "M."; //$NON-NLS-1$
+ public static final @NonNull String TX_KEY_PART_PREFIX = "Kp."; //$NON-NLS-1$
+ public static final @NonNull String TX_MODEL_PARAMETER_PREFIX = "Tp."; //$NON-NLS-1$
+ public static final @NonNull String TX_QUERY_PREFIX = "Q."; //$NON-NLS-1$
+ public static final @NonNull String TX_QUERY_PARAMETER_PREFIX = "Qp."; //$NON-NLS-1$
public static final @NonNull String TX_USED_PACKAGE_PREFIX = "U."; //$NON-NLS-1$
/* public static final @NonNull String ACCUMULATOR_PREFIX = "a"; //$NON-NLS-1$
@@ -220,8 +224,8 @@ public class UMLX2XMIidVisitor extends AbstractExtendingUMLXVisitor<Boolean, UML
appendNameOf(s, UMLXUtil.getSource(incoming.get(0)));
}
else {
- String expression = relPatternExpressionNode.getExpression();
- int hash = expression != null ? expression.hashCode() : 0;
+ List<String> initExpressionLines = relPatternExpressionNode.getInitExpressionLines();
+ int hash = initExpressionLines.hashCode();
s.append(Integer.toString(hash));
}
}
@@ -386,6 +390,14 @@ public class UMLX2XMIidVisitor extends AbstractExtendingUMLXVisitor<Boolean, UML
}
@Override
+ public Boolean visitTxParameterNode(@NonNull TxParameterNode object) {
+ s.append(TX_QUERY_PARAMETER_PREFIX);
+ appendParent(object);
+ appendNameOf(s, object);
+ return true;
+ }
+
+ @Override
public Boolean visitTxPartNode(@NonNull TxPartNode object) {
String name = object.getReferredEStructuralFeature().getName();
if (name != null) {
@@ -401,6 +413,20 @@ public class UMLX2XMIidVisitor extends AbstractExtendingUMLXVisitor<Boolean, UML
}
@Override
+ public Boolean visitTxQueryNode(@NonNull TxQueryNode object) {
+ s.append(TX_QUERY_PREFIX);
+ appendParent(object);
+ appendNameOf(s, object);
+ for (TxParameterNode txParameterNode : object.getOwnedTxParameterNodes()) {
+ s.append(FIELD_SEPARATOR);
+ if (txParameterNode != null) {
+ appendNameOf(s, txParameterNode);
+ }
+ }
+ return true;
+ }
+
+ @Override
public Boolean visitTxTypedModelNode(@NonNull TxTypedModelNode object) {
String name = object.getName();
if (name != null) {
diff --git a/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/umlx2qvtr/PatternForest.java b/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/umlx2qvtr/PatternForest.java
new file mode 100644
index 000000000..cfe99747e
--- /dev/null
+++ b/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/umlx2qvtr/PatternForest.java
@@ -0,0 +1,778 @@
+/*******************************************************************************
+ * 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.umlx.umlx2qvtr;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.ocl.pivot.Element;
+import org.eclipse.ocl.pivot.OCLExpression;
+import org.eclipse.ocl.pivot.Property;
+import org.eclipse.ocl.pivot.StringLiteralExp;
+import org.eclipse.ocl.pivot.Variable;
+import org.eclipse.ocl.pivot.VariableDeclaration;
+import org.eclipse.ocl.pivot.VariableExp;
+import org.eclipse.ocl.pivot.internal.utilities.PivotUtilInternal;
+import org.eclipse.ocl.pivot.utilities.ClassUtil;
+import org.eclipse.ocl.pivot.utilities.EnvironmentFactory;
+import org.eclipse.ocl.pivot.utilities.MetamodelManager;
+import org.eclipse.qvtd.pivot.qvtbase.TypedModel;
+import org.eclipse.qvtd.pivot.qvtrelation.DomainPattern;
+import org.eclipse.qvtd.pivot.qvtrelation.Relation;
+import org.eclipse.qvtd.pivot.qvtrelation.RelationCallExp;
+import org.eclipse.qvtd.pivot.qvtrelation.RelationDomain;
+import org.eclipse.qvtd.pivot.qvtrelation.SharedVariable;
+import org.eclipse.qvtd.pivot.qvtrelation.TemplateVariable;
+import org.eclipse.qvtd.pivot.qvtrelation.utilities.QVTrelationUtil;
+import org.eclipse.qvtd.pivot.qvttemplate.CollectionTemplateExp;
+import org.eclipse.qvtd.pivot.qvttemplate.ObjectTemplateExp;
+import org.eclipse.qvtd.pivot.qvttemplate.TemplateExp;
+import org.eclipse.qvtd.umlx.RelDiagram;
+import org.eclipse.qvtd.umlx.RelDomainNode;
+import org.eclipse.qvtd.umlx.RelInvocationEdge;
+import org.eclipse.qvtd.umlx.RelInvocationNode;
+import org.eclipse.qvtd.umlx.RelPatternClassNode;
+import org.eclipse.qvtd.umlx.RelPatternEdge;
+import org.eclipse.qvtd.umlx.RelPatternExpressionNode;
+import org.eclipse.qvtd.umlx.RelPatternNode;
+import org.eclipse.qvtd.umlx.TxTypedModelNode;
+import org.eclipse.qvtd.umlx.utilities.UMLXUtil;
+
+import com.google.common.collect.Iterables;
+
+public class PatternForest
+{
+ private class TreeEdge
+ {
+ private @NonNull RelPatternEdge patternEdge;
+ private boolean isGraph;
+ private boolean isOpposite;
+ private @NonNull TreeClassNode parent;
+ private @NonNull TreeNode child;
+
+ public TreeEdge(boolean isGraph, @NonNull RelPatternEdge patternEdge, boolean isOpposite, @NonNull TreeClassNode parent, @NonNull TreeNode child) {
+ this.isGraph = isGraph;
+ this.patternEdge = patternEdge;
+ this.isOpposite = isOpposite;
+ this.parent = parent;
+ this.child = child;
+ parent.addChildEdge(this);
+ TreeEdge oldEdge = patternEdge2treeEdge.put(patternEdge, this);
+ assert oldEdge == null;
+ if (isGraph) {
+ child.addGraphEdge(this);
+ }
+ // else {
+ // assert child.parentEdge == this; --not yet constructed
+ // }
+ if (isOpposite) {
+ toString();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return patternEdge.toString();
+ }
+ }
+
+ private static abstract class TreeNode
+ {
+ protected @Nullable TreeEdge parentEdge = null;
+ protected @Nullable List<@NonNull TreeEdge> graphEdges = null;
+ // protected boolean isInvoked = false;
+
+ public void addGraphEdge(@NonNull TreeEdge graphEdge) {
+ List<@NonNull TreeEdge> graphEdges2 = graphEdges;
+ if (graphEdges2 == null) {
+ graphEdges = graphEdges2 = new ArrayList<>();
+ }
+ assert !graphEdges2.contains(graphEdge);
+ graphEdges2.add(graphEdge);
+ }
+
+ protected abstract void toString(@NonNull StringBuilder s, int depth);
+ }
+
+ private class TreeClassNode extends TreeNode
+ {
+ // Definition structure
+ private @NonNull TreeRoot treeRoot;
+ private @NonNull RelPatternClassNode patternNode;
+ private @NonNull List<@NonNull TreeEdge> childEdges = new ArrayList<>();
+ // Derived structure
+ // private boolean isShared = false;
+ private Variable variable = null;
+ protected boolean isRealized = false;
+
+ public TreeClassNode(@NonNull TreeRoot treeRoot, @NonNull RelPatternClassNode rootPatternNode) {
+ this.treeRoot = treeRoot;
+ this.patternNode = rootPatternNode;
+ TreeNode oldNode = patternNode2treeNode.put(rootPatternNode, this);
+ assert oldNode == null;
+ allNodes.add(rootPatternNode);
+ treeRoot.addNode(this);
+ }
+
+ public TreeClassNode(@NonNull RelPatternEdge patternEdge, boolean isOpposite, @NonNull TreeClassNode parentNode) {
+ this.treeRoot = parentNode.treeRoot;
+ this.patternNode = isOpposite ? UMLXUtil.getSource(patternEdge) : (RelPatternClassNode)UMLXUtil.getTarget(patternEdge);
+ this.parentEdge = new TreeEdge(false, patternEdge, isOpposite, parentNode, this);
+ assert parentNode.patternNode == (isOpposite ? patternEdge.getTarget() : patternEdge.getSource());
+ TreeNode oldNode = patternNode2treeNode.put(patternNode, this);
+ assert oldNode == null;
+ allNodes.add(patternNode);
+ }
+
+ public void addChildEdge(@NonNull TreeEdge childEdge) {
+ assert !childEdges.contains(childEdge);
+ childEdges.add(childEdge);
+ }
+
+ public @NonNull Variable getVariable() {
+ Variable variable2 = variable;
+ if (variable2 == null) {
+ org.eclipse.ocl.pivot.Class asClass = umlx2qvtr.getReferredType(patternNode);
+ TreeEdge parentEdge2 = parentEdge;
+ boolean isRestVariable = isRestVariable(parentEdge2);
+ boolean isGraphLeafVariable = isGraphLeafVariable();
+ boolean isUnenforcedLeafVariable = isUnrealizedLeafVariable();
+ if (isRestVariable || isGraphLeafVariable || isUnenforcedLeafVariable) {
+ String name = patternNode.isIsAnon() ? null : UMLXUtil.getName(patternNode);
+ variable2 = umlx2qvtr.createSharedVariable(name, asClass, patternNode.isIsRequired(), null);
+ umlx2qvtr.install(patternNode, variable2);
+ }
+ else {
+ variable2 = umlx2qvtr.createTemplateVariable(UMLXUtil.getName(patternNode), asClass, patternNode.isIsRequired(), null);
+ }
+ // }
+ allVariables.add(variable2);
+ variable = variable2;
+ }
+ return variable2;
+ }
+
+ private boolean isGraphLeafVariable() {
+ if (childEdges.isEmpty()) {
+ List<@NonNull TreeEdge> graphEdges2 = graphEdges;
+ if (graphEdges2 != null) {
+ for (@NonNull TreeEdge graphEdge : graphEdges2) {
+ if (graphEdge.parent.treeRoot != treeRoot) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean isRestVariable(TreeEdge parentEdge2) {
+ return (parentEdge2 != null) && (parentEdge2.patternEdge.getSourceIndex() < 0);
+ }
+
+ private boolean isUnrealizedLeafVariable() {
+ // if (!isRealized) {
+ // return false;
+ // }
+ if (parentEdge == null) {
+ return false;
+ }
+ if (isRealized) {
+ return false;
+ }
+ if (!childEdges.isEmpty()) {
+ return false;
+ }
+ // if (treeRoot.relDomainNode.getReferredTxTypedModelNode().isEnforce()) {
+ // return false;
+ // }
+ // if (isInvoked) {
+ // return true;
+ // }
+ if ((graphEdges != null) && !graphEdges.isEmpty()) {
+ return true;
+ }
+ return false;
+ }
+
+ public void setIsRealized() {
+ if (!isRealized) {
+ isRealized = true;
+ for (@NonNull TreeEdge childEdge : childEdges) {
+ EStructuralFeature eStructuralFeature = childEdge.patternEdge.getReferredEStructuralFeature();
+ if ((eStructuralFeature == null) || ((eStructuralFeature instanceof EReference) && ((EReference)eStructuralFeature).isContainment())) {
+ ((TreeClassNode)childEdge.child).setIsRealized();
+ }
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return patternNode.toString();
+ }
+
+ @Override
+ protected void toString(@NonNull StringBuilder s, int depth) {
+ s.append(patternNode);
+ depth++;
+ for (@NonNull TreeEdge treeEdge : childEdges) {
+ s.append("\n");
+ for (int i = 0; i < depth; i++) {
+ s.append(" ");
+ }
+ EStructuralFeature eStructuralFeature = treeEdge.patternEdge.getReferredEStructuralFeature();
+ if (eStructuralFeature != null) {
+ s.append(eStructuralFeature.getName());
+ }
+ else {
+ s.append(treeEdge.patternEdge);
+ }
+ if (treeEdge.isGraph) {
+ s.append(" => ");
+ s.append(treeEdge.child);
+ }
+ else if (treeEdge.child instanceof TreeExpressionNode) {
+ s.append(" := ");
+ s.append(treeEdge.child);
+ }
+ else {
+ s.append(" = ");
+ treeEdge.child.toString(s, depth);
+ }
+ }
+ }
+ }
+
+ private class TreeExpressionNode extends TreeNode
+ {
+ private @NonNull RelPatternExpressionNode patternNode;
+
+ public TreeExpressionNode(@NonNull RelPatternEdge patternEdge, @NonNull TreeClassNode parentNode) {
+ this.patternNode = (RelPatternExpressionNode) UMLXUtil.getTarget(patternEdge);
+ this.parentEdge = new TreeEdge(false, patternEdge, false, parentNode, this);
+ assert parentNode.patternNode == patternEdge.getSource();
+ TreeNode oldNode = patternNode2treeNode.put(patternNode, this);
+ assert oldNode == null;
+ }
+
+ @Override
+ public String toString() {
+ return patternNode.toString();
+ }
+
+ @Override
+ protected void toString(@NonNull StringBuilder s, int depth) {
+ s.append(patternNode);
+ }
+ }
+
+ private class TreeRoot
+ {
+ protected final @NonNull RelDomainNode relDomainNode;
+ private @NonNull List<@NonNull TreeClassNode> rootNodes = new ArrayList<>();
+
+ public TreeRoot(@NonNull RelDomainNode relDomainNode) {
+ this.relDomainNode = relDomainNode;
+ treeRoots.add(this);
+ }
+
+ public void addNode(@NonNull TreeClassNode rootNode) {
+ rootNodes.add(rootNode);
+ }
+
+ public @NonNull String getName() {
+ TxTypedModelNode txTypedModelNode = relDomainNode.getReferredTxTypedModelNode();
+ if (txTypedModelNode != null) {
+ return UMLXUtil.getName(txTypedModelNode);
+ }
+ else {
+ return "«primitive»";
+ }
+ }
+
+ @Override
+ public String toString() {
+ return relDomainNode.toString();
+ }
+ }
+
+ protected final @NonNull UMLX2QVTr umlx2qvtr;
+ protected final @NonNull MetamodelManager metamodelManager;
+ protected final @NonNull RelDiagram relDiagram;
+ //
+ private final @NonNull List<@NonNull RelPatternClassNode> allNodes = new ArrayList<>();
+ private final @NonNull List<@NonNull TreeRoot> treeRoots = new ArrayList<>();
+ private final Map<@NonNull RelDomainNode, @NonNull TreeRoot> domainNode2treeRoot = new HashMap<>();
+ private final Map<@NonNull RelPatternNode, @NonNull TreeNode> patternNode2treeNode = new HashMap<>();
+ private final Map<@NonNull RelPatternEdge, @NonNull TreeEdge> patternEdge2treeEdge = new HashMap<>();
+ private final @NonNull Map<@NonNull RelPatternClassNode, @NonNull Element> relPatternNode2qvtrElement = new HashMap<>();
+ private final @NonNull List<@NonNull RelationDomain> allDomains = new ArrayList<>();
+ private final @NonNull List<@NonNull Variable> allVariables = new ArrayList<>();
+
+ public PatternForest(@NonNull UMLX2QVTr umlx2qvtr, @NonNull RelDiagram relDiagram) {
+ this.umlx2qvtr = umlx2qvtr;
+ EnvironmentFactory environmentFactory = umlx2qvtr.getEnvironmentFactory();
+ this.metamodelManager = environmentFactory.getMetamodelManager();
+ this.relDiagram = relDiagram;
+ analyzePatternRoots();
+ analyzePatternTree();
+ // analyzeIsolatedNodes();
+ analyzeRealizedEdges(); // FIXME not needed
+ // analyzeInvocationEdges(); // FIXME not needed
+ }
+
+ /* private void analyzeInvocationEdges() {
+ for (@NonNull RelInvocationNode relInvocationNode : UMLXUtil.getOwnedRelInvocationNodes(relDiagram)) {
+ for (@NonNull RelInvocationEdge relInvocationEdge : UMLXUtil.getOwnedRelInvocationEdges(relInvocationNode)) {
+ RelPatternNode invokingRelPatternNode = relInvocationEdge.getInvokingRelPatternNode();
+ TreeNode treeNode = patternNode2treeNode.get(invokingRelPatternNode);
+ assert treeNode != null;
+ treeNode.isInvoked = true;
+ }
+ }
+ } */
+
+ private void analyzePatternRoots() {
+ for (@NonNull RelDomainNode relDomainNode : UMLXUtil.getOwnedRelDomainNodes(relDiagram)) {
+ TreeRoot treeRoot = new TreeRoot(relDomainNode);
+ domainNode2treeRoot.put(relDomainNode, treeRoot);
+ for (@NonNull RelPatternNode relPatternNode : UMLXUtil.getOwnedRelPatternNodes(relDomainNode)) {
+ if (relPatternNode.isIsRoot() && (relPatternNode instanceof RelPatternClassNode)) {
+ RelPatternClassNode rootGraphNode = (RelPatternClassNode) relPatternNode;
+ patternNode2treeNode.put(rootGraphNode, new TreeClassNode(treeRoot, rootGraphNode));
+ }
+ }
+ }
+ }
+
+ private void analyzePatternTree() {
+ int iSimple = 0;
+ for (; iSimple < allNodes.size(); iSimple++) {
+ connectSimpleTreeEdges(allNodes.get(iSimple));
+ }
+ for (int iComplex = 0; iComplex < allNodes.size(); iComplex++) {
+ connectComplexTreeEdges(allNodes.get(iComplex));
+ for (; iSimple < allNodes.size(); iSimple++) {
+ connectSimpleTreeEdges(allNodes.get(iSimple));
+ }
+ }
+ //
+ // Identify the shared leaf nodes to be realized as shared variables.
+ //
+ // Set<@NonNull TreeNode> sharedTreeLeafNodes = new HashSet<>();
+ // for (@NonNull TreeNode rootTreeNode : treeRoots) {
+ // rootTreeNode.gatherSharedTreeLeafNodes(sharedTreeLeafNodes);
+ // }
+ }
+
+ private void analyzeRealizedEdges() {
+ for (@NonNull TreeRoot treeRoot : treeRoots) {
+ TxTypedModelNode txTypedModelNode = treeRoot.relDomainNode.getReferredTxTypedModelNode();
+ if ((txTypedModelNode != null) && txTypedModelNode.isEnforce()) {
+ for (@NonNull TreeClassNode rootNode : treeRoot.rootNodes) {
+ rootNode.setIsRealized();
+ }
+ }
+ }
+ }
+
+ private void connectComplexTreeEdges(@NonNull RelPatternClassNode relNode) {
+ for (@NonNull RelPatternEdge relPatternEdge : Iterables.concat(UMLXUtil.getOutgoing(relNode), UMLXUtil.getIncoming(relNode))) {
+ if (!patternEdge2treeEdge.containsKey(relPatternEdge)) {
+ RelPatternNode sourceNode = UMLXUtil.getSource(relPatternEdge);
+ TreeClassNode parentNode = (TreeClassNode) patternNode2treeNode.get(sourceNode);
+ if (parentNode != null) {
+ RelPatternNode targetNode = UMLXUtil.getTarget(relPatternEdge);
+ TreeNode childNode = patternNode2treeNode.get(targetNode);
+ if (childNode != null) {
+ new TreeEdge(true, relPatternEdge, false, parentNode, childNode);
+ }
+ else {
+ new TreeClassNode(relPatternEdge, false, parentNode);
+ }
+ }
+ else if (relPatternEdge.getReferredEStructuralFeature() instanceof EReference){
+ sourceNode = UMLXUtil.getTarget(relPatternEdge);
+ parentNode = (TreeClassNode) patternNode2treeNode.get(sourceNode);
+ if (parentNode != null) {
+ RelPatternNode targetNode = UMLXUtil.getSource(relPatternEdge);
+ TreeNode childNode = patternNode2treeNode.get(targetNode);
+ if (childNode != null) {
+ new TreeEdge(true, relPatternEdge, true, parentNode, childNode);
+ }
+ else {
+ new TreeClassNode(relPatternEdge, true, parentNode);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void connectSimpleTreeEdges(@NonNull RelPatternClassNode relNode) {
+ for (@NonNull RelPatternEdge relPatternEdge : Iterables.concat(UMLXUtil.getOutgoing(relNode), UMLXUtil.getIncoming(relNode))) {
+ if (!patternEdge2treeEdge.containsKey(relPatternEdge)) {
+ RelPatternNode sourceNode = UMLXUtil.getSource(relPatternEdge);
+ TreeClassNode parentNode = (TreeClassNode) patternNode2treeNode.get(sourceNode);
+ if (parentNode != null) {
+ EStructuralFeature eStructuralFeature = relPatternEdge.getReferredEStructuralFeature();
+ if ((eStructuralFeature != null) && !eStructuralFeature.isMany()) {
+ RelPatternNode targetNode = UMLXUtil.getTarget(relPatternEdge);
+ TreeNode childNode = patternNode2treeNode.get(targetNode);
+ if (childNode != null) {
+ new TreeEdge(true, relPatternEdge, false, parentNode, childNode);
+ }
+ else if (targetNode instanceof RelPatternClassNode) {
+ new TreeClassNode(relPatternEdge, false, parentNode);
+ }
+ else {
+ new TreeExpressionNode(relPatternEdge, parentNode);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * First pass, create all the declared elements.
+ */
+ public @NonNull Relation create() {
+ Iterable<@NonNull RelDomainNode> relDomainNodes = UMLXUtil.getOwnedRelDomainNodes(relDiagram);
+ //
+ // Create the nodes of the QVTr template pattern.
+ //
+ for (@NonNull RelDomainNode relDomainNode : relDomainNodes) {
+ for (@NonNull RelPatternNode relPatternNode : UMLXUtil.getOwnedRelPatternNodes(relDomainNode)) {
+ if (relPatternNode instanceof RelPatternClassNode) {
+ createRelationNode((RelPatternClassNode)relPatternNode);
+ }
+ }
+ }
+ //
+ // Create the edges of the QVTr template pattern.
+ //
+ for (@NonNull RelDomainNode relDomainNode : relDomainNodes) {
+ for (@NonNull RelPatternEdge relPatternEdge : UMLXUtil.getOwnedRelPatternEdges(relDomainNode)) {
+ createRelationEdge(relPatternEdge);
+ }
+ }
+ //
+ // Create the patterns of the QVTr template pattern.
+ //
+ for (@NonNull RelDomainNode relDomainNode : relDomainNodes) {
+ if (relDomainNode.getReferredTxTypedModelNode() != null) {
+ createRelationDomain(relDomainNode);
+ }
+ }
+ //
+ // Create the Relation
+ //
+ Relation qvtrRelation = createRelation();
+ //
+ // Create non-pattern shared variables
+ //
+ for (@NonNull RelDomainNode relDomainNode : relDomainNodes) {
+ for (@NonNull RelPatternNode relPatternNode : UMLXUtil.getOwnedRelPatternNodes(relDomainNode)) {
+ if (!relPatternNode.isIsRoot() && (relPatternNode instanceof RelPatternClassNode)) {
+ RelPatternClassNode relPatternClassNode = (RelPatternClassNode)relPatternNode;
+ TreeNode treeNode = patternNode2treeNode.get(relPatternClassNode);
+ if (treeNode == null) {
+ org.eclipse.ocl.pivot.Class asClass = umlx2qvtr.getReferredType(relPatternClassNode);
+ String name = relPatternClassNode.isIsAnon() ? null : UMLXUtil.getName(relPatternClassNode);
+ Variable variable = umlx2qvtr.createSharedVariable(name, asClass, relPatternClassNode.isIsRequired(), null);
+ qvtrRelation.getVariable().add(variable);
+ umlx2qvtr.install(relPatternClassNode, variable);
+ }
+ }
+ }
+ }
+ //
+ // Compute derived properties
+ //
+ for (@NonNull RelationDomain qvtrRelationDomain : allDomains) {
+ for (@NonNull DomainPattern qvtrDomainPattern : QVTrelationUtil.getOwnedPatterns(qvtrRelationDomain)) {
+ TemplateExp rootTemplateExpression = QVTrelationUtil.getOwnedTemplateExpression(qvtrDomainPattern);
+ qvtrRelationDomain.getRootVariable().add(QVTrelationUtil.getBindsTo(rootTemplateExpression));
+ List<@NonNull Variable> boundVariables = new ArrayList<>();
+ umlx2qvtr.computeBoundVariables(boundVariables, rootTemplateExpression);
+ List<Variable> bindsTo = qvtrDomainPattern.getBindsTo();
+ Iterables.addAll(ClassUtil.nullFree(bindsTo), boundVariables);
+ }
+ }
+ return qvtrRelation;
+ }
+
+ private @NonNull Relation createRelation() {
+ Relation qvtrRelation = umlx2qvtr.createRelation(UMLXUtil.getName(relDiagram), allDomains);
+ umlx2qvtr.install(relDiagram, qvtrRelation);
+ // Collections.sort(qvtrAllVariables, NameUtil.NAMEABLE_COMPARATOR);
+ // Iterables.addAll(QVTrelationUtil.Internal.getOwnedVariablesList(qvtrRelation), qvtrAllVariables);
+ qvtrRelation.setIsTopLevel(relDiagram.isIsTop());
+ qvtrRelation.getVariable().addAll(allVariables);
+ return qvtrRelation;
+ }
+
+ private @NonNull RelationDomain createRelationDomain(@NonNull RelDomainNode relDomainNode) {
+ TxTypedModelNode txTypedModelNode = UMLXUtil.getReferredTxTypedModelNode(relDomainNode);
+ TypedModel qvtrTypedModel = umlx2qvtr.getQVTrElement(TypedModel.class, txTypedModelNode);
+ RelationDomain qvtrRelationDomain = umlx2qvtr.createRelationDomain(qvtrTypedModel);
+ qvtrRelationDomain.setIsCheckable(txTypedModelNode.isCheck());
+ qvtrRelationDomain.setIsEnforceable(txTypedModelNode.isEnforce());
+ umlx2qvtr.install(relDomainNode, qvtrRelationDomain);
+ allDomains.add(qvtrRelationDomain);
+ //
+ TreeRoot treeRoot = domainNode2treeRoot.get(relDomainNode);
+ assert treeRoot != null;
+ for (@NonNull TreeClassNode rootNode : treeRoot.rootNodes) {
+ Element qvtrElement = relPatternNode2qvtrElement.get(rootNode.patternNode);
+ qvtrRelationDomain.getPattern().add(umlx2qvtr.createDomainPattern((TemplateExp)qvtrElement));
+ }
+ return qvtrRelationDomain;
+ }
+
+ private @Nullable Element createRelationEdge(@NonNull RelPatternEdge relPatternEdge) {
+ TreeEdge treeEdge = patternEdge2treeEdge.get(relPatternEdge);
+ assert treeEdge != null;
+ TreeNode treeSource = treeEdge.parent;
+ TreeNode treeTarget = treeEdge.child;
+ RelPatternClassNode relSource;
+ RelPatternNode relTarget;
+ EStructuralFeature eStructuralFeature = relPatternEdge.getReferredEStructuralFeature();
+ int sourceIndex;
+ if (treeEdge.isOpposite) {
+ relSource = (RelPatternClassNode) relPatternEdge.getTarget();
+ relTarget = relPatternEdge.getSource();
+ // eStructuralFeature = ((EReference)relPatternEdge.getReferredEStructuralFeature()).getEOpposite();
+ sourceIndex = 0;
+ }
+ else {
+ relSource = relPatternEdge.getSource();
+ relTarget = relPatternEdge.getTarget();
+ // eStructuralFeature = relPatternEdge.getReferredEStructuralFeature();
+ sourceIndex = relPatternEdge.getSourceIndex();
+ }
+ TemplateExp qvtrSourceExpression = (TemplateExp)relPatternNode2qvtrElement.get(relSource);
+ assert qvtrSourceExpression != null;
+ Element qvtrTarget = relPatternNode2qvtrElement.get(relTarget);
+ assert treeSource == patternNode2treeNode.get(relSource);
+ assert treeTarget == patternNode2treeNode.get(relTarget);
+ if (qvtrTarget == null) { // FIXME is a temporary StringLiteralExp still necessary?
+ RelPatternExpressionNode relPatternExpressionNode = ((TreeExpressionNode)treeTarget).patternNode;
+ StringBuilder s = new StringBuilder();
+ for (String line : relPatternExpressionNode.getInitExpressionLines()) {
+ s.append(line);
+ s.append("\n");
+ }
+ OCLExpression targetExpression = umlx2qvtr.createStringLiteralExp(s.toString());
+ umlx2qvtr.install(relPatternExpressionNode, targetExpression);
+ // addReference1(relPatternExpressionNode);
+ qvtrTarget = targetExpression;
+ }
+ assert (sourceIndex == 0) == (eStructuralFeature != null);
+ if (sourceIndex != 0) {
+ CollectionTemplateExp qvtrCollectionTemplateExp = (CollectionTemplateExp) qvtrSourceExpression;
+ if (sourceIndex < 0) {
+ qvtrCollectionTemplateExp.setRest((SharedVariable)qvtrTarget);
+ }
+ else {
+ int javaIndex = sourceIndex-1;
+ while (qvtrCollectionTemplateExp.getMember().size() < javaIndex) {
+ qvtrCollectionTemplateExp.getMember().add(umlx2qvtr.createNullLiteralExp());
+ }
+ if (qvtrTarget instanceof Variable) {
+ qvtrTarget = umlx2qvtr.createVariableExp((Variable)qvtrTarget);
+ }
+ if (javaIndex < qvtrCollectionTemplateExp.getMember().size()) {
+ qvtrCollectionTemplateExp.getMember().set(javaIndex, (OCLExpression)qvtrTarget);
+ }
+ else {
+ qvtrCollectionTemplateExp.getMember().add((OCLExpression)qvtrTarget);
+ }
+ }
+ }
+ else {
+ assert !(qvtrTarget instanceof VariableExp);
+ if (treeEdge.isGraph && (qvtrTarget instanceof TemplateExp)) {
+ qvtrTarget = ((TemplateExp)qvtrTarget).getBindsTo();
+ }
+ if (qvtrTarget instanceof VariableDeclaration) {
+ qvtrTarget = umlx2qvtr.createVariableExp((VariableDeclaration)qvtrTarget);
+ }
+ ObjectTemplateExp qvtrObjectTemplateExp = (ObjectTemplateExp) qvtrSourceExpression;
+ Property asProperty = metamodelManager.getASOfEcore(Property.class, eStructuralFeature);
+ assert asProperty != null;
+ if (treeEdge.isOpposite) {
+ asProperty = asProperty.getOpposite();
+ assert asProperty != null;
+ }
+ assert qvtrTarget != null;
+ qvtrObjectTemplateExp.getPart().add(umlx2qvtr.createPropertyTemplateItem(asProperty, (OCLExpression)qvtrTarget));
+ }
+ return null;
+ }
+
+ private @Nullable Element createRelationNode(@NonNull RelPatternClassNode relPatternClassNode) {
+ TreeClassNode treeNode = (TreeClassNode) patternNode2treeNode.get(relPatternClassNode);
+ if (treeNode == null) {
+ // FIXME create shared variable
+ return null;
+ }
+ Variable asVariable = treeNode.getVariable();
+ // if (asVariable != null) {
+ // return asVariable;
+ // }
+ if (asVariable instanceof TemplateVariable) {
+ TemplateExp qvtrExpression = null;
+ org.eclipse.ocl.pivot.Class type = (org.eclipse.ocl.pivot.Class)asVariable.getType();
+ if (type == null) {
+ type = metamodelManager.getStandardLibrary().getOclInvalidType();
+ }
+ for (@NonNull TreeEdge childEdge : treeNode.childEdges) {
+ if (childEdge.patternEdge.getSourceIndex() != 0) {
+ qvtrExpression = umlx2qvtr.createCollectionTemplateExp((TemplateVariable) asVariable, type, asVariable.isIsRequired());
+ break;
+ }
+ }
+ if ((qvtrExpression == null) && asVariable.isIsMany()) {
+ qvtrExpression = umlx2qvtr.createCollectionTemplateExp((TemplateVariable) asVariable, type, asVariable.isIsRequired());
+ }
+ if (qvtrExpression == null) {
+ qvtrExpression = umlx2qvtr.createObjectTemplateExp((TemplateVariable) asVariable, type, asVariable.isIsRequired());
+ }
+ relPatternNode2qvtrElement.put(relPatternClassNode, qvtrExpression);
+ umlx2qvtr.install(relPatternClassNode, qvtrExpression);
+ return qvtrExpression;
+ }
+ else {
+ relPatternNode2qvtrElement.put(relPatternClassNode, asVariable);
+ return asVariable;
+ }
+ }
+
+ /**
+ * Second pass after all internal and external symbol defined; parse the OCL expression text.
+ */
+ public void resolveExpressions() {
+ for (@NonNull RelDomainNode relDomainNode : UMLXUtil.getOwnedRelDomainNodes(relDiagram)) {
+ for (@NonNull RelPatternNode relPatternNode : UMLXUtil.getOwnedRelPatternNodes(relDomainNode)) {
+ List<String> lines = relPatternNode.getInitExpressionLines();
+ if (lines.size() > 0) {
+ if (relPatternNode instanceof RelPatternClassNode) {
+ resolveRelPatternClassNodeExpression((@NonNull RelPatternClassNode) relPatternNode);
+ }
+ else {
+ resolveRelPatternExpressionNodeExpression((@NonNull RelPatternExpressionNode) relPatternNode);
+ }
+ }
+ }
+ }
+ for (@NonNull RelInvocationNode relInvocationNode : UMLXUtil.getOwnedRelInvocationNodes(relDiagram)) {
+ resolveInvocation(relInvocationNode);
+ // for (@NonNull RelInvocationEdge relInvocationEdge : UMLXUtil.getOwnedRelInvocationEdges(relInvocationNode)) {
+ // RelPatternNode invokingRelPatternNode = relInvocationEdge.getInvokingRelPatternNode();
+ // TreeNode treeNode = patternNode2treeNode.get(invokingRelPatternNode);
+ // assert treeNode != null;
+ // treeNode.isInvoked = true;
+ // }
+ }
+ }
+
+ private void resolveRelPatternClassNodeExpression(@NonNull RelPatternClassNode relPatternClassNode) {
+ SharedVariable qvtrVariable = umlx2qvtr.getQVTrElement(SharedVariable.class, relPatternClassNode);
+ List<String> lines = relPatternClassNode.getInitExpressionLines();
+ if (lines.size() > 0) {
+ OCLExpression qvtrExpression = umlx2qvtr.parseContextualExpression(qvtrVariable, lines);
+ qvtrVariable.setOwnedInit(qvtrExpression);
+ }
+ }
+
+ private void resolveRelPatternExpressionNodeExpression( @NonNull RelPatternExpressionNode relPatternExpressionNode) {
+ StringLiteralExp stringExpression = umlx2qvtr.basicGetQVTrElement(StringLiteralExp.class, relPatternExpressionNode);
+ if (stringExpression != null) {
+ resolveMemberExpression(relPatternExpressionNode, stringExpression);
+ }
+ else if (relPatternExpressionNode.getInvokingRelInvocationEdges().isEmpty()) {
+ // OCLExpression qvtrExpression = createUnparsedExpression(relPatternExpressionNode);
+ // addWhenPredicate(qvtrRelation, qvtrExpression);
+ }
+ else {
+ Relation qvtrRelation = umlx2qvtr.getQVTrElement(Relation.class, relDiagram);
+ OCLExpression qvtrExpression = umlx2qvtr.parseContextualExpression(qvtrRelation, UMLXUtil.getInitExpressionLines(relPatternExpressionNode));
+ assert qvtrExpression != null;
+ umlx2qvtr.install(relPatternExpressionNode, qvtrExpression);
+ }
+ }
+
+ protected void resolveMemberExpression(@NonNull RelPatternExpressionNode relPatternExpressionNode, @NonNull StringLiteralExp stringExpression) {
+ String textExpression = stringExpression.getStringSymbol();
+ final EObject eContainer = stringExpression.eContainer();
+ assert eContainer != null;
+ OCLExpression qvtrExpression = umlx2qvtr.parseContextualExpression(eContainer, Collections.singletonList(textExpression));
+ if (qvtrExpression != null) {
+ EReference eContainmentFeature = stringExpression.eContainmentFeature();
+ PivotUtilInternal.resetContainer(stringExpression);
+ eContainer.eSet(eContainmentFeature, qvtrExpression);
+ // context.reinstall(relPatternExpressionNode, qvtrExpression);
+ }
+ }
+
+ private @Nullable Element resolveInvocation(@NonNull RelInvocationNode relInvocationNode) {
+ List<@NonNull OCLExpression> qvtrArguments = new ArrayList<>();
+ for (@NonNull RelInvocationEdge relInvocationEdge : UMLXUtil.getOwnedRelInvocationEdges(relInvocationNode)) {
+ // relInvocationEdge.get
+ RelPatternNode referredRelPatternNode = UMLXUtil.getInvokingRelPatternNode(relInvocationEdge); //UMLXUtil.getReferredRelPatternNode(relInvocationEdge);
+ Element qvtrElement = umlx2qvtr.getQVTrElement(Element.class, referredRelPatternNode);
+ if (qvtrElement instanceof TemplateExp) {
+ qvtrElement = ((TemplateExp)qvtrElement).getBindsTo();
+ }
+ if (qvtrElement instanceof Variable) {
+ qvtrElement = umlx2qvtr.createVariableExp((Variable)qvtrElement);
+ }
+ assert qvtrElement != null;
+ qvtrArguments.add((OCLExpression)qvtrElement);
+ }
+ RelDiagram referredRelDiagram = UMLXUtil.getReferredRelDiagram(relInvocationNode);
+ Relation qvtrReferredRelation = umlx2qvtr.getQVTrElement(Relation.class, referredRelDiagram);
+ RelationCallExp qvtrRelationCallExp = umlx2qvtr.createRelationCallExp(qvtrReferredRelation, qvtrArguments);
+ RelDiagram relDiagram = UMLXUtil.getOwningRelDiagram(relInvocationNode);
+ Relation qvtrRelation = umlx2qvtr.getQVTrElement(Relation.class, relDiagram);
+ if (!relInvocationNode.isIsThen()) {
+ umlx2qvtr.addWhenPredicate(qvtrRelation, qvtrRelationCallExp);
+ }
+ else {
+ umlx2qvtr.addWherePredicate(qvtrRelation, qvtrRelationCallExp);
+ }
+ return qvtrRelationCallExp;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder s = new StringBuilder();
+ s.append(relDiagram.getName());
+ for (@NonNull TreeRoot treeRoot : treeRoots) {
+ s.append("\n" + String.valueOf(treeRoot.getName()));
+ for (@NonNull TreeNode treeNode : treeRoot.rootNodes) {
+ s.append("\n ");
+ treeNode.toString(s, 1);
+ }
+ }
+ return s.toString();
+ }
+}
diff --git a/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/umlx2qvtr/UMLX2QVTr.java b/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/umlx2qvtr/UMLX2QVTr.java
index cd2f881fe..3a80744a7 100644
--- a/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/umlx2qvtr/UMLX2QVTr.java
+++ b/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/umlx2qvtr/UMLX2QVTr.java
@@ -12,25 +12,19 @@ package org.eclipse.qvtd.umlx.umlx2qvtr;
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.StringTokenizer;
import org.eclipse.emf.common.util.URI;
-import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
-import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
-import org.eclipse.ocl.pivot.CollectionType;
-import org.eclipse.ocl.pivot.DataType;
import org.eclipse.ocl.pivot.Element;
import org.eclipse.ocl.pivot.ExpressionInOCL;
import org.eclipse.ocl.pivot.Import;
@@ -38,16 +32,11 @@ import org.eclipse.ocl.pivot.InvalidType;
import org.eclipse.ocl.pivot.Namespace;
import org.eclipse.ocl.pivot.OCLExpression;
import org.eclipse.ocl.pivot.Property;
-import org.eclipse.ocl.pivot.StandardLibrary;
-import org.eclipse.ocl.pivot.StringLiteralExp;
-import org.eclipse.ocl.pivot.Variable;
-import org.eclipse.ocl.pivot.VariableExp;
import org.eclipse.ocl.pivot.internal.context.AbstractParserContext;
import org.eclipse.ocl.pivot.internal.manager.PivotMetamodelManager;
import org.eclipse.ocl.pivot.internal.scoping.EnvironmentView;
import org.eclipse.ocl.pivot.internal.scoping.ScopeView;
import org.eclipse.ocl.pivot.internal.utilities.PivotUtilInternal;
-import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.ocl.pivot.utilities.EnvironmentFactory;
import org.eclipse.ocl.pivot.utilities.MetamodelManager;
import org.eclipse.ocl.pivot.utilities.NameUtil;
@@ -55,303 +44,36 @@ import org.eclipse.ocl.pivot.utilities.ParserContext;
import org.eclipse.ocl.pivot.utilities.ParserException;
import org.eclipse.ocl.pivot.utilities.PivotUtil;
import org.eclipse.qvtd.compiler.CompilerChainException;
+import org.eclipse.qvtd.pivot.qvtbase.Function;
+import org.eclipse.qvtd.pivot.qvtbase.FunctionParameter;
import org.eclipse.qvtd.pivot.qvtbase.Rule;
import org.eclipse.qvtd.pivot.qvtbase.TypedModel;
import org.eclipse.qvtd.pivot.qvtbase.utilities.QVTbaseUtil;
-import org.eclipse.qvtd.pivot.qvtrelation.DomainPattern;
import org.eclipse.qvtd.pivot.qvtrelation.Key;
import org.eclipse.qvtd.pivot.qvtrelation.QVTrelationFactory;
-import org.eclipse.qvtd.pivot.qvtrelation.Relation;
-import org.eclipse.qvtd.pivot.qvtrelation.RelationCallExp;
-import org.eclipse.qvtd.pivot.qvtrelation.RelationDomain;
import org.eclipse.qvtd.pivot.qvtrelation.RelationModel;
import org.eclipse.qvtd.pivot.qvtrelation.RelationalTransformation;
-import org.eclipse.qvtd.pivot.qvtrelation.SharedVariable;
-import org.eclipse.qvtd.pivot.qvtrelation.TemplateVariable;
import org.eclipse.qvtd.pivot.qvtrelation.utilities.QVTrelationHelper;
import org.eclipse.qvtd.pivot.qvtrelation.utilities.QVTrelationUtil;
-import org.eclipse.qvtd.pivot.qvttemplate.CollectionTemplateExp;
-import org.eclipse.qvtd.pivot.qvttemplate.ObjectTemplateExp;
-import org.eclipse.qvtd.pivot.qvttemplate.PropertyTemplateItem;
-import org.eclipse.qvtd.pivot.qvttemplate.TemplateExp;
import org.eclipse.qvtd.umlx.RelDiagram;
-import org.eclipse.qvtd.umlx.RelDomainNode;
-import org.eclipse.qvtd.umlx.RelInvocationEdge;
-import org.eclipse.qvtd.umlx.RelInvocationNode;
-import org.eclipse.qvtd.umlx.RelPatternNode;
-import org.eclipse.qvtd.umlx.RelPatternEdge;
-import org.eclipse.qvtd.umlx.RelPatternExpressionNode;
-import org.eclipse.qvtd.umlx.RelPatternClassNode;
import org.eclipse.qvtd.umlx.TxDiagram;
import org.eclipse.qvtd.umlx.TxImportNode;
import org.eclipse.qvtd.umlx.TxKeyNode;
import org.eclipse.qvtd.umlx.TxPackageNode;
+import org.eclipse.qvtd.umlx.TxParameterNode;
import org.eclipse.qvtd.umlx.TxPartNode;
+import org.eclipse.qvtd.umlx.TxQueryNode;
import org.eclipse.qvtd.umlx.TxTypedModelNode;
import org.eclipse.qvtd.umlx.UMLXElement;
import org.eclipse.qvtd.umlx.UMLXModel;
+import org.eclipse.qvtd.umlx.UMLXTypedElement;
import org.eclipse.qvtd.umlx.util.AbstractExtendingUMLXVisitor;
import org.eclipse.qvtd.umlx.utilities.UMLXUtil;
import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
public class UMLX2QVTr extends QVTrelationHelper
{
- protected static class ConnectionHelper
- {
- protected final @NonNull UMLX2QVTr context;
- protected final @NonNull MetamodelManager metamodelManager;
- private final @NonNull Map<@NonNull RelPatternClassNode, @NonNull OCLExpression> relPatternNode2qvtrExpression = new HashMap<>();
- private final @NonNull Set<@NonNull RelPatternEdge> connectedEdges = new HashSet<>();
- private final @NonNull Set<@NonNull RelPatternClassNode> connectedClassNodeSet = new HashSet<>();
-
- public ConnectionHelper(@NonNull UMLX2QVTr context) {
- this.context = context;
- this.metamodelManager = context.getMetamodelManager();
- }
-
- private boolean connectCollectionEdge(@NonNull RelPatternClassNode sourceNode, int sourceIndex, @NonNull RelPatternNode targetNode) {
- CollectionTemplateExp sourceTemplateExp = (CollectionTemplateExp) relPatternNode2qvtrExpression.get(sourceNode);
- OCLExpression targetExpression = relPatternNode2qvtrExpression.get(targetNode);
- assert sourceTemplateExp != null;
- if (sourceIndex > 0) {
- if (targetExpression == null) {
- if (targetNode instanceof RelPatternExpressionNode) {
- targetExpression = createUnparsedExpression((RelPatternExpressionNode) targetNode);
- }
- else {
- SharedVariable sharedVariable = context.getQVTrElement(SharedVariable.class, targetNode);
- targetExpression = context.createVariableExp(sharedVariable);
- }
- }
- List<@NonNull OCLExpression> ownedMembersList = QVTrelationUtil.Internal.getOwnedMembersList(sourceTemplateExp);
- int javaIndex = sourceIndex - 1;
- while (ownedMembersList.size() < javaIndex) {
- ownedMembersList.add(context.createNullLiteralExp());
- }
- if (ownedMembersList.size() == javaIndex) {
- ownedMembersList.add(targetExpression);
- }
- else {
- ownedMembersList.set(javaIndex, targetExpression);
- }
- return true;
- }
- else if (sourceIndex < 0) {
- SharedVariable sharedVariable = context.getQVTrElement(SharedVariable.class, targetNode);
- sourceTemplateExp.setRest(sharedVariable);
- return true;
- }
- else {
- return false;
- }
- }
-
- private boolean connectComplexEdge(@NonNull RelPatternClassNode sourceNode, @NonNull EStructuralFeature eStructuralFeature, @NonNull RelPatternNode targetNode) {
- EReference eReference = (EReference)eStructuralFeature;
- // assert !eReference.isMany();
- // EReference eOpposite = eReference.getEOpposite();
- // if ((eOpposite != null) && (targetNode instanceof RelPatternClassNode)) {
- // connect((RelPatternClassNode)targetNode, eOpposite, sourceNode);
- // return true;
- // }
- connectObjectEdge(sourceNode, eStructuralFeature, targetNode);
- return true;
- // throw new UnsupportedOperationException();
- // return false;
- }
-
- private @NonNull Iterable<@NonNull RelPatternClassNode> connectComplexEdges(@NonNull RelPatternClassNode relNode) {
- List<@NonNull RelPatternClassNode> newClassNodes = new ArrayList<>();
- for (@NonNull RelPatternEdge relEdge : UMLXUtil.getOutgoing(relNode)) {
- if (!connectedEdges.contains(relEdge)) {
- RelPatternClassNode sourceNode = relNode;
- EStructuralFeature eStructuralFeature = relEdge.getReferredEStructuralFeature();
- RelPatternNode targetNode = UMLXUtil.getTarget(relEdge);
- if (eStructuralFeature != null) {
- if (connectComplexEdge(sourceNode, eStructuralFeature, targetNode)) {
- if (targetNode instanceof RelPatternClassNode) {
- newClassNodes.add((RelPatternClassNode)targetNode);
- }
- connectedEdges.add(relEdge);
- }
- }
- else {
- if (connectCollectionEdge(sourceNode, relEdge.getSourceIndex(), targetNode)) {
- if (targetNode instanceof RelPatternClassNode) {
- newClassNodes.add((RelPatternClassNode)targetNode);
- }
- connectedEdges.add(relEdge);
- }
- }
- }
- }
- for (@NonNull RelPatternEdge relEdge : UMLXUtil.getIncoming(relNode)) {
- if (!connectedEdges.contains(relEdge)) {
- RelPatternClassNode sourceNode = UMLXUtil.getSource(relEdge);
- EStructuralFeature eStructuralFeature = relEdge.getReferredEStructuralFeature();
- RelPatternClassNode targetNode = relNode;
- if (eStructuralFeature != null) {
- if (connectComplexEdge(sourceNode, eStructuralFeature, targetNode)) {
- newClassNodes.add(targetNode);
- connectedEdges.add(relEdge);
- }
- }
- else {
- if (connectCollectionEdge(sourceNode, relEdge.getSourceIndex(), targetNode)) {
- if (targetNode instanceof RelPatternClassNode) {
- newClassNodes.add(targetNode);
- }
- connectedEdges.add(relEdge);
- }
- }
- }
- }
- return newClassNodes;
- }
-
- public void connectNodes(@NonNull Iterable<@NonNull RelPatternClassNode> relRootPatternClassNodes) {
- List<@NonNull RelPatternClassNode> connectedClassNodeList = Lists.newArrayList(relRootPatternClassNodes);
- connectedClassNodeSet.addAll(connectedClassNodeList);
- int iSimple = 0;
- for (; iSimple < connectedClassNodeList.size(); iSimple++) {
- RelPatternClassNode connectableClassNode = connectedClassNodeList.get(iSimple);
- Iterable<@NonNull RelPatternClassNode> newClassNodes = connectSimpleEdges(connectableClassNode);
- for (@NonNull RelPatternClassNode newClassNode : newClassNodes) {
- if (connectedClassNodeSet.add(newClassNode)) {
- connectedClassNodeList.add(newClassNode);
- }
- }
- }
- for (int iComplex = 0; iComplex < connectedClassNodeList.size(); iComplex++) {
- RelPatternClassNode connectableClassNode = connectedClassNodeList.get(iComplex);
- Iterable<@NonNull RelPatternClassNode> newClassNodes = connectComplexEdges(connectableClassNode);
- for (@NonNull RelPatternClassNode newClassNode : newClassNodes) {
- if (connectedClassNodeSet.add(newClassNode)) {
- connectedClassNodeList.add(newClassNode);
- }
- }
- for (; iSimple < connectedClassNodeList.size(); iSimple++) {
- RelPatternClassNode connectableClassNode2 = connectedClassNodeList.get(iSimple);
- Iterable<@NonNull RelPatternClassNode> newClassNodes2 = connectSimpleEdges(connectableClassNode2);
- for (@NonNull RelPatternClassNode newClassNode : newClassNodes2) {
- if (connectedClassNodeSet.add(newClassNode)) {
- connectedClassNodeList.add(newClassNode);
- }
- }
- }
- }
- }
-
- private void connectObjectEdge(@NonNull RelPatternClassNode sourceNode, @NonNull EStructuralFeature eStructuralFeature, @NonNull RelPatternNode targetNode) {
- ObjectTemplateExp sourceTemplateExp = (ObjectTemplateExp) relPatternNode2qvtrExpression.get(sourceNode);
- OCLExpression targetExpression = relPatternNode2qvtrExpression.get(targetNode);
- assert sourceTemplateExp != null;
- if (targetExpression == null) {
- if (targetNode instanceof RelPatternExpressionNode) {
- targetExpression = createUnparsedExpression((RelPatternExpressionNode)targetNode);
- }
- else {
- SharedVariable sharedVariable = context.getQVTrElement(SharedVariable.class, targetNode);
- targetExpression = context.createVariableExp(sharedVariable);
- }
- }
- Property asProperty = metamodelManager.getASOfEcore(Property.class, eStructuralFeature);
- assert asProperty != null;
- // if (txPartNode.isIsOpposite()) {
- // asProperty = asProperty.getOpposite();
- // }
- PropertyTemplateItem qvtrPropertyTemplateItem = context.createPropertyTemplateItem(asProperty, targetExpression);
- QVTrelationUtil.Internal.getOwnedPartsList(sourceTemplateExp).add(qvtrPropertyTemplateItem);
- }
-
- private boolean connectSimpleEdge(@NonNull RelPatternClassNode sourceNode, @NonNull EStructuralFeature eStructuralFeature, @NonNull RelPatternNode targetNode) {
- if (eStructuralFeature instanceof EAttribute) {
- EAttribute eAttribute = (EAttribute)eStructuralFeature;
- connectObjectEdge(sourceNode, eAttribute, targetNode);
- return true;
- }
- EReference eReference = (EReference)eStructuralFeature;
- if (!eReference.isMany()) {
- connectObjectEdge(sourceNode, eReference, targetNode);
- return true;
- }
- if (connectedClassNodeSet.contains(targetNode)) {
- EReference eOpposite = eReference.getEOpposite();
- if (eOpposite != null) {
- connectObjectEdge((RelPatternClassNode)targetNode, eOpposite, sourceNode);
- return true;
- }
- }
- return false;
- }
-
- private @NonNull Iterable<@NonNull RelPatternClassNode> connectSimpleEdges(@NonNull RelPatternClassNode relNode) {
- List<@NonNull RelPatternClassNode> newClassNodes = new ArrayList<>();
- for (@NonNull RelPatternEdge relEdge : UMLXUtil.getOutgoing(relNode)) {
- if (!connectedEdges.contains(relEdge)) {
- RelPatternClassNode sourceNode = relNode;
- EStructuralFeature eStructuralFeature = relEdge.getReferredEStructuralFeature();
- RelPatternNode targetNode = UMLXUtil.getTarget(relEdge);
- if (eStructuralFeature != null) {
- if (connectSimpleEdge(sourceNode, eStructuralFeature, targetNode)) {
- if (targetNode instanceof RelPatternClassNode) {
- newClassNodes.add((RelPatternClassNode)targetNode);
- }
- connectedEdges.add(relEdge);
- }
- }
- else {
- if (connectCollectionEdge(sourceNode, relEdge.getSourceIndex(), targetNode)) {
- if (targetNode instanceof RelPatternClassNode) {
- newClassNodes.add((RelPatternClassNode)targetNode);
- }
- connectedEdges.add(relEdge);
- }
- }
- }
- }
- for (@NonNull RelPatternEdge relEdge : UMLXUtil.getIncoming(relNode)) {
- if (!connectedEdges.contains(relEdge)) {
- RelPatternClassNode sourceNode = UMLXUtil.getSource(relEdge);
- EStructuralFeature eStructuralFeature = relEdge.getReferredEStructuralFeature();
- RelPatternClassNode targetNode = relNode;
- if (eStructuralFeature != null) {
- if (connectSimpleEdge(sourceNode, eStructuralFeature, targetNode)) {
- newClassNodes.add(targetNode);
- connectedEdges.add(relEdge);
- }
- }
- else {
- if (connectCollectionEdge(sourceNode, relEdge.getSourceIndex(), targetNode)) {
- if (targetNode instanceof RelPatternClassNode) {
- newClassNodes.add(targetNode);
- }
- connectedEdges.add(relEdge);
- }
- }
- }
- }
- return newClassNodes;
- }
-
- protected @NonNull OCLExpression createUnparsedExpression(@NonNull RelPatternExpressionNode relPatternExpressionNode) {
- OCLExpression targetExpression = context.createStringLiteralExp(UMLXUtil.getExpression(relPatternExpressionNode));
- context.install(relPatternExpressionNode, targetExpression);
- context.addReference(relPatternExpressionNode);
- return targetExpression;
- }
-
- private OCLExpression get(@NonNull RelPatternClassNode relPatternNode) {
- return relPatternNode2qvtrExpression.get(relPatternNode);
- }
-
- private void put(@NonNull RelPatternClassNode relPatternNode, @NonNull OCLExpression qvtrExpression) {
- relPatternNode2qvtrExpression.put(relPatternNode, qvtrExpression);
- }
- }
-
protected static class CreateVisitor extends AbstractExtendingUMLXVisitor<@Nullable Element, @NonNull UMLX2QVTr>
{
protected final @NonNull MetamodelManager metamodelManager;
@@ -364,15 +86,7 @@ public class UMLX2QVTr extends QVTrelationHelper
this.qvtrModel = qvtrModel;
}
- public <T1 extends UMLXElement, T2 extends Element> @Nullable T2 create(@Nullable T1 source) {
- if (source == null) {
- return null;
- }
- @SuppressWarnings("unchecked") @Nullable T2 target = (T2) source.accept(this);
- return target;
- }
-
- public <@NonNull T1 extends UMLXElement, T2 extends Element> void createAll(/*@NonNull*/ Iterable<T1> sources, /*@NonNull*/ List<? super T2> targets) {
+ private <@NonNull T1 extends UMLXElement, T2 extends Element> void createAll(/*@NonNull*/ Iterable<T1> sources, /*@NonNull*/ List<? super T2> targets) {
for (T1 source : sources) {
@SuppressWarnings("unchecked") T2 target = (T2) source.accept(this);
if ((target != null) && (targets != null)) {
@@ -381,70 +95,7 @@ public class UMLX2QVTr extends QVTrelationHelper
}
}
- /**
- * Accumulate a TemplateExp and TemplateVariable for relPatternNode and all transitively EReference-connection RelPatternNode in qvtrDomainClassNodes.
- * No relationships between TemplateExps are established here.
- * Return the TemplateExp for relPatternNode.
- */
- private @NonNull OCLExpression createDomainPatternNodes(@NonNull RelPatternClassNode relPatternClassNode, @NonNull ConnectionHelper connectionHelper) {
- OCLExpression qvtrTemplateExp = connectionHelper.get(relPatternClassNode);
- if (qvtrTemplateExp == null) {
- Variable asVariable = visit(Variable.class, relPatternClassNode);
- if (asVariable instanceof TemplateVariable) {
- TemplateVariable asTemplateVariable = (TemplateVariable)asVariable;
- org.eclipse.ocl.pivot.Class asClass = metamodelManager.getASOfEcore(org.eclipse.ocl.pivot.Class.class, relPatternClassNode.getReferredEClassifier());
- assert asClass != null;
- if (relPatternClassNode.isIsMany()/*asClass instanceof CollectionType*/) {
- qvtrTemplateExp = context.createCollectionTemplateExp(asTemplateVariable, (CollectionType)asVariable.getType(), relPatternClassNode.isIsRequired());
- }
- else {
- qvtrTemplateExp = context.createObjectTemplateExp(asTemplateVariable, asClass, relPatternClassNode.isIsRequired());
- }
- // context.putUMLX2QVTrTrace(relPatternNode, qvtrTemplateExp);
- connectionHelper.put(relPatternClassNode, qvtrTemplateExp);
- for (@NonNull RelPatternEdge relPatternEdge : UMLXUtil.getOutgoing(relPatternClassNode)) {
- RelPatternNode relTargetNode = UMLXUtil.getTarget(relPatternEdge);
- EStructuralFeature eStructuralFeature = relPatternEdge.getReferredEStructuralFeature();
- if ((relTargetNode instanceof RelPatternClassNode) && !(eStructuralFeature instanceof EAttribute)) {
- createDomainPatternNodes((RelPatternClassNode)relTargetNode, connectionHelper);
- }
- }
- for (@NonNull RelPatternEdge relPatternEdge : UMLXUtil.getIncoming(relPatternClassNode)) {
- RelPatternClassNode relSourceNode = UMLXUtil.getSource(relPatternEdge);
- EStructuralFeature eStructuralFeature = relPatternEdge.getReferredEStructuralFeature();
- if (!(eStructuralFeature instanceof EAttribute)) {
- createDomainPatternNodes(relSourceNode, connectionHelper);
- }
- }
- }
- else {
- qvtrTemplateExp = context.createVariableExp(asVariable);
- }
- }
- return qvtrTemplateExp;
- }
-
- /**
- * Return the most positive non-zero source index of all incoming edges. Returns null if no incoming edge has a
- * non-zeto source index.
- */
- private @Nullable Integer getIncomingSourceIndex(@NonNull RelPatternClassNode relPatternClassNode) {
- Integer mostPositiveSourceIndex = null;
- for (@NonNull RelPatternEdge relPatternEdge : UMLXUtil.getIncoming(relPatternClassNode)) {
- int sourceIndex = relPatternEdge.getSourceIndex();
- if (sourceIndex != 0) {
- if (mostPositiveSourceIndex == null) {
- mostPositiveSourceIndex = sourceIndex;
- }
- else if (mostPositiveSourceIndex < sourceIndex) {
- mostPositiveSourceIndex = sourceIndex;
- }
- }
- }
- return mostPositiveSourceIndex;
- }
-
- public org.eclipse.ocl.pivot.@NonNull Package getPackage(org.eclipse.ocl.pivot.@Nullable Package asParentPackage, @NonNull String name) {
+ private org.eclipse.ocl.pivot.@NonNull Package getPackage(org.eclipse.ocl.pivot.@Nullable Package asParentPackage, @NonNull String name) {
List<org.eclipse.ocl.pivot.@NonNull Package> asPackages = (asParentPackage != null ? QVTbaseUtil.Internal.getOwnedPackagesList(asParentPackage) : QVTbaseUtil.Internal.getOwnedPackagesList(qvtrModel));
org.eclipse.ocl.pivot.Package qvtrPackage = NameUtil.getNameable(asPackages, name);
if (qvtrPackage == null) {
@@ -456,29 +107,7 @@ public class UMLX2QVTr extends QVTrelationHelper
return qvtrPackage;
}
- public org.eclipse.ocl.pivot.@NonNull Package getRootPackage(@NonNull String name) {
- org.eclipse.ocl.pivot.Package qvtrPackage = NameUtil.getNameable(qvtrModel.getOwnedPackages(), name);
- if (qvtrPackage == null) {
- @NonNull String nsURI = "http:/fixme"; // FIXME
- qvtrPackage = PivotUtil.createPackage(name, null, nsURI, null);
- qvtrModel.getOwnedPackages().add(qvtrPackage);
- }
- return qvtrPackage;
- }
-
- protected <T extends Element> @NonNull T visit(@NonNull Class<T> qvtrClass, @NonNull UMLXElement umlxElement) {
- Element qvtrElement = umlxElement.accept(this);
- if (qvtrElement == null) {
- throw new IllegalArgumentException("Missing UMLX element for " + umlxElement);
- }
- if (!qvtrClass.isAssignableFrom(qvtrElement.getClass())) {
- throw new ClassCastException("UMLX element " + qvtrElement + " cannot be cast to " + qvtrClass);
- }
- @SuppressWarnings("unchecked")T castElement = (T)qvtrElement;
- return castElement;
- }
-
- public void visitAll(/*@NonNull*/ Iterable<? extends @NonNull UMLXElement> sources) {
+ private void visitAll(/*@NonNull*/ Iterable<? extends @NonNull UMLXElement> sources) {
for (@NonNull UMLXElement source : sources) {
source.accept(this);
}
@@ -486,126 +115,9 @@ public class UMLX2QVTr extends QVTrelationHelper
@Override
public @Nullable Element visitRelDiagram(@NonNull RelDiagram relDiagram) {
- List<@NonNull RelationDomain> qvtrRelationDomains = new ArrayList<>();
- ConnectionHelper connectionHelper = new ConnectionHelper(context);
- // Iterable<@NonNull RelPatternNode> relNodes = UMLXUtil.getOwnedNodes(relDiagram);
- List<@NonNull RelPatternClassNode> relRootPatternClassNodes = new ArrayList<>();
- for (@NonNull RelDomainNode relDomainNode : UMLXUtil.getOwnedRelDomainNodes(relDiagram)) {
- if (relDomainNode.getReferredTxTypedModelNode() != null) {
- //
- // Create the RelationDomain
- //
- RelationDomain qvtrRelationDomain = visit(RelationDomain.class, relDomainNode);
- qvtrRelationDomains.add(qvtrRelationDomain);
- //
- // Create each DomainPattern, TemplateExp and TemplateVariable
- //
- for (@NonNull RelPatternNode relPatternNode : UMLXUtil.getOwnedRelPatternNodes(relDomainNode)) {
- if (relPatternNode.isIsRoot() && (relPatternNode instanceof RelPatternClassNode)) {
- OCLExpression qvtrTemplateExp = createDomainPatternNodes((@NonNull RelPatternClassNode) relPatternNode, connectionHelper);
- DomainPattern qvtrRootPattern = context.createDomainPattern((TemplateExp) qvtrTemplateExp);
- qvtrRelationDomain.getPattern().add(qvtrRootPattern);
- relRootPatternClassNodes.add((RelPatternClassNode) relPatternNode);
- }
- }
- }
- }
- for (@NonNull RelInvocationNode relInvocationNode : UMLXUtil.getOwnedRelInvocationNodes(relDiagram)) {
- visit(relInvocationNode);
- }
- //
- // Gather the TemplateVariables, create the SharedVariables
- //
- List<@NonNull Variable> qvtrAllVariables = new ArrayList<>();
- for (@NonNull RelDomainNode relDomainNode : UMLXUtil.getOwnedRelDomainNodes(relDiagram)) {
- for (@NonNull RelPatternNode relNode : UMLXUtil.getOwnedRelPatternNodes(relDomainNode)) {
- if (relNode instanceof RelPatternClassNode) {
- RelPatternClassNode relPatternNode = (RelPatternClassNode) relNode;
- Variable asVariable = context.basicGetQVTrElement(Variable.class, relPatternNode);
- if (asVariable == null) {
- asVariable = visit(SharedVariable.class, relPatternNode);
- }
- qvtrAllVariables.add(asVariable);
- }
- }
- }
- //
- // Establish the TemplateVariable interrelationships
- //
- connectionHelper.connectNodes(relRootPatternClassNodes);
- //
- // Create the Relation
- //
- // Collections.sort(qvtrRelationDomains, NameUtil.NAMEABLE_COMPARATOR);
- Relation qvtrRelation = context.createRelation(UMLXUtil.getName(relDiagram), qvtrRelationDomains);
- context.install(relDiagram, qvtrRelation);
- // Collections.sort(qvtrAllVariables, NameUtil.NAMEABLE_COMPARATOR);
- Iterables.addAll(QVTrelationUtil.Internal.getOwnedVariablesList(qvtrRelation), qvtrAllVariables);
- qvtrRelation.setIsTopLevel(relDiagram.isIsTop());
- //
- // Compute derived properties
- //
- for (@NonNull RelationDomain qvtrRelationDomain : qvtrRelationDomains) {
- for (@NonNull DomainPattern qvtrDomainPattern : QVTrelationUtil.getOwnedPatterns(qvtrRelationDomain)) {
- TemplateExp rootTemplateExpression = QVTrelationUtil.getOwnedTemplateExpression(qvtrDomainPattern);
- qvtrRelationDomain.getRootVariable().add(QVTrelationUtil.getBindsTo(rootTemplateExpression));
- List<@NonNull Variable> boundVariables = new ArrayList<>();
- context.computeBoundVariables(boundVariables, rootTemplateExpression);
- List<Variable> bindsTo = qvtrDomainPattern.getBindsTo();
- Iterables.addAll(ClassUtil.nullFree(bindsTo), boundVariables);
- }
- }
- return qvtrRelation;
- }
-
- @Override
- public @Nullable RelationDomain visitRelDomainNode(@NonNull RelDomainNode relDomainNode) {
- TxTypedModelNode txTypedModelNode = UMLXUtil.getReferredTxTypedModelNode(relDomainNode);
- TypedModel qvtrTypedModel = context.getQVTrElement(TypedModel.class, txTypedModelNode);
- RelationDomain qvtrRelationDomain = context.createRelationDomain(qvtrTypedModel);
- qvtrRelationDomain.setIsCheckable(txTypedModelNode.isCheck());
- qvtrRelationDomain.setIsEnforceable(txTypedModelNode.isEnforce());
- context.install(relDomainNode, qvtrRelationDomain);
- return qvtrRelationDomain;
- }
-
- @Override
- public @Nullable Element visitRelInvocationNode(@NonNull RelInvocationNode relInvocationNode) {
- context.addReference(relInvocationNode);
- return null;
- }
-
- @Override
- public @Nullable Element visitRelPatternClassNode(@NonNull RelPatternClassNode relPatternClassNode) {
- EClassifier eClassifier = UMLXUtil.getReferredEClassifier(relPatternClassNode);
- if (eClassifier instanceof EClass) {
- org.eclipse.ocl.pivot.Class asClass = metamodelManager.getASOfEcore(org.eclipse.ocl.pivot.Class.class, eClassifier);
- assert asClass != null;
- if (relPatternClassNode.isIsMany()) {
- asClass = ((PivotMetamodelManager)metamodelManager).getCollectionType(relPatternClassNode.isIsOrdered(), relPatternClassNode.isIsUnique(), asClass,
- relPatternClassNode.isIsNullFree(), null, null);
- }
- Variable asVariable;
- Integer mostPositiveSourceIndex = getIncomingSourceIndex(relPatternClassNode);
- if (mostPositiveSourceIndex == null) {
- asVariable = context.createTemplateVariable(UMLXUtil.getName(relPatternClassNode), asClass, relPatternClassNode.isIsRequired(), null);
- }
- else if (mostPositiveSourceIndex > 0) {
- asVariable = context.createTemplateVariable(UMLXUtil.getName(relPatternClassNode), asClass, relPatternClassNode.isIsRequired(), null);
- }
- else {
- asVariable = context.createSharedVariable(relPatternClassNode.isIsAnon() ? null : UMLXUtil.getName(relPatternClassNode), asClass, relPatternClassNode.isIsRequired(), null);
- }
- context.install(relPatternClassNode, asVariable);
- return asVariable;
- }
- else {
- DataType asDataType = metamodelManager.getASOfEcore(DataType.class, eClassifier);
- assert asDataType != null;
- Variable asVariable = context.createSharedVariable(UMLXUtil.getName(relPatternClassNode), asDataType, relPatternClassNode.isIsRequired(), null);
- context.install(relPatternClassNode, asVariable);
- return asVariable;
- }
+ PatternForest patternForest = new PatternForest(context, relDiagram);
+ context.patternForests.add(patternForest);
+ return patternForest.create(); // Pass 1: create the elements
}
@Override
@@ -633,16 +145,17 @@ public class UMLX2QVTr extends QVTrelationHelper
List<@NonNull Rule> allRelationsList = new ArrayList<>();
createAll(UMLXUtil.getOwnedRelDiagrams(txDiagram), allRelationsList);
+ createAll(UMLXUtil.getOwnedTxQueryNodes(txDiagram), QVTbaseUtil.Internal.getOwnedOperationsList(qvtrRelationalTransformation));
// Collections.sort(allRelationsList, NameUtil.NAMEABLE_COMPARATOR);
Iterables.addAll(QVTrelationUtil.Internal.getOwnedRelationsList(qvtrRelationalTransformation), allRelationsList);
- QVTbaseUtil.getContextVariable(context.getStandardLibrary(), qvtrRelationalTransformation);
+ QVTbaseUtil.getContextVariable(metamodelManager.getStandardLibrary(), qvtrRelationalTransformation);
return qvtrRelationalTransformation;
}
@Override
public @Nullable Element visitTxImportNode(@NonNull TxImportNode txImportNode) {
String uri = txImportNode.getUri();
- EObject eObject = context.getEnvironmentFactory().getResourceSet().getEObject(URI.createURI(uri), true);
+ EObject eObject = metamodelManager.getEnvironmentFactory().getResourceSet().getEObject(URI.createURI(uri), true);
try {
Namespace asNamespace = metamodelManager.getASOf(Namespace.class, eObject);
if (asNamespace != null) {
@@ -687,6 +200,25 @@ public class UMLX2QVTr extends QVTrelationHelper
}
@Override
+ public @Nullable Element visitTxParameterNode(@NonNull TxParameterNode txParameterNode) {
+ org.eclipse.ocl.pivot.@NonNull Class asClass = context.getReferredType(txParameterNode);
+ FunctionParameter asFunctionParameter = context.createFunctionParameter(UMLXUtil.getName(txParameterNode), asClass, txParameterNode.isIsRequired());
+ context.install(txParameterNode, asFunctionParameter);
+ return asFunctionParameter;
+ }
+
+ @Override
+ public @Nullable Element visitTxQueryNode(@NonNull TxQueryNode txQueryNode) {
+ List<@NonNull FunctionParameter> qvtrParameters = new ArrayList<>();
+ createAll(UMLXUtil.getOwnedTxParameterNodes(txQueryNode), qvtrParameters);
+ org.eclipse.ocl.pivot.@NonNull Class asClass = context.getReferredType(txQueryNode);
+ Function asFunction = context.createFunction(UMLXUtil.getName(txQueryNode), asClass, txQueryNode.isIsRequired(), qvtrParameters);
+ context.install(txQueryNode, asFunction);
+ context.txQueryNodes.add(txQueryNode);
+ return asFunction;
+ }
+
+ @Override
public @Nullable Element visitTxTypedModelNode(@NonNull TxTypedModelNode txTypedModelNode) {
List<org.eclipse.ocl.pivot.@NonNull Package> usedPackages = new ArrayList<>();
createAll(UMLXUtil.getOwnedTxPackageNodes(txTypedModelNode), usedPackages);
@@ -711,45 +243,6 @@ public class UMLX2QVTr extends QVTrelationHelper
return null;
}
- /* @Override
- public @Nullable UMLXElement visitRelationalTransformation(@NonNull RelationalTransformation qvtrTransformation) {
- TxDiagram txDiagram = UMLXFactory.eINSTANCE.createTxDiagram();
- txDiagram.setName(qvtrTransformation.getName());
- TxTransformationNode txTransformationNode = UMLXFactory.eINSTANCE.createTxTransformationNode();
- context.putQVTr2UMLXTrace(qvtrTransformation, txTransformationNode);
- txTransformationNode.setName(qvtrTransformation.getName());
- // txTransformationNode.setOwnedContext(create(qvtrTransformation.getOwnedContext()));
- // createAll(qvtrTransformation.getOwnedOperations(), txTransformationNode.getOwnedOperations());
- createAll(QVTrelationUtil.getModelParameters(qvtrTransformation), txTransformationNode.getTxTypedModelNodes());
- createAll(QVTrelationUtil.getOwnedKey(qvtrTransformation), txTransformationNode.getTxKeyNodes());
- createAll(QVTrelationUtil.getRule(qvtrTransformation), txDiagram.getOwnedDiagrams());
- // doRules(qvtrTransformation, txTransformationNode);
- // createAll(qvtrTransformation.getOwnedComments(), txTransformationNode.getOwnedComments());
- txDiagram.getOwnedNodes().add(txTransformationNode);
- umlxModel.getOwnedDiagrams().add(txDiagram);
- return null;
- } */
-
- /* @Override
- public @Nullable UMLXElement visitTypedModel(@NonNull TypedModel qvtrTypedModel) {
- TxTypedModelNode txTypedModelNode = UMLXFactory.eINSTANCE.createTxTypedModelNode();
- context.putQVTr2UMLXTrace(qvtrTypedModel, txTypedModelNode);
- txTypedModelNode.setName(qvtrTypedModel.getName());
- for (org.eclipse.ocl.pivot.@NonNull Package usedPackage : QVTrelationUtil.getUsedPackages(qvtrTypedModel)) {
- TxPackageNode txPackageNode = UMLXFactory.eINSTANCE.createTxPackageNode();
- // context.addTrace(usedPackage, txPackageNode);
- txPackageNode.setReferredPackage(usedPackage.getEPackage());
- txTypedModelNode.getTxPackageNodes().add(txPackageNode);
- }
- return txTypedModelNode;
- } */
-
- /* @Override
- public @Nullable UMLXElement visitVariableExp(@NonNull VariableExp qvtrVariableExp) {
- RelPatternNode relPatternNode = context.getUMLXElement(RelPatternNode.class, PivotUtil.getReferredVariable(qvtrVariableExp));
- return relPatternNode;
- } */
-
@Override
public @Nullable Element visiting(@NonNull UMLXElement umlxElement) {
System.out.println("Unsupported " + umlxElement.eClass().getName() + " for " + getClass().getSimpleName());
@@ -758,85 +251,11 @@ public class UMLX2QVTr extends QVTrelationHelper
}
}
- protected static class ReferenceVisitor extends AbstractExtendingUMLXVisitor<@Nullable Object, @NonNull UMLX2QVTr>
- {
- public ReferenceVisitor(@NonNull UMLX2QVTr context) {
- super(context);
- }
-
- @Override
- public @Nullable Object visiting(@NonNull UMLXElement visitable) {
- System.out.println("Unsupported " + visitable.eClass().getName() + " for " + getClass().getSimpleName());
- return null;
- // throw new IllegalArgumentException("Unsupported " + visitable.eClass().getName() + " for " + getClass().getSimpleName());
- }
-
- @Override
- public @Nullable Object visitRelInvocationNode(@NonNull RelInvocationNode relInvocationNode) {
- List<@NonNull VariableExp> qvtrArguments = new ArrayList<>();
- for (@NonNull RelInvocationEdge relInvocationEdge : UMLXUtil.getOwnedRelInvocationEdges(relInvocationNode)) {
- // relInvocationEdge.get
- RelPatternNode referredRelPatternNode = UMLXUtil.getInvokingRelPatternNode(relInvocationEdge); //UMLXUtil.getReferredRelPatternNode(relInvocationEdge);
- Variable qvtrVariable = context.getQVTrElement(Variable.class, referredRelPatternNode);
- qvtrArguments.add(context.createVariableExp(qvtrVariable));
- }
- RelDiagram referredRelDiagram = UMLXUtil.getReferredRelDiagram(relInvocationNode);
- Relation qvtrReferredRelation = context.getQVTrElement(Relation.class, referredRelDiagram);
- RelationCallExp qvtrRelationCallExp = context.createRelationCallExp(qvtrReferredRelation, qvtrArguments);
- RelDiagram relDiagram = UMLXUtil.getOwningRelDiagram(relInvocationNode);
- Relation qvtrRelation = context.getQVTrElement(Relation.class, relDiagram);
- if (!relInvocationNode.isIsThen()) {
- context.addWhenPredicate(qvtrRelation, qvtrRelationCallExp);
- }
- else {
- context.addWherePredicate(qvtrRelation, qvtrRelationCallExp);
- }
- return qvtrRelationCallExp;
- }
-
- @Override
- public @Nullable Element visitRelPatternExpressionNode( @NonNull RelPatternExpressionNode relPatternExpressionNode) {
- StringLiteralExp stringExpression = context.getQVTrElement(StringLiteralExp.class, relPatternExpressionNode);
- String textExpression = stringExpression.getStringSymbol();
- final EObject eContainer = stringExpression.eContainer();
- // context.getEnvironmentFactory().getMetamodelManager().parseSpecification(specification);
- ParserContext parserContext = new AbstractParserContext(context.getEnvironmentFactory(), null) {
-
- @Override
- public @Nullable ScopeView computeLookup(@NonNull EObject target, @NonNull EnvironmentView environmentView, @NonNull ScopeView scopeView) {
-
- EObject pivot = eContainer;
- if ((pivot instanceof Element) && (pivot.eResource() != null) && !(pivot instanceof InvalidType)) {
- environmentView.computeLookups((Element) pivot, null); //PivotUtil.getPivot(Element.class, scopeView.getChild());
- }
- return scopeView.getParent();
- }
- };
- // if (parserContext == null) {
- // throw new ParserException(PivotMessagesInternal.UnknownContextType_ERROR_, NameUtil.qualifiedNameFor(contextElement), PivotUtilInternal.getSpecificationRole(specification));
- // }
- parserContext.setRootElement((Element) eContainer);
- try {
- ExpressionInOCL expressionInOCL = parserContext.parse(eContainer, textExpression);
- if (expressionInOCL != null) {
- OCLExpression qvtrExpression = expressionInOCL.getOwnedBody();
- EReference eContainmentFeature = stringExpression.eContainmentFeature();
- PivotUtilInternal.resetContainer(stringExpression);
- PivotUtilInternal.resetContainer(qvtrExpression);
- eContainer.eSet(eContainmentFeature, qvtrExpression);
- }
- } catch (ParserException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return null;
- }
- }
-
private final @NonNull Resource umlxResource;
private final @NonNull Resource qvtrResource;
- private final @NonNull Map<@NonNull UMLXElement, @NonNull Element> umlx2qvtr = new HashMap<>();
- private final @NonNull Set<@NonNull UMLXElement> references = new HashSet<>();
+ private final @NonNull Map<@NonNull UMLXElement, @NonNull Element> umlxElement2qvtrElement = new HashMap<>();
+ private final @NonNull List<@NonNull PatternForest> patternForests = new ArrayList<>();
+ private final @NonNull List<@NonNull TxQueryNode> txQueryNodes = new ArrayList<>();
public UMLX2QVTr(@NonNull EnvironmentFactory environmentFactory, @NonNull Resource umlxResource, @NonNull Resource qvtrResource) {
super(environmentFactory);
@@ -844,12 +263,8 @@ public class UMLX2QVTr extends QVTrelationHelper
this.qvtrResource = qvtrResource;
}
- public void addReference(@NonNull UMLXElement umlxElement) {
- references.add(umlxElement);
- }
-
protected <T extends Element> @Nullable T basicGetQVTrElement(@NonNull Class<T> qvtrClass, @NonNull UMLXElement umlxElement) {
- Element qvtrElement = umlx2qvtr.get(umlxElement);
+ Element qvtrElement = umlxElement2qvtrElement.get(umlxElement);
if (qvtrElement == null) {
return null;
}
@@ -860,27 +275,12 @@ public class UMLX2QVTr extends QVTrelationHelper
return castElement;
}
- public @Nullable EStructuralFeature getEcoreOf(@NonNull Property qvtrProperty) {
- EStructuralFeature ecoreOfPivot = environmentFactory.getMetamodelManager().getEcoreOfPivot(EStructuralFeature.class, qvtrProperty);
- return ecoreOfPivot;
- }
-
- public @NonNull EnvironmentFactory getEnvironmentFactory() {
+ protected @NonNull EnvironmentFactory getEnvironmentFactory() {
return environmentFactory;
}
- public @NonNull String getProjectName(@NonNull URI traceURI) {
- URI trimFileExtension = traceURI.trimFileExtension();
- if (trimFileExtension.isPlatform()) {
- return trimFileExtension.segment(1);
- }
- else {
- return trimFileExtension.segment(0);
- }
- }
-
protected <T extends Element> @NonNull T getQVTrElement(@NonNull Class<T> qvtrClass, @NonNull UMLXElement umlxElement) {
- Element qvtrElement = umlx2qvtr.get(umlxElement);
+ Element qvtrElement = umlxElement2qvtrElement.get(umlxElement);
if (qvtrElement == null) {
throw new IllegalArgumentException("Missing UMLX element for " + umlxElement);
}
@@ -891,8 +291,16 @@ public class UMLX2QVTr extends QVTrelationHelper
return castElement;
}
- public @NonNull StandardLibrary getStandardLibrary() {
- return environmentFactory.getStandardLibrary();
+ protected org.eclipse.ocl.pivot.@NonNull Class getReferredType(@NonNull UMLXTypedElement umlxTypedElement) {
+ PivotMetamodelManager metamodelManager = (PivotMetamodelManager) environmentFactory.getMetamodelManager();
+ EClassifier eClassifier = UMLXUtil.getReferredEClassifier(umlxTypedElement);
+ org.eclipse.ocl.pivot.Class asClass = metamodelManager.getASOfEcore(org.eclipse.ocl.pivot.Class.class, eClassifier);
+ assert asClass != null;
+ if (umlxTypedElement.isIsMany()) {
+ asClass = metamodelManager.getCollectionType(umlxTypedElement.isIsOrdered(), umlxTypedElement.isIsUnique(), asClass,
+ umlxTypedElement.isIsNullFree(), null, null);
+ }
+ return asClass;
}
/**
@@ -900,13 +308,94 @@ public class UMLX2QVTr extends QVTrelationHelper
* context.
*/
protected void install(@NonNull UMLXElement umlxElement, @NonNull Element qvtrElement) {
- Element oldQVTrElement = umlx2qvtr.put(umlxElement, qvtrElement);
+ Element oldQVTrElement = umlxElement2qvtrElement.put(umlxElement, qvtrElement);
assert oldQVTrElement == null;
for (@NonNull String comment : UMLXUtil.getComments(umlxElement)) {
qvtrElement.getOwnedComments().add(createComment(comment));
}
}
+ /**
+ * Create a new trace for the given list of generated objects for the given
+ * context.
+ *
+ protected void reinstall(@NonNull UMLXElement umlxElement, @NonNull Element qvtrElement) {
+ Element oldQVTrElement = umlx2qvtr.put(umlxElement, qvtrElement);
+ assert oldQVTrElement != null;
+ qvtrElement.getOwnedComments().addAll(oldQVTrElement.getOwnedComments());
+ } */
+
+ /* protected @Nullable ExpressionInOCL parseContextualExpressionInOCL(@NonNull EObject eContainer, @NonNull String textExpression) {
+ // context.getEnvironmentFactory().getMetamodelManager().parseSpecification(specification);
+ ParserContext parserContext = new AbstractParserContext(environmentFactory, null) {
+
+ @Override
+ public @Nullable ScopeView computeLookup(@NonNull EObject target, @NonNull EnvironmentView environmentView, @NonNull ScopeView scopeView) {
+
+ EObject pivot = eContainer;
+ if ((pivot instanceof Element) && (pivot.eResource() != null) && !(pivot instanceof InvalidType)) {
+ environmentView.computeLookups((Element) pivot, null); //PivotUtil.getPivot(Element.class, scopeView.getChild());
+ }
+ return scopeView.getParent();
+ }
+ };
+ // if (parserContext == null) {
+ // throw new ParserException(PivotMessagesInternal.UnknownContextType_ERROR_, NameUtil.qualifiedNameFor(contextElement), PivotUtilInternal.getSpecificationRole(specification));
+ // }
+ parserContext.setRootElement((Element) eContainer);
+ try {
+ return parserContext.parse(eContainer, textExpression);
+ } catch (ParserException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return null;
+ }
+ } */
+ protected @Nullable OCLExpression parseContextualExpression(@NonNull EObject eContainer, @NonNull List<String> textExpression) {
+ // context.getEnvironmentFactory().getMetamodelManager().parseSpecification(specification);
+ ParserContext parserContext = new AbstractParserContext(environmentFactory, null) {
+
+ @Override
+ public @Nullable ScopeView computeLookup(@NonNull EObject target, @NonNull EnvironmentView environmentView, @NonNull ScopeView scopeView) {
+
+ EObject pivot = eContainer;
+ if ((pivot instanceof Element) && (pivot.eResource() != null) && !(pivot instanceof InvalidType)) {
+ environmentView.computeLookups((Element) pivot, null); //PivotUtil.getPivot(Element.class, scopeView.getChild());
+ }
+ return scopeView.getParent();
+ }
+ };
+ // if (parserContext == null) {
+ // throw new ParserException(PivotMessagesInternal.UnknownContextType_ERROR_, NameUtil.qualifiedNameFor(contextElement), PivotUtilInternal.getSpecificationRole(specification));
+ // }
+ parserContext.setRootElement((Element) eContainer);
+ try {
+ StringBuilder s = new StringBuilder();
+ for (String line : textExpression) {
+ s.append(line);
+ s.append("\n");
+ }
+ ExpressionInOCL asExpressionInOCL = parserContext.parse(eContainer, s.toString());
+ OCLExpression asExpression = asExpressionInOCL.getOwnedBody();
+ assert asExpression != null;
+ PivotUtilInternal.resetContainer(asExpression);
+ return asExpression;
+ } catch (ParserException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ private void resolveTxQueryBody(@NonNull TxQueryNode txQueryNode) {
+ Function asFunction = getQVTrElement(Function.class, txQueryNode);
+ List<String> lines = txQueryNode.getInitExpressionLines();
+ if (lines.size() > 0) {
+ OCLExpression qvtrExpression = parseContextualExpression(asFunction, lines);
+ asFunction.setQueryExpression(qvtrExpression);
+ }
+ }
+
public void transform() throws CompilerChainException {
for (EObject eObject : umlxResource.getContents()) {
if (eObject instanceof UMLXModel) {
@@ -916,11 +405,11 @@ public class UMLX2QVTr extends QVTrelationHelper
qvtrResource.getContents().add(qvtrModel);
}
}
- if (!references.isEmpty()) {
- ReferenceVisitor referenceVisitor = new ReferenceVisitor(this);
- for (@NonNull UMLXElement element : references) {
- element.accept(referenceVisitor);
- }
+ for (@NonNull TxQueryNode txQueryNode : txQueryNodes) {
+ resolveTxQueryBody(txQueryNode);
+ }
+ for (@NonNull PatternForest patternForest : patternForests) {
+ patternForest.resolveExpressions(); // Pass 2: parse the OCL text
}
}
}
diff --git a/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/utilities/UMLXServices.java b/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/utilities/UMLXServices.java
index 48094736e..1b93ca64d 100644
--- a/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/utilities/UMLXServices.java
+++ b/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/utilities/UMLXServices.java
@@ -16,18 +16,25 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import org.eclipse.emf.common.util.EMap;
+import org.eclipse.emf.ecore.EAnnotation;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
-import org.eclipse.emf.ecore.ETypedElement;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.ecore.xmi.impl.EMOFExtendedMetaData;
import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.ocl.pivot.internal.ecore.es2as.Ecore2ASReferenceSwitch;
+import org.eclipse.ocl.pivot.internal.utilities.PivotConstantsInternal;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.ocl.pivot.utilities.LabelUtil;
import org.eclipse.ocl.pivot.utilities.TreeIterable;
+import org.eclipse.ocl.pivot.utilities.ValueUtil;
+import org.eclipse.ocl.pivot.values.IntegerValue;
+import org.eclipse.ocl.pivot.values.UnlimitedNaturalValue;
import org.eclipse.qvtd.umlx.RelDiagram;
import org.eclipse.qvtd.umlx.RelDomainNode;
import org.eclipse.qvtd.umlx.RelInvocationEdge;
@@ -43,6 +50,7 @@ import org.eclipse.qvtd.umlx.TxPackageNode;
import org.eclipse.qvtd.umlx.TxPartNode;
import org.eclipse.qvtd.umlx.TxTypedModelNode;
import org.eclipse.qvtd.umlx.UMLXNamedElement;
+import org.eclipse.qvtd.umlx.UMLXTypedElement;
/**
* Class owning methods used for service: umlx. The service methods
@@ -52,13 +60,11 @@ public class UMLXServices
{
public UMLXServices() {}
- protected void appendMultiplicity(@NonNull StringBuilder s, @NonNull ETypedElement eTypedElement) {
- if (!eTypedElement.isMany()) {
- s.append(eTypedElement.isRequired() ? "[1]" : "[?]");
+ protected void appendMultiplicity(@NonNull StringBuilder s, int lower, int upper) {
+ if (upper == 1) {
+ s.append(lower == 1 ? "[1]" : "[?]");
}
else {
- int lower = eTypedElement.getLowerBound();
- int upper = eTypedElement.getUpperBound();
if (upper < 0) {
if (lower == 0) {
s.append("[*]");
@@ -79,6 +85,27 @@ public class UMLXServices
}
}
+ protected void appendTypedElement(StringBuilder s, @NonNull UMLXTypedElement umlxTypedElement) {
+ s.append(String.valueOf(umlxTypedElement.getName()));
+ s.append(" : ");
+ if (umlxTypedElement.isIsMany()) {
+ if (umlxTypedElement.isIsUnique()) {
+ s.append(umlxTypedElement.isIsOrdered() ? "OrderedSet" : "Set");
+ }
+ else {
+ s.append(umlxTypedElement.isIsOrdered() ? "Sequence" : "Bag");
+ }
+ s.append("(");
+ }
+ EClassifier eClassifier = umlxTypedElement.getReferredEClassifier();
+ if (eClassifier != null) {
+ s.append(eClassifier.eIsProxy() ? EcoreUtil.getURI(eClassifier) : String.valueOf(eClassifier.getName()));
+ }
+ if (umlxTypedElement.isIsMany()) {
+ s.append(")");
+ }
+ }
+
protected @NonNull String defaultName(@NonNull EObject context, @NonNull Class<? extends UMLXNamedElement> newClass, @NonNull String prefix) {
Set<String> allNames = new HashSet<>();
Resource eResource = context.eResource();
@@ -96,6 +123,110 @@ public class UMLXServices
}
}
+ private int getEOppositeLower(@NonNull EReference eReference) {
+ EReference eOpposite = eReference.getEOpposite();
+ if (eOpposite != null) {
+ return eOpposite.getLowerBound();
+ }
+ EAnnotation oppositeRole = eReference.getEAnnotation(EMOFExtendedMetaData.EMOF_PACKAGE_NS_URI_2_0);
+ if (oppositeRole != null) {
+ EMap<String, String> details = oppositeRole.getDetails();
+ String oppositeName = details.get(Ecore2ASReferenceSwitch.PROPERTY_OPPOSITE_ROLE_NAME_KEY);
+ if (oppositeName != null) {
+ String lowerValue = details.get(Ecore2ASReferenceSwitch.PROPERTY_OPPOSITE_ROLE_LOWER_KEY);
+ IntegerValue one = ValueUtil.ONE_VALUE;
+ IntegerValue lower = lowerValue != null ? ValueUtil.integerValueOf(lowerValue) : one;
+ if (lower.isInvalid()) {
+ // logger.error("Invalid " + Ecore2ASReferenceSwitch.PROPERTY_OPPOSITE_ROLE_LOWER_KEY + " " + lower);
+ lower = one;
+ }
+ return lower.intValue();
+ }
+ }
+ else {
+ oppositeRole = eReference.getEAnnotation(EMOFExtendedMetaData.EMOF_PROPERTY_OPPOSITE_ROLE_NAME_ANNOTATION_SOURCE);
+ if (oppositeRole != null) {
+ EMap<String, String> details = oppositeRole.getDetails();
+ String oppositeName = details.get(EMOFExtendedMetaData.EMOF_COMMENT_BODY);
+ if (oppositeName != null) {
+ String lowerValue = details.get("lower");
+ IntegerValue lower = lowerValue != null ? ValueUtil.integerValueOf(lowerValue) : PivotConstantsInternal.ANNOTATED_IMPLICIT_OPPOSITE_LOWER_VALUE;
+ if (lower.isInvalid()) {
+ // logger.error("Invalid " + Ecore2ASReferenceSwitch.PROPERTY_OPPOSITE_ROLE_LOWER_KEY + " " + lower);
+ lower = PivotConstantsInternal.ANNOTATED_IMPLICIT_OPPOSITE_LOWER_VALUE;
+ }
+ return lower.intValue();
+ }
+ }
+ }
+ return 0;
+ }
+
+ private String getEOppositeName(@NonNull EReference eReference) {
+ EReference eOpposite = eReference.getEOpposite();
+ if (eOpposite != null) {
+ return eOpposite.getName();
+ }
+ EAnnotation oppositeRole = eReference.getEAnnotation(EMOFExtendedMetaData.EMOF_PACKAGE_NS_URI_2_0);
+ if (oppositeRole != null) {
+ EMap<String, String> details = oppositeRole.getDetails();
+ String oppositeName = details.get(Ecore2ASReferenceSwitch.PROPERTY_OPPOSITE_ROLE_NAME_KEY);
+ if (oppositeName != null) {
+ return oppositeName;
+ }
+ }
+ else {
+ oppositeRole = eReference.getEAnnotation(EMOFExtendedMetaData.EMOF_PROPERTY_OPPOSITE_ROLE_NAME_ANNOTATION_SOURCE);
+ if (oppositeRole != null) {
+ EMap<String, String> details = oppositeRole.getDetails();
+ String oppositeName = details.get(EMOFExtendedMetaData.EMOF_COMMENT_BODY);
+ if (oppositeName != null) {
+ return oppositeName;
+ }
+ }
+ }
+ return "«inferred»";
+ }
+
+ private int getEOppositeUpper(@NonNull EReference eReference) {
+ EReference eOpposite = eReference.getEOpposite();
+ if (eOpposite != null) {
+ return eOpposite.getUpperBound();
+ }
+ EAnnotation oppositeRole = eReference.getEAnnotation(EMOFExtendedMetaData.EMOF_PACKAGE_NS_URI_2_0);
+ if (oppositeRole != null) {
+ EMap<String, String> details = oppositeRole.getDetails();
+ String oppositeName = details.get(Ecore2ASReferenceSwitch.PROPERTY_OPPOSITE_ROLE_NAME_KEY);
+ if (oppositeName != null) {
+ String upperValue = details.get(Ecore2ASReferenceSwitch.PROPERTY_OPPOSITE_ROLE_UPPER_KEY);
+ UnlimitedNaturalValue unlimitedOne = ValueUtil.UNLIMITED_ONE_VALUE;
+ UnlimitedNaturalValue upper = upperValue != null ? ValueUtil.unlimitedNaturalValueOf(upperValue) : unlimitedOne;
+ if (upper.isInvalid()) {
+ // logger.error("Invalid " + Ecore2ASReferenceSwitch.PROPERTY_OPPOSITE_ROLE_UPPER_KEY + " " + upper);
+ upper = unlimitedOne;
+ }
+ return upper.intValue();
+ }
+ }
+ else {
+ oppositeRole = eReference.getEAnnotation(EMOFExtendedMetaData.EMOF_PROPERTY_OPPOSITE_ROLE_NAME_ANNOTATION_SOURCE);
+ if (oppositeRole != null) {
+ EMap<String, String> details = oppositeRole.getDetails();
+ String oppositeName = details.get(EMOFExtendedMetaData.EMOF_COMMENT_BODY);
+ if (oppositeName != null) {
+ String upperValue = details.get("upper");
+ UnlimitedNaturalValue upper = upperValue != null ? ValueUtil.unlimitedNaturalValueOf(upperValue) : PivotConstantsInternal.ANNOTATED_IMPLICIT_OPPOSITE_UPPER_VALUE;
+ if (upper.isInvalid()) {
+ // logger.error("Invalid " + Ecore2ASReferenceSwitch.PROPERTY_OPPOSITE_ROLE_UPPER_KEY + " " + upper);
+ upper = PivotConstantsInternal.ANNOTATED_IMPLICIT_OPPOSITE_UPPER_VALUE;
+ }
+ return upper.intValue();
+ }
+ }
+ }
+ return 0;
+ }
+
public int umlxBorderSize(EObject context) {
return 4;
}
@@ -178,31 +309,30 @@ public class UMLXServices
}
}
else if (context instanceof RelPatternClassNode) {
- RelPatternClassNode relPatternClassNode = (RelPatternClassNode)context;
StringBuilder s = new StringBuilder();
- s.append(String.valueOf(relPatternClassNode.getName()));
- s.append(" : ");
- if (relPatternClassNode.isIsMany()) {
- if (relPatternClassNode.isIsUnique()) {
- s.append(relPatternClassNode.isIsOrdered() ? "OrderedSet" : "Set");
- }
- else {
- s.append(relPatternClassNode.isIsOrdered() ? "Sequence" : "Bag");
+ RelPatternClassNode relPatternClassNode = (RelPatternClassNode)context;
+ appendTypedElement(s, relPatternClassNode);
+ List<String> initExpressionLines = relPatternClassNode.getInitExpressionLines();
+ if (initExpressionLines.size() > 0) {
+ s.append(" :=");
+ for (String line : initExpressionLines) {
+ s.append("\n");
+ s.append(line);
}
- s.append("(");
- }
- EClassifier eClassifier = relPatternClassNode.getReferredEClassifier();
- if (eClassifier != null) {
- s.append(eClassifier.eIsProxy() ? EcoreUtil.getURI(eClassifier) : String.valueOf(eClassifier.getName()));
- }
- if (relPatternClassNode.isIsMany()) {
- s.append(")");
}
return s.toString();
}
else if (context instanceof RelPatternExpressionNode) {
- String expression = ((RelPatternExpressionNode)context).getExpression();
- return expression != null ? expression : "«null-expression»";
+ StringBuilder s = new StringBuilder();
+ boolean firstLine = true;
+ for (String line : ((RelPatternExpressionNode)context).getInitExpressionLines()) {
+ if (!firstLine) {
+ s.append("\n");
+ s.append(line);
+ firstLine = false;
+ }
+ }
+ return s.toString();
}
else if (context instanceof TxImportNode) {
return String.valueOf(((TxImportNode)context).getName());
@@ -231,6 +361,11 @@ public class UMLXServices
else if (context instanceof TxTypedModelNode) {
return String.valueOf(((TxTypedModelNode)context).getName());
}
+ else if (context instanceof UMLXTypedElement) {
+ StringBuilder s = new StringBuilder();
+ appendTypedElement(s, (UMLXTypedElement)context);
+ return s.toString();
+ }
return "«umlxLabel - " + context.getClass().getName() + " - " + context.eClass().getName() + "»";
}
@@ -241,14 +376,11 @@ public class UMLXServices
if (context instanceof RelPatternEdge) {
EStructuralFeature eStructuralFeature = ((RelPatternEdge)context).getReferredEStructuralFeature();
if (eStructuralFeature instanceof EReference) {
- EReference eOpposite = ((EReference)eStructuralFeature).getEOpposite();
- if (eOpposite == null) {
- return "«inferred»";
- }
+ EReference eReference = (EReference)eStructuralFeature;
StringBuilder s = new StringBuilder();
- s.append(String.valueOf(eOpposite.getName()));
+ s.append(getEOppositeName(eReference));
s.append(" ");
- appendMultiplicity(s, eOpposite);
+ appendMultiplicity(s, getEOppositeLower(eReference), getEOppositeUpper(eReference));
return s.toString();
}
}
@@ -281,7 +413,7 @@ public class UMLXServices
StringBuilder s = new StringBuilder();
s.append(String.valueOf(eStructuralFeature.getName()));
s.append(" ");
- appendMultiplicity(s, eStructuralFeature);
+ appendMultiplicity(s, eStructuralFeature.getLowerBound(), eStructuralFeature.getUpperBound());
return s.toString();
}
}
diff --git a/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/utilities/UMLXStandaloneSetup.java b/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/utilities/UMLXStandaloneSetup.java
index 17c898712..85cabc702 100644
--- a/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/utilities/UMLXStandaloneSetup.java
+++ b/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/utilities/UMLXStandaloneSetup.java
@@ -21,6 +21,10 @@ import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
import org.eclipse.ocl.pivot.labels.ILabelGenerator;
import org.eclipse.qvtd.umlx.UMLXPackage;
import org.eclipse.qvtd.umlx.labels.RelPatternEdgeLabelGenerator;
+import org.eclipse.qvtd.umlx.labels.UMLXModelLabelGenerator;
+import org.eclipse.qvtd.umlx.labels.UMLXNamedElementLabelGenerator;
+import org.eclipse.qvtd.umlx.labels.RelDomainNodeLabelGenerator;
+import org.eclipse.qvtd.umlx.labels.RelPatternClassNodeLabelGenerator;
import org.eclipse.qvtd.umlx.resource.UMLXResourceFactoryImpl;
import org.eclipse.qvtd.umlx.util.UMLXValidator;
@@ -50,7 +54,11 @@ public class UMLXStandaloneSetup
}
EPackage.Registry.INSTANCE.put(UMLXPackage.eNS_URI, UMLXPackage.eINSTANCE);
EValidator.Registry.INSTANCE.put(UMLXPackage.eINSTANCE, UMLXValidator.INSTANCE);
+ RelDomainNodeLabelGenerator.initialize(ILabelGenerator.Registry.INSTANCE);
+ RelPatternClassNodeLabelGenerator.initialize(ILabelGenerator.Registry.INSTANCE);
RelPatternEdgeLabelGenerator.initialize(ILabelGenerator.Registry.INSTANCE);
+ UMLXModelLabelGenerator.initialize(ILabelGenerator.Registry.INSTANCE);
+ UMLXNamedElementLabelGenerator.initialize(ILabelGenerator.Registry.INSTANCE);
}
/**
diff --git a/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/utilities/UMLXToStringVisitor.java b/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/utilities/UMLXToStringVisitor.java
index 83a6ee72f..470c13c53 100644
--- a/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/utilities/UMLXToStringVisitor.java
+++ b/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/utilities/UMLXToStringVisitor.java
@@ -10,6 +10,8 @@
*******************************************************************************/
package org.eclipse.qvtd.umlx.utilities;
+import java.util.List;
+
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EStructuralFeature;
@@ -17,6 +19,7 @@ import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.utilities.LabelUtil;
import org.eclipse.qvtd.umlx.RelPatternExpressionNode;
+import org.eclipse.qvtd.umlx.TxImportNode;
import org.eclipse.qvtd.umlx.RelDiagram;
import org.eclipse.qvtd.umlx.RelDomainNode;
import org.eclipse.qvtd.umlx.RelInvocationEdge;
@@ -26,10 +29,12 @@ import org.eclipse.qvtd.umlx.RelPatternClassNode;
import org.eclipse.qvtd.umlx.TxKeyNode;
import org.eclipse.qvtd.umlx.TxPackageNode;
import org.eclipse.qvtd.umlx.TxPartNode;
+import org.eclipse.qvtd.umlx.TxQueryNode;
import org.eclipse.qvtd.umlx.TxTypedModelNode;
import org.eclipse.qvtd.umlx.UMLXElement;
import org.eclipse.qvtd.umlx.UMLXModel;
import org.eclipse.qvtd.umlx.UMLXNamedElement;
+import org.eclipse.qvtd.umlx.UMLXTypedElement;
import org.eclipse.qvtd.umlx.util.AbstractExtendingUMLXVisitor;
public class UMLXToStringVisitor extends AbstractExtendingUMLXVisitor<@Nullable Object, @NonNull StringBuilder>
@@ -79,25 +84,19 @@ public class UMLXToStringVisitor extends AbstractExtendingUMLXVisitor<@Nullable
@Override
public @Nullable Object visitRelPatternClassNode(@NonNull RelPatternClassNode relPatternClassNode) {
- EClassifier eClassifier = relPatternClassNode.getReferredEClassifier();
- append(relPatternClassNode.getName());
- append(" : ");
- if (relPatternClassNode.isIsMany()) {
- if (relPatternClassNode.isIsUnique()) {
- append(relPatternClassNode.isIsOrdered() ? "OrderedSet" : "Set");
- }
- else {
- append(relPatternClassNode.isIsOrdered() ? "Sequence" : "Bag");
+ visitUMLXTypedElement(relPatternClassNode);
+ List<String> lines = relPatternClassNode.getInitExpressionLines();
+ if (lines.size() > 0) {
+ append(" = ");
+ boolean firstLine = true;
+ for (String line : lines) {
+ if (!firstLine) {
+ append("\n");
+ }
+ append(line);
+ firstLine = false;
}
- append("(");
- append(LabelUtil.getLabel(eClassifier));
- append(relPatternClassNode.isIsNullFree() ? "[*|1]" : "[*|?]");
- append(")");
}
- else {
- append(LabelUtil.getLabel(eClassifier));
- }
- append(relPatternClassNode.isIsRequired() ? "[1]" : "[?]");
return null;
}
@@ -115,8 +114,23 @@ public class UMLXToStringVisitor extends AbstractExtendingUMLXVisitor<@Nullable
@Override
public @Nullable Object visitRelPatternExpressionNode(@NonNull RelPatternExpressionNode relPatternExpressionNode) {
- String expression = relPatternExpressionNode.getExpression();
- append(expression);
+ List<String> lines = relPatternExpressionNode.getInitExpressionLines();
+ if (lines.size() > 0) {
+ boolean firstLine = true;
+ for (String line : lines) {
+ if (!firstLine) {
+ append("\n");
+ }
+ append(line);
+ firstLine = false;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public @Nullable Object visitTxImportNode(@NonNull TxImportNode txImportNode) {
+ append(txImportNode.getName());
return null;
}
@@ -145,6 +159,31 @@ public class UMLXToStringVisitor extends AbstractExtendingUMLXVisitor<@Nullable
}
@Override
+ public @Nullable Object visitTxQueryNode(@NonNull TxQueryNode txQueryNode) {
+ visitUMLXTypedElement(txQueryNode);
+ // fixme parameters
+ List<String> lines = txQueryNode.getInitExpressionLines();
+ if (lines.size() > 0) {
+ append(" = ");
+ boolean firstLine = true;
+ for (String line : lines) {
+ if (!firstLine) {
+ append("\n");
+ }
+ append(line);
+ firstLine = false;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public @Nullable Object visitTxTypedModelNode(@NonNull TxTypedModelNode txTypedModelNode) {
+ append(txTypedModelNode.getName());
+ return null;
+ }
+
+ @Override
public @Nullable Object visitUMLXModel(@NonNull UMLXModel umlxModel) {
return "UMLXModel";
}
@@ -156,6 +195,30 @@ public class UMLXToStringVisitor extends AbstractExtendingUMLXVisitor<@Nullable
}
@Override
+ public @Nullable Object visitUMLXTypedElement(@NonNull UMLXTypedElement umlxTypedElement) {
+ EClassifier eClassifier = umlxTypedElement.getReferredEClassifier();
+ append(umlxTypedElement.getName());
+ append(" : ");
+ if (umlxTypedElement.isIsMany()) {
+ if (umlxTypedElement.isIsUnique()) {
+ append(umlxTypedElement.isIsOrdered() ? "OrderedSet" : "Set");
+ }
+ else {
+ append(umlxTypedElement.isIsOrdered() ? "Sequence" : "Bag");
+ }
+ append("(");
+ append(LabelUtil.getLabel(eClassifier));
+ append(umlxTypedElement.isIsNullFree() ? "[*|1]" : "[*|?]");
+ append(")");
+ }
+ else {
+ append(LabelUtil.getLabel(eClassifier));
+ }
+ append(umlxTypedElement.isIsRequired() ? "[1]" : "[?]");
+ return null;
+ }
+
+ @Override
public @Nullable Object visiting(@NonNull UMLXElement umlxElement) {
append("Unsupported " + getClass().getSimpleName() + " for " + umlxElement.eClass().getName());
return null;
diff --git a/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/utilities/UMLXUtil.java b/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/utilities/UMLXUtil.java
index ce634b591..11251f006 100644
--- a/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/utilities/UMLXUtil.java
+++ b/plugins/org.eclipse.qvtd.umlx/src/org/eclipse/qvtd/umlx/utilities/UMLXUtil.java
@@ -34,11 +34,14 @@ import org.eclipse.qvtd.umlx.TxDiagram;
import org.eclipse.qvtd.umlx.TxImportNode;
import org.eclipse.qvtd.umlx.TxKeyNode;
import org.eclipse.qvtd.umlx.TxPackageNode;
+import org.eclipse.qvtd.umlx.TxParameterNode;
import org.eclipse.qvtd.umlx.TxPartNode;
+import org.eclipse.qvtd.umlx.TxQueryNode;
import org.eclipse.qvtd.umlx.TxTypedModelNode;
import org.eclipse.qvtd.umlx.UMLXElement;
import org.eclipse.qvtd.umlx.UMLXModel;
import org.eclipse.qvtd.umlx.UMLXNamedElement;
+import org.eclipse.qvtd.umlx.UMLXTypedElement;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
@@ -51,6 +54,10 @@ public class UMLXUtil
public static @NonNull List<@NonNull RelPatternEdge> getIncomingList(@NonNull RelPatternNode relNode) {
return ClassUtil.nullFree(relNode.getIncoming());
}
+
+ public static @NonNull List<@NonNull RelPatternNode> getOwnedRelPatternNodesList(@NonNull RelDomainNode relDomainNode) {
+ return ClassUtil.nullFree(relDomainNode.getOwnedRelPatternNodes());
+ }
}
public static final class IsRootPredicate implements Predicate<@NonNull RelPatternClassNode>
@@ -93,18 +100,14 @@ public class UMLXUtil
return ClassUtil.nullFree(umlxElement.getComments());
}
- public static @NonNull String getExpression(@NonNull RelPatternExpressionNode relPatternExpressionNode) {
- return ClassUtil.nonNullState(relPatternExpressionNode.getExpression());
- }
-
- // public static @NonNull RelDiagram getDiagram(@NonNull RelPatternNode relNode) {
- // return ClassUtil.nonNullState(relNode.getDiagram());
- // }
-
public static @NonNull Iterable<@NonNull RelPatternEdge> getIncoming(@NonNull RelPatternNode relNode) {
return ClassUtil.nullFree(relNode.getIncoming());
}
+ public static @NonNull List<@NonNull String> getInitExpressionLines(@NonNull RelPatternExpressionNode relPatternExpressionNode) {
+ return ClassUtil.nullFree(relPatternExpressionNode.getInitExpressionLines());
+ }
+
public static @NonNull RelPatternNode getInvokingRelPatternNode(@NonNull RelInvocationEdge relInvocationEdge) {
return ClassUtil.nonNullState(relInvocationEdge.getInvokingRelPatternNode());
}
@@ -157,10 +160,18 @@ public class UMLXUtil
return ClassUtil.nullFree(txTypedModelNode.getOwnedTxPackageNodes());
}
+ public static @NonNull Iterable<@NonNull TxParameterNode> getOwnedTxParameterNodes(@NonNull TxQueryNode txTypedModelNode) {
+ return ClassUtil.nullFree(txTypedModelNode.getOwnedTxParameterNodes());
+ }
+
public static @NonNull Iterable<@NonNull TxPartNode> getOwnedTxPartNodes(@NonNull TxKeyNode txKeyNode) {
return ClassUtil.nullFree(txKeyNode.getOwnedTxPartNodes());
}
+ public static @NonNull Iterable<@NonNull TxQueryNode> getOwnedTxQueryNodes(@NonNull TxDiagram txDiagram) {
+ return ClassUtil.nullFree(txDiagram.getOwnedTxQueryNodes());
+ }
+
public static @NonNull Iterable<@NonNull TxTypedModelNode> getOwnedTxTypedModelNodes(@NonNull TxDiagram txDiagram) {
return ClassUtil.nullFree(txDiagram.getOwnedTxTypedModelNodes());
}
@@ -169,12 +180,16 @@ public class UMLXUtil
return ClassUtil.nonNullState(relInvocationNode.getOwningRelDiagram());
}
+ public static @NonNull RelDomainNode getOwningRelDomainNode(@NonNull RelPatternNode relPatternNode) {
+ return ClassUtil.nonNullState(relPatternNode.getOwningRelDomainNode());
+ }
+
public static @NonNull EClass getReferredEClass(@NonNull TxKeyNode txKeyNode) {
return ClassUtil.nonNullState(txKeyNode.getReferredEClass());
}
- public static @NonNull EClassifier getReferredEClassifier(@NonNull RelPatternClassNode relPatternNode) {
- return ClassUtil.nonNullState(relPatternNode.getReferredEClassifier());
+ public static @NonNull EClassifier getReferredEClassifier(@NonNull UMLXTypedElement umlxTypedElement) {
+ return ClassUtil.nonNullState(umlxTypedElement.getReferredEClassifier());
}
public static @NonNull EPackage getReferredEPackage(@NonNull TxPackageNode txPackageNode) {
diff --git a/tests/org.eclipse.qvtd.all.tests/src/org/eclipse/qvtd/all/tests/AllQVTdTests.java b/tests/org.eclipse.qvtd.all.tests/src/org/eclipse/qvtd/all/tests/AllQVTdTests.java
index 96319c47d..ecd57f828 100644
--- a/tests/org.eclipse.qvtd.all.tests/src/org/eclipse/qvtd/all/tests/AllQVTdTests.java
+++ b/tests/org.eclipse.qvtd.all.tests/src/org/eclipse/qvtd/all/tests/AllQVTdTests.java
@@ -21,7 +21,7 @@ import org.eclipse.qvtd.doc.bigmde2016.tests.qvtc.BigMDE2016_QVTc_AutomatedTests
import org.eclipse.qvtd.doc.exe2016.tests.qvtc.EXE2016_QVTc_AutomatedTests;
import org.eclipse.qvtd.doc.exe2016.tests.qvtr.EXE2016_QVTr_AutomatedTests;
import org.eclipse.qvtd.doc.minioclcs.xtext.tests.MiniOCLCSParsingTest;
-import org.eclipse.qvtd.umlx.tests.UMLXTests;
+import org.eclipse.qvtd.umlx.tests.AllUMLXTests;
import org.eclipse.qvtd.xtext.qvtbase.tests.QVTbaseLibraryTests;
import org.eclipse.qvtd.xtext.qvtcore.tests.AllQVTcoreTests;
import org.eclipse.qvtd.xtext.qvtimperative.tests.AllQVTimperativeTests;
@@ -61,7 +61,7 @@ public class AllQVTdTests extends TestCase
if (!EMFPlugin.IS_ECLIPSE_RUNNING) { // FIXME should work as plugin test too
result.addTestSuite(OCL2QVTiTestCases.class);
}
- result.addTestSuite(UMLXTests.class);
+ result.addTest(AllUMLXTests.suite());
result.addTestSuite(BigMDE2016_QVTc_AutomatedTests.class); // NB this is very slow since we are -ea
result.addTestSuite(EXE2016_QVTc_AutomatedTests.class); // NB this is very slow since we are -ea
result.addTestSuite(EXE2016_QVTr_AutomatedTests.class); // NB this is very slow since we are -ea
diff --git a/tests/org.eclipse.qvtd.umlx.tests/META-INF/MANIFEST.MF b/tests/org.eclipse.qvtd.umlx.tests/META-INF/MANIFEST.MF
index 8a148956d..308289feb 100644
--- a/tests/org.eclipse.qvtd.umlx.tests/META-INF/MANIFEST.MF
+++ b/tests/org.eclipse.qvtd.umlx.tests/META-INF/MANIFEST.MF
@@ -8,6 +8,7 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Require-Bundle: org.eclipse.qvtd.xtext.qvtbase.tests,
org.eclipse.qvtd.xtext.qvtrelation.tests,
org.eclipse.qvtd.compiler,
- org.eclipse.qvtd.umlx
+ org.eclipse.qvtd.umlx,
+ com.google.guava
Bundle-Localization: plugin
Export-Package: org.eclipse.qvtd.umlx.tests
diff --git a/tests/org.eclipse.qvtd.umlx.tests/src-gen/.gitignore b/tests/org.eclipse.qvtd.umlx.tests/src-gen/.gitignore
new file mode 100644
index 000000000..cf1db2eed
--- /dev/null
+++ b/tests/org.eclipse.qvtd.umlx.tests/src-gen/.gitignore
@@ -0,0 +1 @@
+/org/
diff --git a/tests/org.eclipse.qvtd.umlx.tests/src/org/eclipse/qvtd/umlx/tests/AllUMLXTests.java b/tests/org.eclipse.qvtd.umlx.tests/src/org/eclipse/qvtd/umlx/tests/AllUMLXTests.java
new file mode 100644
index 000000000..9281302ef
--- /dev/null
+++ b/tests/org.eclipse.qvtd.umlx.tests/src/org/eclipse/qvtd/umlx/tests/AllUMLXTests.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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.umlx.tests;
+
+import java.util.Arrays;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Tests for the UMLX support.
+ */
+public class AllUMLXTests extends TestCase
+{
+ public AllUMLXTests() {
+ super("");
+ }
+
+ public static Test suite() {
+ TestSuite result = new TestSuite("All UMLX Tests");
+ result.addTestSuite(UMLXSerializeTests.class);
+ return result;
+ }
+
+ public Object run(Object args)
+ throws Exception {
+
+ TestRunner.run(suite());
+ return Arrays
+ .asList(new String[] {"Please see raw test suite output for details."});
+ }
+}
diff --git a/tests/org.eclipse.qvtd.umlx.tests/src/org/eclipse/qvtd/umlx/tests/UMLXTests.java b/tests/org.eclipse.qvtd.umlx.tests/src/org/eclipse/qvtd/umlx/tests/UMLXSerializeTests.java
index 79991c65a..36103eb6f 100644
--- a/tests/org.eclipse.qvtd.umlx.tests/src/org/eclipse/qvtd/umlx/tests/UMLXTests.java
+++ b/tests/org.eclipse.qvtd.umlx.tests/src/org/eclipse/qvtd/umlx/tests/UMLXSerializeTests.java
@@ -10,14 +10,39 @@
*******************************************************************************/
package org.eclipse.qvtd.umlx.tests;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
import org.eclipse.emf.common.EMFPlugin;
+import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.ocl.pivot.Element;
import org.eclipse.ocl.pivot.Model;
+import org.eclipse.ocl.pivot.PivotPackage;
+import org.eclipse.ocl.pivot.Property;
+import org.eclipse.ocl.pivot.VariableDeclaration;
+import org.eclipse.ocl.pivot.VariableExp;
import org.eclipse.ocl.pivot.utilities.OCL;
import org.eclipse.ocl.pivot.utilities.PivotUtil;
+import org.eclipse.ocl.pivot.utilities.TreeIterable;
import org.eclipse.ocl.xtext.base.services.BaseLinkingService;
+import org.eclipse.qvtd.pivot.qvtbase.utilities.QVTbaseUtil;
+import org.eclipse.qvtd.pivot.qvtrelation.DomainPattern;
+import org.eclipse.qvtd.pivot.qvtrelation.QVTrelationFactory;
+import org.eclipse.qvtd.pivot.qvtrelation.Relation;
+import org.eclipse.qvtd.pivot.qvtrelation.TemplateVariable;
+import org.eclipse.qvtd.pivot.qvtrelation.utilities.QVTrelation;
+import org.eclipse.qvtd.pivot.qvttemplate.CollectionTemplateExp;
+import org.eclipse.qvtd.pivot.qvttemplate.ObjectTemplateExp;
+import org.eclipse.qvtd.pivot.qvttemplate.PropertyTemplateItem;
+import org.eclipse.qvtd.pivot.qvttemplate.TemplateExp;
import org.eclipse.qvtd.umlx.qvtr2umlx.QVTr2UMLX;
import org.eclipse.qvtd.umlx.umlx2qvtr.UMLX2QVTr;
import org.eclipse.qvtd.umlx.utilities.UMLXStandaloneSetup;
@@ -25,10 +50,12 @@ import org.eclipse.qvtd.xtext.qvtbase.tests.LoadTestCase;
import org.eclipse.qvtd.xtext.qvtbase.tests.utilities.TestsXMLUtil;
import org.eclipse.qvtd.xtext.qvtrelation.tests.QVTrTestUtil;
+import com.google.common.collect.Lists;
+
/**
* Tests that load a model and verify that there are no unresolved proxies as a result.
*/
-public class UMLXTests extends LoadTestCase
+public class UMLXSerializeTests extends LoadTestCase
{
/* protected void doLoad_QVTr(URI inputURI, URI pivotURI) throws IOException {
OCL ocl = OCL.newInstance(getProjectMap());
@@ -49,7 +76,7 @@ public class UMLXTests extends LoadTestCase
ocl.dispose();
}
- protected void doRoundTripTest(@NonNull URI inputURI1, @NonNull URI pivotURI1, @NonNull URI umlxURI, @NonNull URI pivotURI2) throws Exception {
+ protected void doRoundTripTest(@NonNull URI inputURI1, @NonNull URI pivotURI1, @NonNull URI umlxURI, @NonNull URI pivotURI2, boolean skipCompare) throws Exception {
OCL ocl1 = OCL.newInstance(getProjectMap());
Resource qvtrResource1 = doLoad_Concrete(ocl1, inputURI1, pivotURI1, null);
Resource umlxResource1 = qvtrResource1.getResourceSet().createResource(umlxURI);
@@ -59,7 +86,7 @@ public class UMLXTests extends LoadTestCase
//
assertNoValidationErrors(umlxURI.toString(), umlxResource1);
//
- OCL ocl2 = OCL.newInstance(getProjectMap());
+ QVTrelation ocl2 = QVTrelation.newInstance(getProjectMap());
Resource umlxResource2 = ocl2.getResourceSet().getResource(umlxURI, true);
Resource qvtrResource2 = ocl2.getMetamodelManager().getASResourceSet().createResource(pivotURI2);
UMLX2QVTr umlx2qvtr = new UMLX2QVTr(ocl2.getEnvironmentFactory(), umlxResource2, qvtrResource2);
@@ -70,11 +97,135 @@ public class UMLXTests extends LoadTestCase
Model asModel2 = PivotUtil.getModel(qvtrResource2);
asModel2.setName(asModel1.getName());
asModel2.setExternalURI(asModel1.getExternalURI());
- assertSameModel(qvtrResource1, qvtrResource2);
+ TestsXMLUtil.resetTransients(qvtrResource1);
+ TestsXMLUtil.resetTransients(qvtrResource2);
+ normalize(qvtrResource1);
+ normalize(qvtrResource2);
+ if (!skipCompare) { // FIXME BUG 511230
+ assertSameModel(qvtrResource1, qvtrResource2);
+ }
ocl1.dispose();
ocl2.dispose();
}
+ private void normalize(@NonNull Resource qvtrResource) {
+ for (TreeIterator<EObject> tit = qvtrResource.getAllContents(); tit.hasNext(); ) {
+ EObject eObject = tit.next();
+ if (eObject instanceof Relation) {
+ normalizeRelation((Relation)eObject);
+ tit.prune();
+ }
+ }
+ }
+
+ /**
+ * For non-composed leaf template elements there is a free choice to use a shared or template variable. Since there may be multiple
+ * candidate sites for the template variable, normalize by using a shared variable.
+ */
+ private void normalizeRelation(@NonNull Relation asRelation) {
+ //
+ // Find all references to all variables within the Relation
+ //
+ Map<@NonNull VariableDeclaration, @NonNull List<@NonNull Element>> variable2reference = new HashMap<>();
+ for (@NonNull EObject eObject : new TreeIterable(asRelation, true)) {
+ List<@NonNull VariableDeclaration> referredVariables = null;
+ if (eObject instanceof VariableExp) {
+ referredVariables = Lists.newArrayList(((VariableExp)eObject).getReferredVariable());
+ }
+ else if (eObject instanceof TemplateExp) {
+ referredVariables = Lists.newArrayList(((TemplateExp)eObject).getBindsTo());
+ if (eObject instanceof CollectionTemplateExp) {
+ referredVariables.add(((CollectionTemplateExp)eObject).getRest());
+ }
+ }
+ else if (eObject instanceof DomainPattern) {
+ referredVariables = Lists.newArrayList(((DomainPattern)eObject).getBindsTo());
+ }
+ if (referredVariables != null) {
+ for (@NonNull VariableDeclaration referredVariable : referredVariables) {
+ List<@NonNull Element> references = variable2reference.get(referredVariable);
+ if (references == null) {
+ references = new ArrayList<>();
+ variable2reference.put(referredVariable, references);
+ }
+ references.add((Element)eObject);
+ }
+ }
+ }
+ //
+ // Replace leaf non-composite template variables
+ //
+ for (@NonNull VariableDeclaration variable : variable2reference.keySet()) {
+ List<@NonNull Element> references = variable2reference.get(variable);
+ assert references != null;
+ if (variable instanceof TemplateVariable) {
+ boolean canBeShared = true;
+ for (@NonNull Element reference : references) {
+ if (reference instanceof ObjectTemplateExp) {
+ ObjectTemplateExp objectTemplateExp = (ObjectTemplateExp)reference;
+ if (!objectTemplateExp.getPart().isEmpty()) {
+ canBeShared = false;
+ break;
+ }
+ EObject eContainer = objectTemplateExp.eContainer();
+ if (eContainer instanceof PropertyTemplateItem) {
+ Property asProperty = ((PropertyTemplateItem)eContainer).getReferredProperty();
+ if ((asProperty == null) || asProperty.isIsComposite()) {
+ canBeShared = false;
+ break;
+ }
+ }
+ else {
+ canBeShared = false;
+ break;
+ }
+ }
+ else if (reference instanceof CollectionTemplateExp) {
+ CollectionTemplateExp collectionTemplateExp = (CollectionTemplateExp)reference;
+ if (!collectionTemplateExp.getMember().isEmpty()) {
+ canBeShared = false;
+ break;
+ }
+ if (collectionTemplateExp.getRest() != null) {
+ canBeShared = false;
+ break;
+ }
+ }
+ EReference eContainmentFeature = reference.eContainmentFeature();
+ EClassifier eType = eContainmentFeature.getEType();
+ if (!eType.isInstance(PivotPackage.Literals.OCL_EXPRESSION)) {
+ canBeShared = false;
+ break;
+ }
+ }
+ if (canBeShared) {
+ VariableDeclaration sharedVariable = QVTrelationFactory.eINSTANCE.createSharedVariable();
+ sharedVariable.setName(variable.getName());
+ sharedVariable.setType(variable.getType());
+ // sharedVariable.setIsImplicit(variable.isIsImplicit());
+ sharedVariable.setIsRequired(variable.isIsRequired());
+ // sharedVariable.setOwnedInit(variable.get);
+ QVTbaseUtil.replaceChild(variable, sharedVariable);
+ for (@NonNull Element reference : references) {
+ if (reference instanceof VariableExp) {
+ ((VariableExp)reference).setReferredVariable(sharedVariable);
+ }
+ else if (reference instanceof ObjectTemplateExp) {
+ QVTbaseUtil.replaceChild(reference, PivotUtil.createVariableExp(sharedVariable));
+ }
+ else if (reference instanceof CollectionTemplateExp) {
+ QVTbaseUtil.replaceChild(reference, PivotUtil.createVariableExp(sharedVariable));
+ }
+ else if (reference instanceof DomainPattern) {
+ ((DomainPattern)reference).getBindsTo().remove(variable);
+ }
+ }
+ }
+ }
+ }
+ }
+
+
@Override
protected void setUp() throws Exception {
QVTrTestUtil.doQVTrelationSetup();
@@ -124,7 +275,7 @@ public class UMLXTests extends LoadTestCase
URI pivotURI1 = getProjectFileURI("Forward2Reverse.qvtras");
URI umlxURI = getProjectFileURI("Forward2Reverse.umlx");
URI pivotURI2 = getProjectFileURI("Forward2Reverse.regenerated.qvtras");
- doRoundTripTest(inputURI1, pivotURI1, umlxURI, pivotURI2);
+ doRoundTripTest(inputURI1, pivotURI1, umlxURI, pivotURI2, false);
}
public void testUMLXRoundtrip_Keys_qvtr() throws Exception {
@@ -132,7 +283,7 @@ public class UMLXTests extends LoadTestCase
URI pivotURI1 = getProjectFileURI("Keys.qvtras");
URI umlxURI = getProjectFileURI("Keys.umlx");
URI pivotURI2 = getProjectFileURI("Keys.regenerated.qvtras");
- doRoundTripTest(inputURI1, pivotURI1, umlxURI, pivotURI2);
+ doRoundTripTest(inputURI1, pivotURI1, umlxURI, pivotURI2, false);
}
public void testUMLXRoundtrip_SeqToStm_qvtr() throws Exception {
@@ -141,14 +292,14 @@ public class UMLXTests extends LoadTestCase
URI pivotURI1 = getProjectFileURI("SeqToStm.qvtras");
URI umlxURI = getProjectFileURI("SeqToStm.umlx");
URI pivotURI2 = getProjectFileURI("SeqToStm.regenerated.qvtras");
- doRoundTripTest(inputURI1, pivotURI1, umlxURI, pivotURI2);
+ doRoundTripTest(inputURI1, pivotURI1, umlxURI, pivotURI2, false);
}
- /* public void testUMLXRoundtrip_SimplerRelToCore_qvtr() throws Exception {
+ public void testUMLXRoundtrip_SimplerRelToCore_qvtr() throws Exception {
URI inputURI1 = URI.createPlatformResourceURI("/org.eclipse.qvtd.examples.qvtrelation.reltocore/qvtrsrc/SimplerRelToCore.qvtr", true);
URI pivotURI1 = getProjectFileURI("SimplerRelToCore.qvtras");
URI umlxURI = getProjectFileURI("SimplerRelToCore.umlx");
URI pivotURI2 = getProjectFileURI("SimplerRelToCore.regenerated.qvtras");
- doRoundTripTest(inputURI1, pivotURI1, umlxURI, pivotURI2);
- } */
+ doRoundTripTest(inputURI1, pivotURI1, umlxURI, pivotURI2, true); // FIXME BUG 511230
+ }
}

Back to the top