Commit 8a8711f2 authored by Philip Makedonski's avatar Philip Makedonski
Browse files

+ added TP to TD dialog with basic options (&34)

* needs cleaning up..
parent 19c3025d
Loading
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -13,6 +13,11 @@
            categoryId="org.etsi.mts.tdl.tools.rt.ui.commands.category"
            id="org.etsi.mts.tdl.tools.rt.ui.commands.translateCommand">
      </command>
      <command
            name="Transform TPs to TDs"
            categoryId="org.etsi.mts.tdl.tools.rt.ui.commands.category"
            id="org.etsi.mts.tdl.tools.rt.ui.commands.tp2tdCommand">
      </command>
   </extension>
   <extension
         point="org.eclipse.ui.handlers">
@@ -20,6 +25,10 @@
            commandId="org.etsi.mts.tdl.tools.rt.ui.commands.translateCommand"
            class="org.etsi.mts.tdl.tools.rt.ui.handlers.TranslationHandler">
      </handler>
      <handler
            commandId="org.etsi.mts.tdl.tools.rt.ui.commands.tp2tdCommand"
            class="org.etsi.mts.tdl.tools.rt.ui.handlers.TP2TDHandler">
      </handler>
   </extension>
   <extension
         point="org.eclipse.ui.bindings">
@@ -45,6 +54,17 @@
                  id="org.etsi.mts.tdl.tools.rt.ui.menus.translateCommand">
            </command>
         </menu>
         <menu
               label="TDL"
               mnemonic="T"
               id="org.etsi.mts.tdl.tools.menus.TDLMenu">
            <command
                  commandId="org.etsi.mts.tdl.tools.rt.ui.commands.tp2tdCommand"
                  icon="icons/TransformIcon.png"
                  mnemonic="T"
                  id="org.etsi.mts.tdl.tools.rt.ui.menus.tp2tdCommand">
            </command>
         </menu>
      </menuContribution>
      <menuContribution
            locationURI="toolbar:org.eclipse.ui.main.toolbar?after=additions">
@@ -56,6 +76,12 @@
                  tooltip="Translate TDL Model"
                  id="org.etsi.mts.tdl.tools.rt.ui.toolbars.translateCommand">
            </command>
            <command
                  commandId="org.etsi.mts.tdl.tools.rt.ui.commands.tp2tdCommand"
                  icon="icons/TransformIcon.png"
                  tooltip="Transform TPs to TDs"
                  id="org.etsi.mts.tdl.tools.rt.ui.toolbars.tp2tdCommand">
            </command>
         </toolbar>
      </menuContribution>
   </extension>
+175 −0
Original line number Diff line number Diff line
package org.etsi.mts.tdl.tools.rt.ui;

import org.eclipse.core.runtime.preferences.ConfigurationScope;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.layout.GridData;
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.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.osgi.service.prefs.Preferences;

public class TP2TDDialog extends TitleAreaDialog {

    private Text prefixField;
    private Text suffixField;
    private Button removeAnnotationsButton;
    private Button removeAnnotatedBlocksButton;

    //TODO: numbers, first / last?
    private String regex = "[a-zA-Z_]"; 

    
    //TODO: store between runs 
    private String prefix = "";
    private String suffix = "_TDs";
    private boolean removeAnnotations = false;
    private boolean removeAnnotatedBlocks = false;
	private IEclipsePreferences preferences;
	private Preferences tp2td;

    public TP2TDDialog(Shell parentShell) {
        super(parentShell);
        preferences = ConfigurationScope.INSTANCE
                .getNode("org.etsi.mts.tdl.converters");
        tp2td = preferences.node("tp2td");
    }

    @Override
    public void create() {
        super.create();
        setTitle("Transform TPs to TDs");
        setMessage("Customise the tranformation process", IMessageProvider.INFORMATION);
    }

