eu.geclipse.ui.internal.actions.DeleteGridElementAction.java Source code

Java tutorial

Introduction

Here is the source code for eu.geclipse.ui.internal.actions.DeleteGridElementAction.java

Source

/******************************************************************************
 * Copyright (c) 2008 g-Eclipse consortium 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Initial development of the original code was made for
 * project g-Eclipse founded by European Union
 * project number: FP6-IST-034327  http://www.geclipse.eu/
 *
 * Contributor(s):
 *     Mariusz Wojtysiak - initial API and implementation
 *     David Johnson (UoR) - added support for deleting JSDLs linked to 
 *                           workflows
 *****************************************************************************/
package eu.geclipse.ui.internal.actions;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.window.IShellProvider;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.DeleteResourceAction;
import org.eclipse.ui.actions.SelectionListenerAction;

import eu.geclipse.core.filesystem.GEclipseFileSystem;
import eu.geclipse.core.model.GridModel;
import eu.geclipse.core.model.IGridConnectionElement;
import eu.geclipse.core.model.IGridContainer;
import eu.geclipse.core.model.IGridElement;
import eu.geclipse.core.model.IGridJob;
import eu.geclipse.core.model.IGridJobDescription;
import eu.geclipse.core.reporting.IProblem;
import eu.geclipse.core.reporting.ISolution;
import eu.geclipse.core.reporting.ProblemException;
import eu.geclipse.ui.dialogs.ProblemDialog;
import eu.geclipse.ui.internal.Activator;
import eu.geclipse.workflow.IGridWorkflowDescription;
import eu.geclipse.workflow.IGridWorkflowJobDescription;

/**
 *
 */
public class DeleteGridElementAction extends SelectionListenerAction {
    Shell shell;
    private DeleteResourceAction eclipseAction;

    protected DeleteGridElementAction(final Shell shell) {
        super(Messages.getString("DeleteGridElementAction.actionNameDelete")); //$NON-NLS-1$

        this.shell = shell;
        this.eclipseAction = new DeleteResourceAction(new IShellProvider() {
            public Shell getShell() {
                return shell;
            }
        });

        ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages();
        ImageDescriptor deleteImage = sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_DELETE);
        setImageDescriptor(deleteImage);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.action.Action#run()
     */
    @Override
    public void run() {
        List<IGridJob> selectedJobs = new ArrayList<IGridJob>(getSelectedResources().size());
        List<IGridJobDescription> selectedWorkflowJobDescriptions = new ArrayList<IGridJobDescription>(
                getSelectedResources().size());
        List<IResource> selectedResources = new ArrayList<IResource>(getSelectedResources().size());
        dispatchSelectedElements(selectedJobs, selectedWorkflowJobDescriptions, selectedResources);
        deactivateConnections(selectedResources.toArray(new IResource[selectedResources.size()]));
        if (!selectedJobs.isEmpty()) {
            deleteJobs(selectedJobs);
        }
        if (!selectedResources.isEmpty()) {
            deleteOtherResources(selectedResources);
        }
        if (!selectedWorkflowJobDescriptions.isEmpty()) {
            deleteWorkflowJobDescriptions(selectedWorkflowJobDescriptions);
        }
    }

    @Override
    protected boolean updateSelection(final IStructuredSelection selection) {
        return !getSelectedResources().isEmpty();
    }

    private void deactivateConnections(final IResource[] resources) {

        if (resources != null) {

            for (IResource resource : resources) {

                IGridElement element = GridModel.getRoot().findElement(resource);

                if (element instanceof IGridConnectionElement) {

                    try {

                        IGridConnectionElement connection = (IGridConnectionElement) element;
                        IFileStore fileStore = connection.getConnectionFileStore();

                        // Deactivate the connection before deleting it in order to avoid
                        // info or child fetching
                        GEclipseFileSystem.setFileStoreActive(fileStore, false, false, false);

                        // Refresh the resource tree in order to remove all cached child
                        // resources that would also cause info fetching
                        resource.refreshLocal(IResource.DEPTH_INFINITE, null);

                    } catch (CoreException cExc) {
                        Activator.logException(cExc);
                    }

                }

                if (resource instanceof IContainer) {
                    try {
                        IResource[] members = ((IContainer) resource).members();
                        deactivateConnections(members);
                    } catch (CoreException cExc) {
                        Activator.logException(cExc);
                    }
                }

            }

        }

    }

