Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian W. Damus2016-06-20 23:08:35 +0000
committerChristian W. Damus2016-06-21 12:00:14 +0000
commit9c8164bdfca8d8eb55f3925332b079d63ce93654 (patch)
treecd44a419ffa47f151e6ec885cdf489141cbd30d5 /extraplugins
parentda232baf5ed359e641090de829fee43273d3bf48 (diff)
downloadorg.eclipse.papyrus-9c8164bdfca8d8eb55f3925332b079d63ce93654.tar.gz
org.eclipse.papyrus-9c8164bdfca8d8eb55f3925332b079d63ce93654.tar.xz
org.eclipse.papyrus-9c8164bdfca8d8eb55f3925332b079d63ce93654.zip
Bug 496439: [RSA Import] Give mapping traces to extension transformations
https://bugs.eclipse.org/bugs/show_bug.cgi?id=496439 Carry mapping traces forward from each transformation in the chain to the next. Provide a black-box library with custom operations that query the mapping traces to find sources for generated outputs because the standard invresolve and invresolveone operations only inspect the traces of the current transformation, not any previous. Provide also a new API for execution of a transformation that automatically includes the traces, so that extensions can make use of them, too (otherwise, as currently in Papyrus-RT, they will always have to reimplement access to the executor pool, which is a detail that should be abstracted away from them). Change-Id: Ibeece23d01bf8fb86bf714995141cfc01685a509
Diffstat (limited to 'extraplugins')
-rw-r--r--extraplugins/migration/org.eclipse.papyrus.m2m.qvto/plugin.xml11
-rw-r--r--extraplugins/migration/org.eclipse.papyrus.m2m.qvto/src/org/eclipse/papyrus/m2m/qvto/TraceHelper.java161
-rw-r--r--extraplugins/migration/org.eclipse.papyrus.migration.rsa/src/org/eclipse/papyrus/migration/rsa/transformation/ImportTransformation.java153
-rw-r--r--extraplugins/migration/org.eclipse.papyrus.migration.rsa/src/org/eclipse/papyrus/migration/rsa/transformation/ImportTransformationLauncher.java9
4 files changed, 275 insertions, 59 deletions
diff --git a/extraplugins/migration/org.eclipse.papyrus.m2m.qvto/plugin.xml b/extraplugins/migration/org.eclipse.papyrus.m2m.qvto/plugin.xml
index d58f53e2fc6..b6044f7e524 100644
--- a/extraplugins/migration/org.eclipse.papyrus.m2m.qvto/plugin.xml
+++ b/extraplugins/migration/org.eclipse.papyrus.m2m.qvto/plugin.xml
@@ -47,6 +47,17 @@
</metamodel>
</library>
</unit>
+ <unit
+ description="Provides access to the incremental trace model for ad hoc trace queries."
+ name="Traces"
+ namespace="org.eclipse.papyrus.m2m.qvto">
+ <library
+ class="org.eclipse.papyrus.m2m.qvto.TraceHelper">
+ <metamodel
+ nsURI="http://www.eclipse.org/emf/2002/Ecore">
+ </metamodel>
+ </library>
+ </unit>
</extension>
<extension
point="org.eclipse.m2m.qvt.oml.runtime.qvtTransformation">
diff --git a/extraplugins/migration/org.eclipse.papyrus.m2m.qvto/src/org/eclipse/papyrus/m2m/qvto/TraceHelper.java b/extraplugins/migration/org.eclipse.papyrus.m2m.qvto/src/org/eclipse/papyrus/m2m/qvto/TraceHelper.java
new file mode 100644
index 00000000000..0eda873a6d9
--- /dev/null
+++ b/extraplugins/migration/org.eclipse.papyrus.m2m.qvto/src/org/eclipse/papyrus/m2m/qvto/TraceHelper.java
@@ -0,0 +1,161 @@
+/*****************************************************************************
+ * Copyright (c) 2016 Christian W. Damus 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:
+ * Christian W. Damus - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.m2m.qvto;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.m2m.internal.qvt.oml.trace.EValue;
+import org.eclipse.m2m.internal.qvt.oml.trace.Trace;
+import org.eclipse.m2m.internal.qvt.oml.trace.TraceRecord;
+import org.eclipse.m2m.internal.qvt.oml.trace.VarParameterValue;
+import org.eclipse.m2m.qvt.oml.ExecutionContext;
+import org.eclipse.m2m.qvt.oml.blackbox.java.Operation;
+import org.eclipse.m2m.qvt.oml.blackbox.java.Operation.Kind;
+import org.eclipse.m2m.qvt.oml.util.IContext;
+import org.eclipse.m2m.qvt.oml.util.ISessionData;
+
+/**
+ * Query operations that introspect the trace model.
+ */
+@SuppressWarnings("restriction")
+public class TraceHelper {
+ /**
+ * QVTo {@link ExecutionContext} session data key for the cumulative trace history.
+ * This is distinct from the session data for incremental update traces because it
+ * is not used for incremental update, but as a "memory" of trace relationships
+ * established by past transformations.
+ */
+ public static ISessionData.SimpleEntry<org.eclipse.m2m.qvt.oml.util.Trace> TRACE_HISTORY = new ISessionData.SimpleEntry<org.eclipse.m2m.qvt.oml.util.Trace>();
+
+ private final Map<String, EClass> eclasses = new HashMap<String, EClass>();
+
+ /**
+ * Initializes me.
+ */
+ public TraceHelper() {
+ super();
+ }
+
+ /**
+ * Gets the source object from which a given {@code self} object traces.
+ *
+ * @param context
+ * the execution context
+ * @param self
+ * the object for which to trace its original in the source model
+ *
+ * @return
+ * the source object, or {@code null} if not found in the traces
+ */
+ @Operation(contextual = true, kind = Kind.QUERY, withExecutionContext = true)
+ public Object traceFrom(IContext context, Object self) {
+ return traceFrom(context, self, null);
+ }
+
+ /**
+ * Gets the source object from which a given {@code self} object traces.
+ *
+ * @param context
+ * the execution context
+ * @param self
+ * the object for which to trace its original in the source model
+ * @param type
+ * the type of source object to obtain, in case multiple sources
+ * map to the same target (may be {@code null} to get any source)
+ *
+ * @return
+ * the source object, or {@code null} if not found in the traces
+ */
+ @Operation(contextual = true, kind = Kind.QUERY, withExecutionContext = true)
+ public Object traceFrom(IContext context, Object self, String type) {
+ EObject result = null;
+
+ org.eclipse.m2m.qvt.oml.util.Trace history = context.getSessionData().getValue(TRACE_HISTORY);
+ List<EObject> traces = (history != null) ? history.getTraceContent() : Collections.<EObject> emptyList();
+
+ for (EObject next : traces) {
+ if (next instanceof Trace) {
+ Trace trace = (Trace) next;
+ EList<TraceRecord> inverse = trace.getTargetToTraceRecordMap().get(self);
+ if (inverse != null) {
+ for (TraceRecord record : inverse) {
+ VarParameterValue source = record.getContext().getContext();
+ EValue sourceValue = (source == null) ? null : source.getValue();
+ EObject sourceElement = (sourceValue == null) ? null : sourceValue.getModelElement();
+
+ if ((sourceElement != null) && ((type == null) || isA(sourceElement.eClass(), type))) {
+ result = sourceElement;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+ private boolean isA(EClass eclass, String type) {
+ boolean result;
+
+ EClass target = eclasses.get(type);
+ if (target != null) {
+ result = target.isSuperTypeOf(eclass);
+ } else {
+ result = __isA(eclass, type);
+ }
+
+ return result;
+ }
+
+ private boolean __isA(EClass eclass, String type) {
+ boolean result;
+
+ String qname = qname(eclass);
+ result = qname.equals(type);
+ if (!result) {
+ for (EClass next : eclass.getESuperTypes()) {
+ result = isA(next, type);
+ if (result) {
+ break;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ private String qname(EClass eclass) {
+ StringBuilder buf = new StringBuilder();
+ buf.append(eclass.getEPackage().getName());
+ buf.append("::"); //$NON-NLS-1$
+ buf.append(eclass.getName());
+
+ for (EPackage nesting = eclass.getEPackage().getESuperPackage(); nesting != null; nesting = nesting.getESuperPackage()) {
+ buf.insert(0, "::"); //$NON-NLS-1$
+ buf.insert(0, nesting.getName());
+ }
+
+ String result = buf.toString();
+ eclasses.put(result, eclass);
+ return result;
+ }
+}
diff --git a/extraplugins/migration/org.eclipse.papyrus.migration.rsa/src/org/eclipse/papyrus/migration/rsa/transformation/ImportTransformation.java b/extraplugins/migration/org.eclipse.papyrus.migration.rsa/src/org/eclipse/papyrus/migration/rsa/transformation/ImportTransformation.java
index 797ef627759..89d3ac30a00 100644
--- a/extraplugins/migration/org.eclipse.papyrus.migration.rsa/src/org/eclipse/papyrus/migration/rsa/transformation/ImportTransformation.java
+++ b/extraplugins/migration/org.eclipse.papyrus.migration.rsa/src/org/eclipse/papyrus/migration/rsa/transformation/ImportTransformation.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2013, 2014 CEA LIST.
+ * Copyright (c) 2013, 2016 CEA LIST, Christian W. Damus, and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,6 +8,7 @@
*
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus - bug 496439
*****************************************************************************/
package org.eclipse.papyrus.migration.rsa.transformation;
@@ -67,11 +68,14 @@ import org.eclipse.m2m.qvt.oml.ExecutionContextImpl;
import org.eclipse.m2m.qvt.oml.ExecutionDiagnostic;
import org.eclipse.m2m.qvt.oml.ModelExtent;
import org.eclipse.m2m.qvt.oml.TransformationExecutor;
+import org.eclipse.m2m.qvt.oml.util.ISessionData;
+import org.eclipse.m2m.qvt.oml.util.Trace;
import org.eclipse.m2m.qvt.oml.util.WriterLog;
import org.eclipse.papyrus.dsml.validation.PapyrusDSMLValidationRule.PapyrusDSMLValidationRulePackage;
import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.infra.tools.util.ClassLoaderHelper;
import org.eclipse.papyrus.infra.tools.util.ListHelper;
+import org.eclipse.papyrus.m2m.qvto.TraceHelper;
import org.eclipse.papyrus.m2m.qvto.TransformationUI;
import org.eclipse.papyrus.migration.rsa.Activator;
import org.eclipse.papyrus.migration.rsa.RSAToPapyrusParameters.Config;
@@ -162,6 +166,12 @@ public class ImportTransformation {
/** The extension point contributing {@link TransformationExtension}s */
public static final String EXTENSION_POINT_ID = Activator.PLUGIN_ID + ".extensions";
+ /** Accumulation of incremental update traces from each transformation. */
+ private Trace trace = Trace.createEmptyTrace();
+
+ /** Transformation execution context used for all transformation runs. */
+ private ExecutionContext context;
+
static {
sourceEPackages.add(org.eclipse.papyrus.migration.rsa.default_.DefaultPackage.eINSTANCE);
sourceEPackages.add(org.eclipse.papyrus.migration.rsa.profilebase.ProfileBasePackage.eINSTANCE);
@@ -489,52 +499,65 @@ public class ImportTransformation {
String statusMessage = String.format("Import %s", getModelName());
MultiStatus generationStatus = new MultiStatus(Activator.PLUGIN_ID, IStatus.OK, statusMessage, null);
- ExecutionContext context = createExecutionContext(monitor, generationStatus);
+ context = createExecutionContext(monitor, generationStatus);
+
+ try {
+ getInPapyrusProfiles(); // Preload profiles
- getInPapyrusProfiles(); // Preload profiles
+ long endLoad = System.nanoTime();
+ loadingTime = endLoad - startLoad;
- long endLoad = System.nanoTime();
- loadingTime = endLoad - startLoad;
+ //
+ // TRANSFORMATIONS
+ //
- //
- // TRANSFORMATIONS
- //
+ IStatus result; // Result of an individual transformation (Will be aggregated to the complete GenerationStatus)
- IStatus result; // Result of an individual transformation (Will be aggregated to the complete GenerationStatus)
+ prepareExtensions();
- prepareExtensions();
+ long startExtensions = System.nanoTime();
+ result = importExtensions(context, monitor, ExtensionFunction::executeBefore);
+ long endExtensions = System.nanoTime();
+ this.importExtensionsTime = endExtensions - startExtensions;
+ generationStatus.add(result);
- long startExtensions = System.nanoTime();
- result = importExtensions(context, monitor, ExtensionFunction::executeBefore);
- long endExtensions = System.nanoTime();
- this.importExtensionsTime = endExtensions - startExtensions;
- generationStatus.add(result);
+ // Diagrams
+ Collection<URI> transformations = getDiagramTransformationURIs();
- // Diagrams
- Collection<URI> transformations = getDiagramTransformationURIs();
+ monitor.subTask("Importing diagrams...");
+ for (URI transformationURI : transformations) {
+ result = runTransformation(transformationURI, extents, monitor);
+ generationStatus.add(result);
+ }
- monitor.subTask("Importing diagrams...");
- for (URI transformationURI : transformations) {
- result = runTransformation(transformationURI, context, monitor, extents);
+ // Semantic model changes (Default language for OpaqueExpressions...)
+ monitor.subTask("Importing semantic model...");
+ result = runTransformation(getSemanticTransformationURI(), extents, monitor);
generationStatus.add(result);
- }
- // Semantic model changes (Default language for OpaqueExpressions...)
- monitor.subTask("Importing semantic model...");
- result = runTransformation(getSemanticTransformationURI(), context, monitor, extents);
- generationStatus.add(result);
+ if (!monitor.isCanceled()) {
+ monitor.subTask("Handle additional profiles...");
+ // Default.epx and ProfileBase.epx
+ result = importRSAProfiles(context, monitor);
+ generationStatus.add(result);
+ }
- if (!monitor.isCanceled()) {
- monitor.subTask("Handle additional profiles...");
- // Default.epx and ProfileBase.epx
- result = importRSAProfiles(context, monitor);
- generationStatus.add(result);
- }
+ Collection<URI> additional = getAdditionalTransformationURIs();
+ if (!additional.isEmpty()) {
+ monitor.subTask("Additional transformations...");
+ for (URI transformationURI : additional) {
+ result = runTransformation(transformationURI, extents, monitor);
+ generationStatus.add(result);
+ }
+ }
- long startExtensionsAfter = System.nanoTime();
- result = importExtensions(context, monitor, ExtensionFunction::executeAfter);
- long endExtensionsAfter = System.nanoTime();
- this.importExtensionsTime += endExtensionsAfter - startExtensionsAfter;
+ long startExtensionsAfter = System.nanoTime();
+ result = importExtensions(context, monitor, ExtensionFunction::executeAfter);
+ long endExtensionsAfter = System.nanoTime();
+ this.importExtensionsTime += endExtensionsAfter - startExtensionsAfter;
+ } finally {
+ context = null;
+ }
//
// FRAGMENTS & SAVE
@@ -777,30 +800,10 @@ public class ImportTransformation {
extents.add(getInProfileDefinitions());
extents.add(getInConfig());
- TransformationExecutor executor;
- try {
- executor = getTransformation(transformationURI, monitor);
- } catch (DiagnosticException ex) {
- Diagnostic diagnostic = ex.getDiagnostic();
-
- Activator.log.warn(String.format("Cannot load the transformation : %s. Diagnostic: %s", transformationURI, diagnostic.getMessage()));
- return createStatusFromDiagnostic(diagnostic);
- }
-
- ExecutionDiagnostic transformationResult;
- synchronized (executor) {
- try {
- transformationResult = executor.execute(context, extents.toArray(new ModelExtent[0]));
- } finally {
- executor.cleanup();
- executorsPool.releaseExecutor(executor);
- }
- }
-
+ IStatus transformationStatus = runTransformation(transformationURI, extents, monitor);
IStatus loadedProfilesStatus = createStatusFromDiagnostic(loadedProfiles);
- IStatus transformationStatus = createStatusFromDiagnostic(transformationResult);
- int severity = Math.max(loadedProfiles.getSeverity(), transformationResult.getSeverity());
+ int severity = Math.max(loadedProfiles.getSeverity(), transformationStatus.getSeverity());
String message;
if (severity > IStatus.OK) {
@@ -1085,6 +1088,22 @@ public class ImportTransformation {
}
}
+ /**
+ * Runs a transformation using the context shared by all transformations.
+ *
+ * @param transformationURI
+ * the transformation to run
+ * @param extents
+ * the extents on which to apply the transformation
+ * @param monitor
+ * progress monitor
+ *
+ * @return the result of the transformation execution
+ */
+ public IStatus runTransformation(URI transformationURI, List<ModelExtent> extents, IProgressMonitor monitor) {
+ return runTransformation(transformationURI, context, monitor, extents);
+ }
+
protected IStatus runTransformation(URI transformationURI, ExecutionContext context, IProgressMonitor monitor, List<ModelExtent> extents) {
if (monitor.isCanceled()) {
return new Status(IStatus.CANCEL, Activator.PLUGIN_ID, "Operation canceled");
@@ -1103,7 +1122,18 @@ public class ImportTransformation {
ExecutionDiagnostic result;
synchronized (executor) {
try {
+ // Gather the new execution traces
+ Trace newTraces = Trace.createEmptyTrace();
+ @SuppressWarnings("restriction")
+ ISessionData.SimpleEntry<Trace> traceKey = org.eclipse.m2m.internal.qvt.oml.evaluator.QVTEvaluationOptions.INCREMENTAL_UPDATE_TRACE;
+ context.getSessionData().setValue(traceKey, newTraces);
+
result = executor.execute(context, extents.toArray(new ModelExtent[0]));
+
+ // Append to our history
+ List<EObject> history = new ArrayList<EObject>(trace.getTraceContent());
+ history.addAll(newTraces.getTraceContent());
+ trace.setTraceContent(history);
} finally {
executor.cleanup();
executorsPool.releaseExecutor(executor);
@@ -1152,6 +1182,10 @@ public class ImportTransformation {
initTransformationProperties(context);
+ // Invoke extensions as incremental transformations
+
+ context.getSessionData().setValue(TraceHelper.TRACE_HISTORY, trace);
+
return context;
}
@@ -1304,10 +1338,15 @@ public class ImportTransformation {
return getTransformationURI("RSAProfilesToPapyrus");
}
+ protected Collection<URI> getAdditionalTransformationURIs() {
+ return Collections.emptyList();
+ }
+
protected Collection<URI> getAllTransformationURIs() {
Collection<URI> allTransformations = getDiagramTransformationURIs();
allTransformations.add(getProfilesTransformationURI());
allTransformations.add(getSemanticTransformationURI());
+ allTransformations.addAll(getAdditionalTransformationURIs());
return allTransformations;
}
diff --git a/extraplugins/migration/org.eclipse.papyrus.migration.rsa/src/org/eclipse/papyrus/migration/rsa/transformation/ImportTransformationLauncher.java b/extraplugins/migration/org.eclipse.papyrus.migration.rsa/src/org/eclipse/papyrus/migration/rsa/transformation/ImportTransformationLauncher.java
index 81c13274614..28d02c53116 100644
--- a/extraplugins/migration/org.eclipse.papyrus.migration.rsa/src/org/eclipse/papyrus/migration/rsa/transformation/ImportTransformationLauncher.java
+++ b/extraplugins/migration/org.eclipse.papyrus.migration.rsa/src/org/eclipse/papyrus/migration/rsa/transformation/ImportTransformationLauncher.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2014 CEA LIST.
+ * Copyright (c) 2014, 2016 CEA LIST, Christian W. Damus, and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,6 +8,7 @@
*
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus - bug 496439
*****************************************************************************/
package org.eclipse.papyrus.migration.rsa.transformation;
@@ -159,7 +160,7 @@ public class ImportTransformationLauncher {
analysisHelper = new DependencyAnalysisHelper(config);
for (URI uri : urisToImport) {
- ImportTransformation transformation = new ImportTransformation(uri, config, analysisHelper);
+ ImportTransformation transformation = createTransformation(uri);
transformations.add(transformation);
}
@@ -167,6 +168,10 @@ public class ImportTransformationLauncher {
importModels(transformations);
}
+ protected ImportTransformation createTransformation(URI transformationURI) {
+ return new ImportTransformation(transformationURI, config, analysisHelper);
+ }
+
/**
* Start a Job and delegate to {@link #importModels(IProgressMonitor, List)}
*

Back to the top