    @Override
    protected Control createDialogArea(Composite parent) {
        Composite area = (Composite) super.createDialogArea(parent);
        Composite container = new Composite(area, SWT.NONE);
        container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        GridLayout layout = new GridLayout(2, false);
        container.setLayout(layout);

        prefix = tp2td.get("prefix", "");
        suffix = tp2td.get("suffix", "_TDs");
        removeAnnotations = tp2td.getBoolean("removeAnnotations", false);
        removeAnnotatedBlocks = tp2td.getBoolean("removeAnnotatedBlocks", false);

        
        //DONE: validate to make sure that at least one is used
        //		- validate special characters (only characters, numbers, underscores)
        //		-> basic validation done, no numbers at present (need to check first character in case)
        //TODO: fix layouts
        prefixField = createTextField(container, "Package prefix", prefix);
        addValidation(prefixField, regex);
        suffixField = createTextField(container, "Package suffix", suffix);
        addValidation(suffixField, regex);
        //TODO: hints
        removeAnnotationsButton = createOption(container, "Remove annotations", isRemoveAnnotations());
        removeAnnotatedBlocksButton = createOption(container, "Remove annotated blocks", isRemoveAnnotatedBlocks());
        removeAnnotationsButton.addSelectionListener(SelectionListener.widgetSelectedAdapter(e-> {
        	if (!removeAnnotationsButton.getSelection() && removeAnnotatedBlocksButton.getSelection()) {
        		removeAnnotatedBlocksButton.setSelection(false);
        	}
        }));
        removeAnnotatedBlocksButton.addSelectionListener(SelectionListener.widgetSelectedAdapter(e-> {
        	if (!removeAnnotationsButton.getSelection() && removeAnnotatedBlocksButton.getSelection()) {
        		removeAnnotationsButton.setSelection(true);
        	}
        }));
        
        return area;
    }

    //TODO: there ought to be JFace shortcut for this... or use bindings?
    private Text createTextField(Composite container, String label, String value) {
        Label l = new Label(container, SWT.NONE);
        l.setText(label);

        GridData d = new GridData();
        d.grabExcessHorizontalSpace = true;
        d.horizontalAlignment = GridData.FILL;
        var text = new Text(container, SWT.BORDER);
        text.setLayoutData(d);
        text.setText(value);
        return text;
    }
    private void addValidation(Text text, String regex) {
    	text.addVerifyListener(e->validateRegEx(e, regex));
    }
    private Object validateRegEx(VerifyEvent e, String regex) {
    	e.doit = e.text.matches(regex) || e.keyCode == SWT.DEL || e.keyCode == SWT.BS;
		return null;
	}

    private Button createOption(Composite container, String label, boolean value) {
    	final Button button = new Button (container, SWT.CHECK);
        GridData d = new GridData();
        d.grabExcessHorizontalSpace = true;
        d.horizontalAlignment = GridData.FILL;
    	button.setLayoutData(d);
		button.setText(label);
		button.setSelection(value);
		return button;
    }


    @Override
    protected boolean isResizable() {
        return true;
    }

    // save content of the Text fields because they get disposed
    // as soon as the Dialog closes
    
    private void saveInput() {
        prefix = prefixField.getText();
        suffix = suffixField.getText();
        removeAnnotations = removeAnnotationsButton.getSelection();
        removeAnnotatedBlocks = removeAnnotatedBlocksButton.getSelection();
        
        tp2td.put("prefix", prefix);
        tp2td.get("suffix", suffix);
        tp2td.putBoolean("removeAnnotations", removeAnnotations);
        tp2td.putBoolean("removeAnnotatedBlocks", removeAnnotatedBlocks);
        
        try {
            // forces the application to save the preferences
            preferences.flush();
        } catch (Exception e2) {
            e2.printStackTrace();
        }

    }

    @Override
    protected void okPressed() {
        saveInput();
        super.okPressed();
    }

    public String getPrefix() {
        return prefix;
    }

    public String getSuffix() {
        return suffix;
    }

	public boolean isRemoveAnnotations() {
		return removeAnnotations;
	}

	public boolean isRemoveAnnotatedBlocks() {
		return removeAnnotatedBlocks;
	}
}
 No newline at end of file
+150 −0
Original line number Diff line number Diff line
package org.etsi.mts.tdl.tools.rt.ui.handlers;

import java.util.List;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IFile;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.handlers.HandlerUtil;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.xtext.EcoreUtil2;
import org.eclipse.xtext.resource.XtextResourceSet;
import org.etsi.mts.tdl.Annotation;
import org.etsi.mts.tdl.Block;
import org.etsi.mts.tdl.CompoundBehaviour;
import org.etsi.mts.tdl.Element;
import org.etsi.mts.tdl.Package;
import org.etsi.mts.tdl.TestDescription;
import org.etsi.mts.tdl.tools.rt.ui.TP2TDDialog;

import com.google.inject.Guice;
import com.google.inject.Injector;

public class TP2TDHandler extends AbstractHandler{