    private void dispatchSelectedElements(final List<IGridJob> selectedJobs,
            final List<IGridJobDescription> selectedWorkflowJobDescriptions,
            final List<IResource> otherSelectedResources) {

        for (Object obj : getSelectedResources()) {

            if (obj instanceof IResource) {

                IResource resource = (IResource) obj;
                IGridElement element = GridModel.getRoot().findElement(resource);

                if (element instanceof IGridJob) {
                    selectedJobs.add((IGridJob) element);
                }

                else if (element instanceof IGridJobDescription) {
                    // find out if the parent resource is a workflow
                    IGridContainer parent = element.getParent();
                    if (parent instanceof IGridWorkflowDescription) {
                        boolean inWorkflow = false;
                        List<IGridWorkflowJobDescription> childrenJobs = ((IGridWorkflowDescription) parent)
                                .getChildrenJobs();
                        for (Iterator<IGridWorkflowJobDescription> i = childrenJobs.iterator(); i.hasNext();) {
                            IGridWorkflowJobDescription child = i.next();
                            String childUri = child.getDescriptionPath().toString();
                            String fullPath = element.getResource().getLocation().toString();
                            if (childUri.equals(fullPath)) {
                                inWorkflow = true;
                            }
                        }
                        if (inWorkflow) {
                            selectedWorkflowJobDescriptions.add((IGridJobDescription) element);
                        } else {
                            otherSelectedResources.add(resource);
                        }
                    } else {
                        otherSelectedResources.add(resource);
                    }
                }

                else {
                    otherSelectedResources.add(resource);
                }

            }

        }
    }

    private void deleteOtherResources(final List<IResource> selectedResources) {
        this.eclipseAction.selectionChanged(new StructuredSelection(selectedResources));
        this.eclipseAction.run();
    }

    /*
     * At the moment it only works if workflow is not dirty (i.e. workflow must be saved for
     * it to behave correctly). There is not yet any Problem reporting or Progress monitoring.
     */
    private void deleteWorkflowJobDescriptions(final List<IGridJobDescription> selectedJobDescriptions) {
        MessageDialog dialog = null;
        String dialogMessage = ""; //$NON-NLS-1$
        if (selectedJobDescriptions.size() == 1) {
            IGridJobDescription selectedJobDesc = selectedJobDescriptions.get(0);
            String jsdl = selectedJobDesc.getResource().getName();
            dialogMessage = String.format(Messages.getString("DeleteGridElementAction.confirmJobDescDeleteOne"), //$NON-NLS-1$
                    jsdl);
        } else {
            String jsdlList = ""; //$NON-NLS-1$
            for (Iterator<IGridJobDescription> i = selectedJobDescriptions.iterator(); i.hasNext();) {
                jsdlList = jsdlList + " " + i.next().getResource().getName(); //$NON-NLS-1$
            }
            dialogMessage = String.format(Messages.getString("DeleteGridElementAction.confirmJobDescDeleteMany"), //$NON-NLS-1$
                    jsdlList);
        }
        dialog = new MessageDialog(DeleteGridElementAction.this.shell,
                Messages.getString("DeleteGridElementAction.confirmationTitle"), //$NON-NLS-1$
                null, dialogMessage, MessageDialog.WARNING,
                new String[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL }, 0);

        if (dialog.open() == Window.OK) {
            try {
                for (Iterator<IGridJobDescription> i1 = selectedJobDescriptions.iterator(); i1.hasNext();) {
                    IResource r = i1.next().getResource();
                    r.delete(true, new NullProgressMonitor()); // TODO add a proper progress monitor to use           
                }

            } catch (CoreException e) {
                // TODO Auto-generated catch block, add proper problem reporting
                e.printStackTrace();
            }
        }
    }

