blob: 24880df261349f182fdb9f017362602d5c8fb648 [file] [log] [blame]
/*******************************************************************************
* 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;
}
}