	@Override
	public Object execute(ExecutionEvent event) throws ExecutionException {
		
		ISelection selection = HandlerUtil.getCurrentSelection(event);
		IEditorInput input = HandlerUtil.getActiveEditorInput(event);
		IFile file = null;
		if (input != null && input instanceof FileEditorInput) {
			file = ((FileEditorInput) input).getFile();
		} else if (selection !=null && selection instanceof IStructuredSelection) {
			IStructuredSelection structuredSelection = (IStructuredSelection) selection;
			Object firstElement = structuredSelection.getFirstElement();
			if (firstElement instanceof IFile) {
				file = (IFile) firstElement;
			}
		}
		
		if (file !=null) {
			//TODO: copied from translation handler, there has to be a better way.. or at least reused.. 
			URI uri = URI.createPlatformResourceURI(file.getFullPath().toString(), true);
			Injector injector = Guice.createInjector();
			XtextResourceSet resourceSet = injector.getInstance(XtextResourceSet.class);
//			ResourceSet rs = new ResourceSetImpl();
			XtextResourceSet rs = resourceSet;
			Resource r = rs.getResource(uri, true);
			EcoreUtil.resolveAll(r);


			var dialog = new TP2TDDialog(Display.getDefault().getActiveShell());
			// just to demonstrate how to set the title background color
			dialog.setTitleAreaColor(Display.getDefault().getSystemColor(SWT.COLOR_DARK_GRAY).getRGB());
			
			// now open the dialog
			dialog.create();
			if (dialog.open() == Window.OK) {
				//Handle...
				//TODO: encapsulate
				URI targetURI = URI.createURI(uri.toString());
				String ext = targetURI.fileExtension();
				String last = targetURI.trimFileExtension().lastSegment();
				last = dialog.getPrefix() + last + dialog.getSuffix();
				targetURI = targetURI.trimSegments(1).appendSegment(last).appendFileExtension(ext);
//				XtextResourceSet resourceSet = injector.getInstance(XtextResourceSet.class);
//				resourceSet = rs;
				Resource tr = resourceSet.createResource(targetURI);
				tr.getContents().addAll(EcoreUtil.copyAll(r.getContents()));

				processModel(tr, dialog.getPrefix(), dialog.getSuffix(), 
						dialog.isRemoveAnnotations(), dialog.isRemoveAnnotatedBlocks());
				
				//TODO: this also has to be reused
				try {
					EcoreUtil.resolveAll(tr);
//					EcoreUtil2.resolveAll(r, null);
//				    HashMap<Object,Object> options = Maps.newHashMap();
//				    options.put(XtextResource.OPTION_RESOLVE_ALL, true);
					tr.save(null);
				} catch (Exception e1) {
					System.err.println("  Translation: "+e1.getMessage());
					e1.printStackTrace();
					//TODO: provide an error dialog, fall back to XF, indicate approximate location based on error message / details
				}

			}
		}
		
		return null;
	}

	private void processModel(Resource resource, String prefix, String suffix, boolean removeAnnotations, boolean removeAnnotatedBlocks) {
		//update names for all packages
		var packages = EcoreUtil2.eAllOfType(resource.getContents().get(0), Package.class);
		for (var p : packages) {
			p.setName(prefix+p.getName()+suffix);
		}		
		//remove annotations
		if (removeAnnotations) {
			var tds = EcoreUtil2.eAllOfType(resource.getContents().get(0), TestDescription.class);
			for (var td : tds) {
				if (!removeAnnotatedBlocks) {
					//naive approach, clean up blocks as well
					removeElements(td, Annotation.class);
				} else {
					//more sophisticated approach, clean up blocks as well
					var annotations = EcoreUtil2.eAllOfType(td, Annotation.class);
					for (var a : annotations) {
						if (a.getAnnotatedElement() instanceof CompoundBehaviour) {
							var cb = (CompoundBehaviour) a.getAnnotatedElement();
							if (cb.container() instanceof Block) {
								var container = (Block) cb.container();
								var behaviours = cb.getBlock().getBehaviour();
								//TODO: order?
								container.getBehaviour().addAll(behaviours);
								EcoreUtil2.delete(cb, true);
							}
						} else {
							EcoreUtil2.delete(a, true);
						}
					}
				}
				
			}
		}
		
	}
	
	private <T extends Element> void removeElements(Resource tr, Class<T> type) {
		removeElements(tr.getContents().get(0), type);
	}

	private <T extends Element> void removeElements(EObject element, Class<T> type) {
		List<T> elements = EcoreUtil2.eAllOfType(element, type);
		EcoreUtil2.deleteAll(elements, true);
	}

}