    private enum ConfirmChoice {
        /**
         * 
         */
        deleteFromGrid,
        /**
         * 
         */
        deleteOnlyFromWorkspace,
        /**
         * 
         */
        cancel
    }

    private void deleteJobs(final List<IGridJob> selectedJobs) {
        ConfirmChoice choice = confirmDeleteJobs(selectedJobs);

        if (choice != ConfirmChoice.cancel) {
            DeleteJobsJob job = new DeleteJobsJob(selectedJobs, choice);

            job.setUser(true);
            job.schedule();
        }
    }

    private ConfirmChoice confirmDeleteJobs(final List<IGridJob> selectedJobs) {
        ConfirmChoice choice = ConfirmChoice.cancel;
        String question = null, warning = null;

        if (selectedJobs.size() == 1) {
            IGridJob job = selectedJobs.iterator().next();
            question = String.format(Messages.getString("DeleteGridElementAction.confirmationOne"), //$NON-NLS-1$
                    job.getJobName());
            if (job.getJobStatus().canChange()) {
                warning = String.format(Messages.getString("DeleteGridElementAction.warningOne"), job.getJobName()); //$NON-NLS-1$
            }
        } else {
            question = String.format(Messages.getString("DeleteGridElementAction.confirmationMany"), //$NON-NLS-1$
                    Integer.valueOf(selectedJobs.size()));

            for (IGridJob job : selectedJobs) {
                if (job.getJobStatus().canChange()) {
                    warning = Messages.getString("DeleteGridElementAction.warningMany"); //$NON-NLS-1$
                    break;
                }
            }
        }

        String msg = question;

        if (warning != null) {
            msg += "\n\n" + warning; //$NON-NLS-1$
        }

        ConfirmDeleteJobsDialog dialog = new ConfirmDeleteJobsDialog(msg,
                warning == null ? MessageDialog.QUESTION : MessageDialog.WARNING);

        if (dialog.open() == 0) {
            if (dialog.isDeleteFromGrid()) {
                choice = ConfirmChoice.deleteFromGrid;
            } else {
                choice = ConfirmChoice.deleteOnlyFromWorkspace;
            }
        }

        return choice;
    }

    private class ConfirmDeleteJobsDialog extends MessageDialog {
        private Button deleteFromGridCheckbox;
        private boolean deleteFromGrid;

        ConfirmDeleteJobsDialog(final String dialogMessage, final int dialogImageType) {
            super(DeleteGridElementAction.this.shell,
                    Messages.getString("DeleteGridElementAction.confirmationTitle"), //$NON-NLS-1$
                    null, dialogMessage, dialogImageType,
                    new String[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL }, 0);
        }

        /* (non-Javadoc)
         * @see org.eclipse.jface.dialogs.MessageDialog#createCustomArea(org.eclipse.swt.widgets.Composite)
         */
        @Override
        protected Control createCustomArea(final Composite parent) {
            this.deleteFromGridCheckbox = new Button(parent, SWT.CHECK);
            this.deleteFromGridCheckbox.setText(Messages.getString("DeleteGridElementAction.alsoDeleteFromGrid")); //$NON-NLS-1$
            this.deleteFromGridCheckbox.setSelection(true);

            return super.createCustomArea(parent);
        }

        /* (non-Javadoc)
         * @see org.eclipse.jface.dialogs.Dialog#close()
         */
        @Override
        public boolean close() {
            this.deleteFromGrid = this.deleteFromGridCheckbox.getSelection();
            return super.close();
        }

        boolean isDeleteFromGrid() {
            return this.deleteFromGrid;
        }

    }

    private class DeleteJobsJob extends Job {
        boolean forceDeleteLocal = false;
        private List<IGridJob> selectedJobs;
        private ConfirmChoice userChoice;

