io.mashin.oep.ui.editor.WorkflowEditor.java Source code

Java tutorial

Introduction

Here is the source code for io.mashin.oep.ui.editor.WorkflowEditor.java

Source

/**
 * Copyright (c) 2015 Mashin (http://mashin.io). All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.mashin.oep.ui.editor;

import io.mashin.oep.figures.NodeFigure;
import io.mashin.oep.hpdl.XMLUtils;
import io.mashin.oep.model.Workflow;
import io.mashin.oep.parts.WorkflowEditPartFactory;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.EventObject;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.gef.DefaultEditDomain;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.KeyHandler;
import org.eclipse.gef.KeyStroke;
import org.eclipse.gef.dnd.TemplateTransferDragSourceListener;
import org.eclipse.gef.dnd.TemplateTransferDropTargetListener;
import org.eclipse.gef.editparts.ScalableFreeformRootEditPart;
import org.eclipse.gef.editparts.ZoomManager;
import org.eclipse.gef.palette.PaletteRoot;
import org.eclipse.gef.requests.CreationFactory;
import org.eclipse.gef.requests.SimpleFactory;
import org.eclipse.gef.ui.actions.ActionRegistry;
import org.eclipse.gef.ui.actions.AlignmentAction;
import org.eclipse.gef.ui.actions.DirectEditAction;
import org.eclipse.gef.ui.actions.GEFActionConstants;
import org.eclipse.gef.ui.actions.ToggleGridAction;
import org.eclipse.gef.ui.actions.ToggleSnapToGeometryAction;
import org.eclipse.gef.ui.actions.ZoomInAction;
import org.eclipse.gef.ui.actions.ZoomOutAction;
import org.eclipse.gef.ui.palette.PaletteViewer;
import org.eclipse.gef.ui.palette.PaletteViewerProvider;
import org.eclipse.gef.ui.parts.GraphicalEditorWithFlyoutPalette;
import org.eclipse.gef.ui.parts.GraphicalViewerKeyHandler;
import org.eclipse.gef.ui.parts.TreeViewer;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.commands.ActionHandler;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.jface.util.TransferDropTargetListener;
import org.eclipse.swt.SWT;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.eclipse.ui.dialogs.SaveAsDialog;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.ide.FileStoreEditorInput;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;

public class WorkflowEditor extends GraphicalEditorWithFlyoutPalette {

    private KeyHandler sharedKeyHandler;
    private Workflow workflow;
    private boolean editorSaving = false;

    OutlinePage outlinePage;

    private PaletteRoot paletteRoot;

    /**
     * This is called by the Workspace.
     */
    public WorkflowEditor() {
        setEditDomain(new DefaultEditDomain(this));
    }

    /**
     * Configure the graphical viewer before it receives contents.
     * <p>
     * This is the place to choose an appropriate RootEditPart and
     * EditPartFactory for your editor. The RootEditPart determines the behavior
     * of the editor's "work-area". For example, GEF includes zoomable and
     * scrollable root edit parts. The EditPartFactory maps model elements to
     * edit parts (controllers).
     * </p>
     */
    protected void configureGraphicalViewer() {
        super.configureGraphicalViewer();

        ScalableFreeformRootEditPart root = new ScalableFreeformRootEditPart();

        GraphicalViewer viewer = getGraphicalViewer();
        viewer.setEditPartFactory(new WorkflowEditPartFactory());
        viewer.setRootEditPart(root);
        viewer.setKeyHandler(new GraphicalViewerKeyHandler(viewer).setParent(getCommonKeyHandler()));

        List<String> zoomLevels = new ArrayList<>(3);
        zoomLevels.add(ZoomManager.FIT_ALL);
        zoomLevels.add(ZoomManager.FIT_WIDTH);
        zoomLevels.add(ZoomManager.FIT_HEIGHT);
        root.getZoomManager().setZoomLevelContributions(zoomLevels);
        root.getZoomManager().setZoomAnimationStyle(ZoomManager.ANIMATE_ZOOM_IN_OUT);

        IAction zoomIn = new ZoomInAction(root.getZoomManager());
        IAction zoomOut = new ZoomOutAction(root.getZoomManager());
        getActionRegistry().registerAction(zoomIn);
        getActionRegistry().registerAction(zoomOut);
        //getSite().getKeyBindingService().registerAction(zoomIn);
        //getSite().getKeyBindingService().registerAction(zoomOut);

        IHandlerService service = (IHandlerService) getEditorSite().getService(IHandlerService.class);
        service.activateHandler(zoomIn.getActionDefinitionId(), new ActionHandler(zoomIn));
        service.activateHandler(zoomOut.getActionDefinitionId(), new ActionHandler(zoomOut));

        IAction snapAction = new ToggleSnapToGeometryAction(getGraphicalViewer());
        getActionRegistry().registerAction(snapAction);

        IAction showGrid = new ToggleGridAction(getGraphicalViewer());
        getActionRegistry().registerAction(showGrid);

        //// configure the context menu provider
        //ContextMenuProvider cmProvider = new ShapesEditorContextMenuProvider(
        //    viewer, getActionRegistry());
        //viewer.setContextMenu(cmProvider);
        //getSite().registerContextMenu(cmProvider, viewer);

        //getSite().setSelectionProvider(viewer);

    }

    /**
     * Returns the KeyHandler with common bindings for both the Outline and
     * Graphical Views. For example, delete is a common action.
     */
    protected KeyHandler getCommonKeyHandler() {
        if (sharedKeyHandler == null) {
            sharedKeyHandler = new KeyHandler();
            sharedKeyHandler.put(KeyStroke.getPressed(SWT.F2, 0),
                    getActionRegistry().getAction(GEFActionConstants.DIRECT_EDIT));
            //sharedKeyHandler.put(
            //    KeyStroke.getPressed(SWT.DEL, 0),
            //    getActionRegistry().getAction(ActionFactory.DELETE.getId()));
        }
        return sharedKeyHandler;
    }

    @Override
    public void commandStackChanged(EventObject event) {
        firePropertyChange(IEditorPart.PROP_DIRTY);
        super.commandStackChanged(event);
    }

    @Override
    protected PaletteViewerProvider createPaletteViewerProvider() {
        return new PaletteViewerProvider(getEditDomain()) {
            protected void configurePaletteViewer(PaletteViewer viewer) {
                super.configurePaletteViewer(viewer);
                // create a drag source listener for this palette viewer
                // together with an appropriate transfer drop target listener,
                // this will enable
                // model element creation by dragging a
                // CombinatedTemplateCreationEntries
                // from the palette into the editor
                // @see ShapesEditor#createTransferDropTargetListener()
                viewer.addDragSourceListener(new TemplateTransferDragSourceListener(viewer));
            }
        };
    }

    @SuppressWarnings("unchecked")
    @Override
    protected void createActions() {
        super.createActions();
        ActionRegistry registry = getActionRegistry();
        IAction action;

        action = new DirectEditAction((IWorkbenchPart) this);
        registry.registerAction(action);
        getSelectionActions().add(action.getId());

        //action = new AlignmentAction((IWorkbenchPart) this,
        //    PositionConstants.LEFT);
        //registry.registerAction(action);
        //getSelectionActions().add(action.getId());

        //action = new AlignmentAction((IWorkbenchPart) this,
        //    PositionConstants.RIGHT);
        //registry.registerAction(action);
        //getSelectionActions().add(action.getId());

        //action = new AlignmentAction((IWorkbenchPart) this,
        //    PositionConstants.TOP);
        //registry.registerAction(action);
        //getSelectionActions().add(action.getId());

        //action = new AlignmentAction((IWorkbenchPart) this,
        //    PositionConstants.BOTTOM);
        //registry.registerAction(action);
        //getSelectionActions().add(action.getId());

        action = new AlignmentAction((IWorkbenchPart) this, PositionConstants.CENTER);
        registry.registerAction(action);
        getSelectionActions().add(action.getId());

        action = new AlignmentAction((IWorkbenchPart) this, PositionConstants.MIDDLE);
        registry.registerAction(action);
        getSelectionActions().add(action.getId());
    }

    /**
     * Create a transfer drop target listener. When using a
     * CombinedTemplateCreationEntry tool in the palette, this will enable model
     * element creation by dragging from the palette.
     * 
     * @see #createPaletteViewerProvider()
     */
    private TransferDropTargetListener createTransferDropTargetListener() {
        return new TemplateTransferDropTargetListener(getGraphicalViewer()) {
            @SuppressWarnings("rawtypes")
            protected CreationFactory getFactory(Object template) {
                return new SimpleFactory((Class) template);
            }
        };
    }

    @Override
    protected PaletteRoot getPaletteRoot() {
        if (paletteRoot == null) {
            paletteRoot = WorkflowEditorPalleteFactory.createPalette(this);
        }
        return paletteRoot;
    }

    Workflow getModel() {
        return this.workflow;
    }

    /**
     * Set up the editor's inital content (after creation).
     */
    protected void initializeGraphicalViewer() {
        super.initializeGraphicalViewer();
        GraphicalViewer viewer = getGraphicalViewer();
        viewer.setContents(getModel()); // set the contents of this editor

        // listen for dropped parts
        viewer.addDropTargetListener(createTransferDropTargetListener());

        getSite().getWorkbenchWindow().getWorkbench().addWorkbenchListener(new IWorkbenchListener() {
            @Override
            public boolean preShutdown(IWorkbench workbench, boolean forced) {
                return true;
            }

            @Override
            public void postShutdown(IWorkbench workbench) {
                NodeFigure.disposeImages();
            }
        });
    }

    @Override
    protected void setInput(IEditorInput input) {
        super.setInput(input);
        BufferedReader br = null;
        String hpdl = "";
        try {

            if (input instanceof FileStoreEditorInput) {

                File file = new File(((FileStoreEditorInput) input).getURI());
                br = new BufferedReader(new FileReader(file));

            } else if (input instanceof IFileEditorInput) {

                IFile file = ((IFileEditorInput) input).getFile();
                br = new BufferedReader(new InputStreamReader(file.getContents()));

            }

            if (br != null) {
                StringBuffer sb = new StringBuffer();
                String line = "";
                while ((line = br.readLine()) != null) {
                    sb.append(line);
                }
                hpdl = sb.toString().trim();
                hpdl = XMLUtils.xmlnsToSchemaVersion(hpdl);
                //hpdl = XMLUtils.xmlnsSLAToSLAVersion(hpdl);

                br.close();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        if (hpdl.isEmpty()) {

            workflow = new Workflow();
            workflow.setName(input.getName());

        } else {

            try {

                SAXReader reader = new SAXReader();
                Document document = reader.read(new StringReader(hpdl));
                //document.accept(new XMLReadUtils.NameSpaceCleaner());

                workflow = new Workflow(document);

            } catch (Exception e) {
                throw new RuntimeException(e);
            }

        }

        setPartName(input.getName());

        if (!editorSaving) {
            if (getGraphicalViewer() != null) {
                getGraphicalViewer().setContents(getModel());
                //loadProperties();
            }
            if (outlinePage != null) {
                outlinePage.setContents(getModel());
            }
        }
    }

    @Override
    public void doSave(IProgressMonitor progressMonitor) {
        editorSaving = true;
        SafeRunner.run(new SafeRunnable() {
            public void run() throws Exception {
                //saveProperties();
                String hpdl = writeModel();

                IEditorInput input = getEditorInput();
                //IFile file = null;

                if (input instanceof FileStoreEditorInput) {

                    //IWorkspace workspace = ResourcesPlugin.getWorkspace();
                    //file = workspace.getRoot().getFile(new Path(((FileStoreEditorInput) input).getURI().getPath()));

                    File file = new File(((FileStoreEditorInput) input).getURI());
                    if (file.canWrite()) {
                        byte[] bytes = hpdl.getBytes();
                        progressMonitor.beginTask("Saving " + file.getAbsolutePath(), bytes.length);
                        FileOutputStream fos = new FileOutputStream(file);
                        for (int i = 0; i < bytes.length; i += 64) {
                            int work = Math.min(64, bytes.length - i);
                            fos.write(bytes, i, work);
                            progressMonitor.worked(work);
                        }
                        fos.flush();
                        fos.close();
                        getCommandStack().markSaveLocation();
                        progressMonitor.done();
                    }

                } else if (input instanceof IFileEditorInput) {

                    IFile file = ((IFileEditorInput) input).getFile();
                    file.setContents(new ByteArrayInputStream(hpdl.getBytes()), true, false, progressMonitor);
                    getCommandStack().markSaveLocation();

                }

                //if (file != null) {
                //  file.setContents(new ByteArrayInputStream(hpdl.getBytes()),
                //      true, false, progressMonitor);
                //  getCommandStack().markSaveLocation();
                //}
            }
        });
        editorSaving = false;
    }

    @Override
    public void doSaveAs() {
        SaveAsDialog dialog = new SaveAsDialog(getSite().getWorkbenchWindow().getShell());

        IEditorInput input = getEditorInput();
        IFile file = null;

        if (input instanceof FileStoreEditorInput) {
            IWorkspace workspace = ResourcesPlugin.getWorkspace();
            file = workspace.getRoot().getFile(new Path(((FileStoreEditorInput) input).getURI().getPath()));
        } else if (input instanceof IFileEditorInput) {
            file = ((IFileEditorInput) input).getFile();
        }

        if (file == null) {
            return;
        }

        dialog.setOriginalFile(file);
        dialog.open();
        IPath path = dialog.getResult();

        if (path == null) {
            return;
        }

        IWorkspace workspace = ResourcesPlugin.getWorkspace();
        final IFile newFile = workspace.getRoot().getFile(path);

        if (!file.exists()) {
            WorkspaceModifyOperation op = new WorkspaceModifyOperation() {
                public void execute(final IProgressMonitor monitor) {
                    //saveProperties();
                    try {
                        String hpdl = writeModel();
                        newFile.create(new ByteArrayInputStream(hpdl.getBytes()), true, monitor);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            };
            try {
                new ProgressMonitorDialog(getSite().getWorkbenchWindow().getShell()).run(false, true, op);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        try {
            superSetInput(new FileEditorInput(newFile));
            getCommandStack().markSaveLocation();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private String writeModel() {
        try {
            Document document = DocumentHelper.createDocument();
            workflow.write(document.addElement("dummy"));
            OutputFormat format = OutputFormat.createPrettyPrint();
            StringWriter stringWriter = new StringWriter();
            XMLWriter writer = new XMLWriter(stringWriter, format);
            writer.write(document);
            stringWriter.flush();
            String hpdl = stringWriter.toString();
            hpdl = XMLUtils.schemaVersionToXmlns(hpdl);
            //hpdl = XMLUtils.slaVersionToXmlnsSLA(hpdl);
            return hpdl;
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }

    protected void superSetInput(IEditorInput input) {
        // The workspace never changes for an editor. So, removing and re-adding
        // the
        // resourceListener is not necessary. But it is being done here for the
        // sake
        // of proper implementation. Plus, the resourceListener needs to be
        // added
        // to the workspace the first time around.
        //if (getEditorInput() != null) {
        //  IFile file = ((IFileEditorInput) getEditorInput()).getFile();
        //  file.getWorkspace().removeResourceChangeListener(resourceListener);
        //}

        super.setInput(input);

        if (getEditorInput() != null) {
            //IFile file = ((IFileEditorInput) getEditorInput()).getFile();
            //file.getWorkspace().addResourceChangeListener(resourceListener);
            setPartName(input.getName());
        }
    }

    @Override
    @SuppressWarnings("rawtypes")
    public Object getAdapter(Class type) {
        if (type == IContentOutlinePage.class) {
            outlinePage = new OutlinePage(new TreeViewer(), this, getActionRegistry(), getEditDomain(),
                    getGraphicalViewer(), getSelectionSynchronizer());
            return outlinePage;
        } else if (type == ZoomManager.class) {
            return getGraphicalViewer().getProperty(ZoomManager.class.toString());
        }
        return super.getAdapter(type);
    }

}