| /******************************************************************************* |
| * Copyright (c) 2021 Robert Bosch GmbH. |
| * |
| * This program and the accompanying materials are made |
| * available under the terms of the Eclipse Public License 2.0 |
| * which is available at https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Robert Bosch GmbH - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.app4mc.transformation.ui.dialog; |
| |
| import java.nio.file.Path; |
| import java.util.ArrayList; |
| import java.util.Dictionary; |
| import java.util.Hashtable; |
| import java.util.List; |
| import java.util.Properties; |
| import java.util.stream.Collectors; |
| |
| import javax.inject.Inject; |
| |
| import org.eclipse.app4mc.transformation.ServiceConstants; |
| import org.eclipse.app4mc.transformation.TransformationConstants; |
| import org.eclipse.app4mc.transformation.TransformationDefinition; |
| import org.eclipse.app4mc.transformation.TransformationProcessor; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.e4.core.di.annotations.Optional; |
| import org.eclipse.e4.core.di.extensions.Service; |
| import org.eclipse.e4.core.services.events.IEventBroker; |
| import org.eclipse.jface.dialogs.Dialog; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.jface.layout.GridDataFactory; |
| import org.eclipse.jface.widgets.WidgetFactory; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.DirectoryDialog; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Group; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.swt.widgets.Text; |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.BundleContext; |
| import org.osgi.framework.FrameworkUtil; |
| import org.osgi.framework.ServiceRegistration; |
| import org.osgi.service.event.EventConstants; |
| import org.osgi.service.event.EventHandler; |
| |
| @SuppressWarnings("restriction") |
| public class TransformationDialog extends Dialog { |
| |
| private TransformationProcessor processor; |
| private List<TransformationDefinition> allDefinitions; |
| |
| private List<TransformationDefinition> selectedM2TDefinitions = new ArrayList<>(); |
| private List<TransformationDefinition> selectedM2MDefinitions = new ArrayList<>(); |
| |
| private Text inputFolderText; |
| private Text outputFolderText; |
| |
| private Path inputPath; |
| |
| // TODO add extension mechanism to provide additional ui configurations in the dialog, e.g. SLG ConfigModel |
| |
| // private Text configModelText; |
| // |
| // private Button experimentalCodeSnippetButton; |
| // private Button enableInstrumentationButton; |
| |
| // private ConfigModel configModel; |
| |
| private ServiceRegistration<?> eventHandler = null; |
| |
| private IEventBroker eventBroker; |
| |
| @Inject |
| public TransformationDialog( |
| Shell parentShell, |
| @Service TransformationProcessor processor, |
| @Service List<TransformationDefinition> definitions, |
| IEventBroker broker, |
| @Optional Path inputPath, |
| @Optional IProject project/*, |
| @Optional ConfigModel configModel*/) { |
| |
| super(parentShell); |
| this.processor = processor; |
| this.allDefinitions = definitions; |
| |
| this.eventBroker = broker; |
| |
| this.inputPath = inputPath; |
| // this.configModel = configModel; |
| |
| // register the eventhandler |
| Bundle bundle = FrameworkUtil.getBundle(getClass()); |
| BundleContext bc = (bundle != null) ? bundle.getBundleContext() : null; |
| if (bc != null) { |
| Dictionary<String, Object> props = new Hashtable<>(); |
| props.put(EventConstants.EVENT_TOPIC, "org/osgi/service/cm/ConfigurationEvent/CM_DELETED"); |
| // register the EventHandler service |
| this.eventHandler = bc.registerService( |
| EventHandler.class.getName(), |
| (EventHandler) event -> { |
| if (event.getProperty("cm.factoryPid").equals(ServiceConstants.SESSION_CONFIGURATION_PID)) { |
| Display.getDefault().asyncExec(() -> { |
| MessageDialog.openInformation(getParentShell(), "Transformation finished", "Transformation finished"); |
| |
| if (project != null) { |
| try { |
| project.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor()); |
| } catch (final CoreException e) { |
| Platform.getLog(getClass()).error(e.getLocalizedMessage(), e); |
| } |
| } |
| |
| eventHandler.unregister(); |
| |
| // send event to stop listening |
| eventBroker.send("org/eclipse/app4mc/transformation/FINISHED", "FINISHED"); |
| }); |
| } |
| }, |
| props); |
| } |
| } |
| |
| @Override |
| protected Control createDialogArea(Composite parent) { |
| Composite container = (Composite) super.createDialogArea(parent); |
| container.setLayout(new GridLayout(3, false)); |
| |
| // input folder |
| WidgetFactory |
| .label(SWT.NONE) |
| .text("Input Folder") |
| .create(container); |
| |
| this.inputFolderText = new Text(container, SWT.BORDER); |
| GridDataFactory |
| .swtDefaults() |
| .align(SWT.FILL, SWT.BEGINNING) |
| .grab(true, false) |
| .applyTo(inputFolderText); |
| |
| Button amaltheaButton = WidgetFactory |
| .button(SWT.PUSH) |
| .text("...") |
| .onSelect(e -> { |
| DirectoryDialog dirDialog = new DirectoryDialog(getShell()); |
| dirDialog.setText("Select the folder that contains the models to transform"); |
| String selectedDir = dirDialog.open(); |
| if (selectedDir != null) { |
| inputFolderText.setText(selectedDir); |
| } |
| }) |
| .create(container); |
| |
| // output folder |
| WidgetFactory |
| .label(SWT.NONE) |
| .text("Output Folder") |
| .create(container); |
| |
| this.outputFolderText = new Text(container, SWT.BORDER); |
| GridDataFactory |
| .swtDefaults() |
| .align(SWT.FILL, SWT.BEGINNING) |
| .grab(true, false) |
| .applyTo(outputFolderText); |
| |
| WidgetFactory |
| .button(SWT.PUSH) |
| .text("...") |
| .onSelect(e -> { |
| DirectoryDialog dirDialog = new DirectoryDialog(getShell()); |
| dirDialog.setText("Select the folder for the transformation results"); |
| String selectedDir = dirDialog.open(); |
| if (selectedDir != null) { |
| outputFolderText.setText(selectedDir); |
| } |
| }) |
| .create(container); |
| |
| /* |
| |
| // SLG specific settings |
| Group slgGroup = new Group(container, SWT.SHADOW_NONE); |
| slgGroup.setText("SLG Settings"); |
| slgGroup.setLayout(new GridLayout(3, false)); |
| GridDataFactory.fillDefaults().span(3, 1).grab(true, false).applyTo(slgGroup); |
| |
| // configuration file |
| WidgetFactory |
| .label(SWT.NONE) |
| .text("Configuration Model") |
| .create(slgGroup); |
| |
| this.configModelText = new Text(slgGroup, SWT.BORDER); |
| GridDataFactory |
| .swtDefaults() |
| .align(SWT.FILL, SWT.BEGINNING) |
| .grab(true, false) |
| .applyTo(configModelText); |
| |
| Button configModelButton = WidgetFactory |
| .button(SWT.PUSH) |
| .text("...") |
| .onSelect(e -> { |
| FileDialog fileDialog = new FileDialog(getShell()); |
| fileDialog.setText("Select the configuration model file"); |
| String selectedFile = fileDialog.open(); |
| if (selectedFile != null) { |
| configModelText.setText(selectedFile); |
| } |
| }) |
| .create(slgGroup); |
| |
| this.experimentalCodeSnippetButton = WidgetFactory |
| .button(SWT.CHECK) |
| .create(slgGroup); |
| Label experimentalLabel = WidgetFactory |
| .label(SWT.NONE) |
| .text("Experimental Code Snippet Matching") |
| .create(slgGroup); |
| GridDataFactory |
| .swtDefaults() |
| .align(SWT.FILL, SWT.BEGINNING) |
| .grab(true, false) |
| .span(2, 1) |
| .applyTo(experimentalLabel); |
| |
| this.enableInstrumentationButton = WidgetFactory |
| .button(SWT.CHECK) |
| .create(slgGroup); |
| Label instrumentationLabel = WidgetFactory |
| .label(SWT.NONE) |
| .text("Enable Instrumentation") |
| .create(slgGroup); |
| GridDataFactory |
| .swtDefaults() |
| .align(SWT.FILL, SWT.BEGINNING) |
| .grab(true, false) |
| .span(2, 1) |
| .applyTo(instrumentationLabel); |
| |
| */ |
| |
| // use already loaded models and lock selection otherwise |
| |
| if (this.inputPath != null) { |
| this.inputFolderText.setText(inputPath.toString()); |
| this.inputFolderText.setEditable(false); |
| amaltheaButton.setEnabled(false); |
| |
| this.outputFolderText.setText(inputPath.resolve("result").toString()); |
| } |
| |
| /* |
| if (this.configModel != null) { |
| this.configModelText.setText(this.configModel.eResource().getURI().toFileString()); |
| this.configModelText.setEditable(false); |
| configModelButton.setEnabled(false); |
| } |
| */ |
| |
| // transformer |
| if (this.allDefinitions.stream().anyMatch(def -> def.getM2TKey() != null)) { |
| Group group = new Group(container, SWT.SHADOW_NONE); |
| group.setText("Model to Text Transformation"); |
| group.setLayout(new GridLayout(2, false)); |
| GridDataFactory.fillDefaults().span(3, 1).grab(true, false).applyTo(group); |
| |
| this.allDefinitions.stream() |
| .filter(def -> def.getM2TKey() != null) |
| .forEach(def -> { |
| WidgetFactory |
| .button(SWT.CHECK) |
| .onSelect(e -> { |
| if (((Button)e.getSource()).getSelection()) { |
| selectedM2TDefinitions.add(def); |
| } else { |
| selectedM2TDefinitions.remove(def); |
| } |
| }) |
| .create(group); |
| WidgetFactory |
| .label(SWT.NONE) |
| .text(def.getName()) |
| .create(group); |
| }); |
| } |
| |
| if (this.allDefinitions.stream().anyMatch(def -> def.getM2MKey() != null)) { |
| Group group = new Group(container, SWT.SHADOW_NONE); |
| group.setText("Model to Model Transformation"); |
| group.setLayout(new GridLayout(2, false)); |
| GridDataFactory.fillDefaults().span(3, 1).grab(true, false).applyTo(group); |
| |
| this.allDefinitions.stream() |
| .filter(def -> def.getM2MKey() != null) |
| .forEach(def -> { |
| WidgetFactory |
| .button(SWT.CHECK) |
| .onSelect(e -> { |
| if (((Button)e.getSource()).getSelection()) { |
| selectedM2MDefinitions.add(def); |
| } else { |
| selectedM2MDefinitions.remove(def); |
| } |
| }) |
| .create(group); |
| WidgetFactory |
| .label(SWT.NONE) |
| .text(def.getName()) |
| .create(group); |
| }); |
| } |
| |
| return container; |
| } |
| |
| @Override |
| protected void okPressed() { |
| // collect information from dialog |
| Properties properties = new Properties(); |
| properties.put(TransformationConstants.INPUT_MODELS_FOLDER, this.inputFolderText.getText()); |
| properties.put(TransformationConstants.OUTPUT_FOLDER, this.outputFolderText.getText()); |
| if (!this.selectedM2TDefinitions.isEmpty()) { |
| List<String> keys = this.selectedM2TDefinitions.stream().map(TransformationDefinition::getM2TKey).collect(Collectors.toList()); |
| properties.put(TransformationConstants.M2T_TRANSFORMERS, String.join(",", keys)); |
| } |
| if (!this.selectedM2MDefinitions.isEmpty()) { |
| List<String> keys = this.selectedM2MDefinitions.stream().map(TransformationDefinition::getM2MKey).collect(Collectors.toList()); |
| properties.put(TransformationConstants.M2M_TRANSFORMERS, String.join(",", keys)); |
| } |
| |
| |
| // properties.put("configurationFile", configModelText.getText()); |
| // |
| // properties.put("experimentalCodeSnippetMatching", Boolean.toString(this.experimentalCodeSnippetButton.getSelection())); |
| // properties.put("enableInstrumentation", Boolean.toString(this.enableInstrumentationButton.getSelection())); |
| |
| try { |
| // start transformation |
| this.processor.startTransformation(properties); |
| |
| // send event to start listening |
| this.eventBroker.send("org/eclipse/app4mc/transformation/STARTED", properties.get(TransformationConstants.LOG_FILE)); |
| |
| super.okPressed(); |
| } catch (Exception e) { |
| MessageDialog.openError(getParentShell(), "Error in transformation", e.getLocalizedMessage()); |
| } |
| |
| } |
| |
| @Override |
| protected void configureShell(Shell newShell) { |
| super.configureShell(newShell); |
| newShell.setText("Amalthea Transformation"); |
| } |
| |
| @Override |
| protected Point getInitialSize() { |
| return new Point( |
| convertHorizontalDLUsToPixels(250), |
| convertVerticalDLUsToPixels(200)); |
| } |
| |
| @Override |
| protected boolean isResizable() { |
| return true; |
| } |
| } |