        /**
         * @param selectedJobs
         * @param userChoice
         */
        public DeleteJobsJob(final List<IGridJob> selectedJobs, final ConfirmChoice userChoice) {
            super(Messages.getString("DeleteGridElementAction.deleteJobName")); //$NON-NLS-1$
            this.selectedJobs = selectedJobs;
            this.userChoice = userChoice;
        }

        @Override
        protected IStatus run(final IProgressMonitor monitor) {
            IStatus status = Status.OK_STATUS;
            SubMonitor submonitor = SubMonitor.convert(monitor);
            submonitor.setWorkRemaining(this.selectedJobs.size());

            try {
                Iterator<IGridJob> iterator = this.selectedJobs.iterator();
                IGridJob job = null;
                while (iterator.hasNext()) {
                    try {
                        testCancel(submonitor);
                        job = iterator.next();

                        deleteJob(submonitor.newChild(1), job);
                        iterator.remove(); // if succesful deleted, then don't delete it again during eventually next try
                    } catch (ProblemException exception) {
                        addSolutionOnlyLocalDel(exception);
                        ProblemDialog.openProblem(DeleteGridElementAction.this.shell,
                                Messages.getString("DeleteGridElementAction.deleteProblemTitle"), //$NON-NLS-1$
                                String.format(Messages.getString("DeleteGridElementAction.problemDescription"), //$NON-NLS-1$
                                        job != null ? job.getJobName() : "unknown"), //$NON-NLS-1$
                                exception);
                        break;
                    }
                }
            } finally {
                submonitor.done();
            }

            return status;
        }

        private void deleteJob(final SubMonitor monitor, final IGridJob job) throws ProblemException {
            monitor.setTaskName(String.format(Messages.getString("DeleteGridElementAction.taskNameDeleting"), //$NON-NLS-1$
                    job.getJobName()));
            monitor.setWorkRemaining(this.userChoice == ConfirmChoice.deleteFromGrid ? 3 : 2);

            stopJobStatusUpdater(job, monitor.newChild(1));

            if (this.userChoice == ConfirmChoice.deleteFromGrid) {
                try {
                    job.deleteJob(monitor.newChild(1));
                } catch (ProblemException exception) {
                    if (this.forceDeleteLocal) {
                        Activator.logException(exception);
                    } else {
                        throw exception;
                    }
                }
            }

            try {
                testCancel(monitor);
                job.getResource().delete(true, monitor.newChild(1));
            } catch (CoreException exception) {
                throw new ProblemException("eu.geclipse.problem.deleteGridElementAction.cannotDeleteResource", //$NON-NLS-1$
                        exception, Activator.PLUGIN_ID);
            }
        }

        private void stopJobStatusUpdater(final IGridJob job, final SubMonitor monitor) {
            monitor.subTask(Messages.getString("DeleteGridElementAction.taskStoppingUpdater")); //$NON-NLS-1$
            GridModel.getJobManager().removeJobStatusUpdater(job, true, monitor);
        }

        private void testCancel(final IProgressMonitor monitor) {
            if (monitor.isCanceled()) {
                throw new OperationCanceledException();
            }
        }

        void addSolutionOnlyLocalDel(final ProblemException exception) {
            if (this.userChoice == ConfirmChoice.deleteFromGrid && !this.forceDeleteLocal) {
                IProblem problem = exception.getProblem();
                problem.addSolution(new ISolution() {

                    public String getDescription() {
                        return Messages.getString("DeleteGridElementAction.forceDeleteLocal"); //$NON-NLS-1$
                    }

                    public String getID() {
                        return null;
                    }

                    public boolean isActive() {
                        return true;
                    }

                    public void solve() throws InvocationTargetException {
                        DeleteJobsJob.this.forceDeleteLocal = true;
                        DeleteJobsJob.this.schedule();
                    }
                });
            }

        }

    }

}