diff --git a/JTL.eclipse/src/jtl/eclipse/AbstractEclipseJTLLauncher.java b/JTL.eclipse/src/jtl/eclipse/AbstractEclipseJTLLauncher.java index 8d1c859..68579f6 100644 --- a/JTL.eclipse/src/jtl/eclipse/AbstractEclipseJTLLauncher.java +++ b/JTL.eclipse/src/jtl/eclipse/AbstractEclipseJTLLauncher.java @@ -11,6 +11,11 @@ import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.Platform; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunchManager; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationType; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.emf.common.util.URI; import jtl.launcher.AbstractJTLLauncher; @@ -102,6 +107,57 @@ protected void processTracesModel() { tracesFile = tracesFileRelative; } + /** + * Runs the next transformation in the chain. + * @param targetFiles List of files to use as input + * of the chained transformation + */ + @Override + protected void runChainTransformation(final ArrayList targetFiles) { + // Get the launch configuration of the + // next transformation in the chain + ILaunchConfiguration lc = getLaunchConfiguration(this.chainTransformation); + if (lc != null) { + for (int i = 0; i < this.chainLimit; i++) { + try { + ILaunchConfigurationWorkingCopy lcwc = + lc.copy("CHAINED_" + this.chainTransformation); + lcwc.setAttribute(LaunchConfigurationAttributes.SOURCEM_TEXT, targetFiles.get(i)); + lcwc.launch(ILaunchManager.RUN_MODE, null); + } catch (CoreException e) { + System.err.println("An error occurred launching a chained transformation..."); + e.printStackTrace(); + } + } + } + } + + + /** + * Retrieves a JTL launch configuration specified by a name. + * @param name Name of the launch configuration + */ + protected ILaunchConfiguration getLaunchConfiguration(final String name) { + final ILaunchManager launchManager = + DebugPlugin.getDefault().getLaunchManager(); + ILaunchConfigurationType launchConfigurationType = launchManager + .getLaunchConfigurationType("JTL.launchConfigurationType"); + ILaunchConfiguration[] launchConfigurations = null; + try { + launchConfigurations = launchManager + .getLaunchConfigurations(launchConfigurationType); + } catch (CoreException e1) { + e1.printStackTrace(); + } + + for (ILaunchConfiguration lc : launchConfigurations) { + if (lc.getName().equals(name)) { + return lc; + } + } + return null; + } + /** * Compute MD5 of files involved in the launch */ diff --git a/JTL.eclipse/src/jtl/eclipse/LaunchConfigurationAttributes.java b/JTL.eclipse/src/jtl/eclipse/LaunchConfigurationAttributes.java index 8614052..e957b0f 100644 --- a/JTL.eclipse/src/jtl/eclipse/LaunchConfigurationAttributes.java +++ b/JTL.eclipse/src/jtl/eclipse/LaunchConfigurationAttributes.java @@ -9,4 +9,7 @@ public interface LaunchConfigurationAttributes { public static final String TRANSF_TEXT = "it.univaq.jtl.transf"; public static final String TRACE_CHECK = "it.univaq.jtl.tracecheck"; public static final String TRACE_TEXT = "it.univaq.jtl.trace"; + public static final String CHAIN_CHECK = "it.univaq.jtl.chaincheck"; + public static final String CHAIN_COMBO = "it.univaq.jtl.chaincombo"; + public static final String CHAIN_LIMIT = "it.univaq.jtl.chainlimit"; } diff --git a/JTL.eclipse/src/jtl/eclipse/LaunchConfigurationDelegate.java b/JTL.eclipse/src/jtl/eclipse/LaunchConfigurationDelegate.java index 240f0b5..428e530 100644 --- a/JTL.eclipse/src/jtl/eclipse/LaunchConfigurationDelegate.java +++ b/JTL.eclipse/src/jtl/eclipse/LaunchConfigurationDelegate.java @@ -111,6 +111,14 @@ public void launch(ILaunchConfiguration configuration, return; } + // Set the chained trasformation, if needed + if (configuration.getAttribute(LaunchConfigurationAttributes.CHAIN_CHECK, false)) { + launcher.setChainTransformation( + configuration.getAttribute(LaunchConfigurationAttributes.CHAIN_COMBO, "")); + launcher.setChainLimit( + configuration.getAttribute(LaunchConfigurationAttributes.CHAIN_LIMIT, 1)); + } + // Launch launcher.launch(); } diff --git a/JTL.eclipse/src/jtl/eclipse/LaunchConfigurationTab.java b/JTL.eclipse/src/jtl/eclipse/LaunchConfigurationTab.java index bbd080f..2a346c5 100644 --- a/JTL.eclipse/src/jtl/eclipse/LaunchConfigurationTab.java +++ b/JTL.eclipse/src/jtl/eclipse/LaunchConfigurationTab.java @@ -2,12 +2,18 @@ import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationType; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.debug.core.ILaunchManager; import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; @@ -17,10 +23,12 @@ import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Spinner; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.dialogs.ResourceListSelectionDialog; @@ -32,8 +40,12 @@ public class LaunchConfigurationTab extends AbstractLaunchConfigurationTab { private Text targetmText; private Text transfText; private Button tracesCheck; + private Button chainCheck; private Text tracesText; + private Combo chainCombo; + private Spinner chainLimitSpinner; private ArrayList tracesControls = new ArrayList(); + private ArrayList chainControls = new ArrayList(); @Override @@ -46,7 +58,7 @@ public void createControl(Composite parent) { comp.setFont(parent.getFont()); // Create a listener for user modifications of text fields - ModifyListener modListener = new ModifyListener() { + ModifyListener modTextListener = new ModifyListener() { @Override public void modifyText(ModifyEvent e) { updateLaunchConfigurationDialog(); @@ -67,7 +79,7 @@ public void modifyText(ModifyEvent e) { sourcemmText = new Text(metamodelsGroup, SWT.BORDER); sourcemmText.setLayoutData( new GridData(SWT.FILL, SWT.CENTER, true, false)); - sourcemmText.addModifyListener(modListener); + sourcemmText.addModifyListener(modTextListener); //sourcemmText.addModifyListener(new ModifyListener() { Button sourcemmButton = new Button(metamodelsGroup, SWT.PUSH); sourcemmButton.setText("Browse..."); @@ -86,7 +98,7 @@ public void widgetSelected(SelectionEvent e) { targetmmText = new Text(metamodelsGroup, SWT.BORDER); targetmmText.setLayoutData( new GridData(SWT.FILL, SWT.CENTER, true, false)); - targetmmText.addModifyListener(modListener); + targetmmText.addModifyListener(modTextListener); Button targetmmButton = new Button(metamodelsGroup, SWT.PUSH); targetmmButton.setText("Browse..."); targetmmButton.addSelectionListener(new SelectionAdapter() { @@ -113,7 +125,7 @@ public void widgetSelected(SelectionEvent e) { sourcemText = new Text(modelsGroup, SWT.BORDER); sourcemText.setLayoutData( new GridData(SWT.FILL, SWT.CENTER, true, false)); - sourcemText.addModifyListener(modListener); + sourcemText.addModifyListener(modTextListener); Button sourcemButton = new Button(modelsGroup, SWT.PUSH); sourcemButton.setText("Browse..."); sourcemButton.addSelectionListener(new SelectionAdapter() { @@ -131,7 +143,7 @@ public void widgetSelected(SelectionEvent e) { targetmText = new Text(modelsGroup, SWT.BORDER); targetmText.setLayoutData( new GridData(SWT.FILL, SWT.CENTER, true, false)); - targetmText.addModifyListener(modListener); + targetmText.addModifyListener(modTextListener); Button targetmButton = new Button(modelsGroup, SWT.PUSH); targetmButton.setText("Browse..."); targetmButton.addSelectionListener(new SelectionAdapter() { @@ -148,7 +160,7 @@ public void widgetSelected(SelectionEvent e) { // Group Group transfGroup = new Group(comp, SWT.NONE); transfGroup.setFont(comp.getFont()); - transfGroup.setLayout(new GridLayout(3, false)); + transfGroup.setLayout(new GridLayout(4, false)); transfGroup.setLayoutData( new GridData(SWT.FILL, SWT.CENTER, true, false)); transfGroup.setText("Transformation"); @@ -158,9 +170,11 @@ public void widgetSelected(SelectionEvent e) { transfText = new Text(transfGroup, SWT.BORDER); transfText.setLayoutData( new GridData(SWT.FILL, SWT.CENTER, true, false)); - transfText.addModifyListener(modListener); + transfText.addModifyListener(modTextListener); Button transfButton = new Button(transfGroup, SWT.PUSH); transfButton.setText("Browse..."); + transfButton.setLayoutData( + new GridData(SWT.BEGINNING, SWT.CENTER, false, false, 2, 1)); transfButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { @@ -175,7 +189,7 @@ public void widgetSelected(SelectionEvent e) { tracesCheck = new Button(transfGroup, SWT.CHECK); tracesCheck.setText("Provide a trace model"); tracesCheck.setLayoutData( - new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1)); + new GridData(SWT.FILL, SWT.CENTER, true, false, 4, 1)); tracesCheck.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { @@ -189,9 +203,11 @@ public void widgetSelected(SelectionEvent e) { tracesText = new Text(transfGroup, SWT.BORDER); tracesText.setLayoutData( new GridData(SWT.FILL, SWT.CENTER, true, false)); - tracesText.addModifyListener(modListener); + tracesText.addModifyListener(modTextListener); final Button tracesButton = new Button(transfGroup, SWT.PUSH); tracesButton.setText("Browse..."); + tracesButton.setLayoutData( + new GridData(SWT.BEGINNING, SWT.CENTER, false, false, 2, 1)); tracesButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { @@ -204,6 +220,67 @@ public void widgetSelected(SelectionEvent e) { tracesControls.add(tracesLabel); tracesControls.add(tracesText); tracesControls.add(tracesButton); + + // Chain + chainCheck = new Button(transfGroup, SWT.CHECK); + chainCheck.setText("Chain this transformation"); + chainCheck.setLayoutData( + new GridData(SWT.FILL, SWT.CENTER, true, false, 4, 1)); + chainCheck.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + final Button check = (Button) e.getSource(); + setChainVisible(check.getSelection()); + updateLaunchConfigurationDialog(); + } + }); + final Label chainLabel = new Label(transfGroup, SWT.NONE); + chainLabel.setText("Next:"); + + // Get the set of JTL launch configurations from the launch manager + final ILaunchManager launchManager = + DebugPlugin.getDefault().getLaunchManager(); + ILaunchConfigurationType launchConfigurationType = launchManager + .getLaunchConfigurationType("JTL.launchConfigurationType"); + ILaunchConfiguration[] launchConfigurations = null; + try { + launchConfigurations = launchManager + .getLaunchConfigurations(launchConfigurationType); + } catch (CoreException e1) { + e1.printStackTrace(); + } + + // Sort the launch configurations by name + Arrays.sort(launchConfigurations, new Comparator() { + @Override + public int compare(final ILaunchConfiguration lc1, final ILaunchConfiguration lc2) { + return lc1.getName().compareTo(lc2.getName()); + } + }); + + chainCombo = new Combo(transfGroup, SWT.DROP_DOWN); + chainCombo.setToolTipText("Select a launch configuration"); + for (ILaunchConfiguration config : launchConfigurations) { + chainCombo.add(config.getName()); + } + chainCombo.setLayoutData( + new GridData(SWT.FILL, SWT.CENTER, true, false)); + chainCombo.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + updateLaunchConfigurationDialog(); + } + }); + final Label chainLimitLabel = new Label(transfGroup, SWT.NONE); + chainLimitLabel.setText("Limit:"); + chainLimitSpinner = new Spinner(transfGroup, SWT.BORDER); + chainLimitSpinner.setToolTipText("Limit the number of input models"); + chainLimitSpinner.setMinimum(1); + chainLimitSpinner.addModifyListener(modTextListener); + chainControls.add(chainLabel); + chainControls.add(chainCombo); + chainControls.add(chainLimitLabel); + chainControls.add(chainLimitSpinner); } @Override @@ -228,6 +305,13 @@ public void initializeFrom(ILaunchConfiguration configuration) { tracesCheck.setSelection(configuration .getAttribute(LaunchConfigurationAttributes.TRACE_CHECK, false)); setTraceModelVisible(tracesCheck.getSelection()); + chainCheck.setSelection(configuration + .getAttribute(LaunchConfigurationAttributes.CHAIN_CHECK, false)); + chainCombo.setText(configuration + .getAttribute(LaunchConfigurationAttributes.CHAIN_COMBO, "")); + chainLimitSpinner.setSelection(configuration + .getAttribute(LaunchConfigurationAttributes.CHAIN_LIMIT, 1)); + setChainVisible(chainCheck.getSelection()); } catch (CoreException e) { System.out.println("Unable to load the configuration data."); e.printStackTrace(); @@ -250,6 +334,12 @@ public void performApply(ILaunchConfigurationWorkingCopy configuration) { tracesText.getText()); configuration.setAttribute(LaunchConfigurationAttributes.TRACE_CHECK, tracesCheck.getSelection()); + configuration.setAttribute(LaunchConfigurationAttributes.CHAIN_CHECK, + chainCheck.getSelection()); + configuration.setAttribute(LaunchConfigurationAttributes.CHAIN_COMBO, + chainCombo.getText()); + configuration.setAttribute(LaunchConfigurationAttributes.CHAIN_LIMIT, + chainLimitSpinner.getSelection()); } @Override @@ -321,6 +411,12 @@ public boolean isValid(ILaunchConfiguration launchConfig) { return false; } + if (chainCheck.getSelection() && chainCombo.getText().equals("")) { + errorMsg += "Select the next launch configuration in the chain"; + this.setErrorMessage(errorMsg); + return false; + } + this.setErrorMessage(null); return super.isValid(launchConfig); } @@ -331,4 +427,10 @@ private void setTraceModelVisible(final boolean visible) { } } + private void setChainVisible(final boolean visible) { + for (Control c : chainControls) { + c.setVisible(visible); + } + } + } diff --git a/JTL/src/jtl/launcher/AbstractJTLLauncher.java b/JTL/src/jtl/launcher/AbstractJTLLauncher.java index 5a578d0..cbd01ef 100644 --- a/JTL/src/jtl/launcher/AbstractJTLLauncher.java +++ b/JTL/src/jtl/launcher/AbstractJTLLauncher.java @@ -66,6 +66,12 @@ public abstract class AbstractJTLLauncher { // Traces model file protected File tracesFile; + // Next transformation in the chain + protected String chainTransformation; + + // Limit the number of models in input to the next transformation + protected int chainLimit; + // ASP output protected ByteArrayOutputStream asp = new ByteArrayOutputStream(); @@ -154,6 +160,23 @@ public void setASP(final ByteArrayOutputStream asp) { this.asp = asp; } + /** + * Sets the name of the next transformation in the chain. + * @param name Name of the next transformation + */ + public void setChainTransformation(final String name) { + this.chainTransformation = name; + } + + /** + * Sets the limit to the number of model to use + * as input of the next transformation in the chain. + * @param limit Limit to the number of models + */ + public void setChainLimit(final int limit) { + this.chainLimit = limit; + } + /** * Launch the transformation process. */ @@ -189,11 +212,22 @@ public void launch() { transfFile = new File(getASPFilename()); // Run the solver - ArrayList modelsFiles = + final ArrayList modelsFiles = runSolver(transfFile, targetmFolder, sourcemFile); - // Process target models - processTargetModels(modelsFiles, targetmmFile); + if (modelsFiles != null && modelsFiles.size() > 0) { + // Process target models + final ArrayList targetFiles = + processTargetModels(modelsFiles, targetmmFile); + + // Run the next transformation in the chain + if (this.chainTransformation != null && + this.chainLimit > 0 && + this.chainLimit <= modelsFiles.size()) { + + runChainTransformation(targetFiles); + } + } // Clean clean(); @@ -406,8 +440,9 @@ private String setTransformationDirection(final String transfASP) { * Process the ASP target models. * @param modelsFiles list of generated target models files * @param targetmmFile target metamodel filename + * @return list of the target models files after processing */ - protected void processTargetModels( + protected ArrayList processTargetModels( final ArrayList modelsFiles, final File targetmmFile) { @@ -423,6 +458,7 @@ protected void processTargetModels( } // Process target models + ArrayList targetFiles = new ArrayList(); for (String target : modelsFiles) { File targetFile = new File(target); @@ -432,7 +468,10 @@ protected void processTargetModels( // ASPm to Ecore (ATL generated from HOT) try { - ASPm2MM.runTransformation(targetmmFile, targetFile); + final String xmiFilename = ASPm2MM.runTransformation(targetmmFile, targetFile); + + // Add the generated file to the list of processed models files + targetFiles.add(xmiFilename); } catch (IOException | ATLCoreException e) { System.out.println("Unable to perform the Target Model ASPm to Ecore transformation:"); e.printStackTrace(); @@ -440,6 +479,8 @@ protected void processTargetModels( removeFile(targetFile); } } + + return targetFiles; } /** @@ -465,6 +506,13 @@ protected void processTracesModel() { } } + /** + * Runs the next transformation in the chain. + * @param targetFiles List of files to use as input + * of the chained transformation + */ + protected void runChainTransformation(ArrayList targetFiles) {} + /** * Run the solver to generate the target models. * @param ASPFile filename of the file containing the ASP program