es.uah.aut.srg.micobs.ui.handlers.UpdateRemoteFoldersHandler.java Source code

Java tutorial

Introduction

Here is the source code for es.uah.aut.srg.micobs.ui.handlers.UpdateRemoteFoldersHandler.java

Source

/*******************************************************************************
 * Copyright (c) 2013-2015 UAH Space Research Group.
 * 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
 *
 * Contributors:
 *     MICOBS SRG Team - Initial API and implementation
 ******************************************************************************/
package es.uah.aut.srg.micobs.ui.handlers;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.ui.dialogs.DiagnosticDialog;
import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.handlers.HandlerUtil;

import es.uah.aut.srg.micobs.diagnostic.CheckingDiagnostic;
import es.uah.aut.srg.micobs.plugin.MICOBSPlugin;
import es.uah.aut.srg.micobs.util.impl.MICOBSUtilProvider;
import es.uah.aut.srg.modeling.util.plugin.ModelingUtilPlugin;
import es.uah.aut.srg.modeling.util.svn.SVNUtil;

/**
 * Class used to implement a handler that updates the SVN externals attribute
 * of a set of folders. The handler will first check the file that
 * triggers the generation, then will ask the user to confirm the operation,
 * then will unlink the previous SVN externals attributes of the folders,
 * and then will update the new SVN externals.
 * 
 * The classes that implement this will have to provide the following:
 * 
 * <ul>
 *       <li>The root class of the triggering model file.</li>
 *       <li>The item provider adapter factory corresponding to the model file.</li>
 *       <li>The message for the user confirmation dialog.</li>
 *       <li>The error message in case the checking of the triggering model
 *          fails.</li>
 *       <li>The list of resources to erase after the confirmation.</li>
 *       <li>The list of mappings between the folders and their new SVN external
 *          attributes.</li>
 * </ul>
 *
 * All the updating process is executed synchronously by the GUI thread.
 *
 */
public abstract class UpdateRemoteFoldersHandler extends AbstractHandler {

    /**
     * Returns the message of the user confirmation dialog.
     * @return the message of the user confirmation dialog.
     */
    protected abstract String getConfirmDialogMessage();

    /**
     * Returns the message string of the error that is generated if the
     * name of the folder that contains the triggering model file does not
     * match with the standard name.
     * @return the message string of the error.
     */
    protected String getModelFolderErrorMessage() {
        return MICOBSPlugin.INSTANCE.getString("_UI_Handlers_ModelFolderError_message");
    }

    /**
     * Returns the message string of the error that is generated if the root
     * class of the triggering model file is not the expected one.
     * @return the message string of the error.
     */
    protected abstract String getModelClassErrorMessage();

    /**
     * Returns an array with the folders whose SVN externals attribute shall be
     * erased prior to the update.
     * 
     * @param rootFolder the root folder of the project that contains the triggering
     *                   model file. 
     * @param model the root object of the triggering model file.
     * @return the array of folders.
     */
    protected abstract IFolder[] getFoldersToUnlink(IContainer rootFolder, EObject model);

    /**
     * Returns the list of mappings between the folders and their new values of
     * the SVN externals attributes. This list is passed as a parameter and shall
     * be filled by the method. Each element of the list corresponds to one folder
     * and the order shall be the same as the one returned by the
     * {@link #getFoldersToUnlink(IContainer, EObject)} method. Each map should
     * contain the local name of the external remote folder and the URL.
     * 
     * @param rootFolder the root folder of the project that contains the triggering
     *                   model file. 
     * @param model the root object of the triggering model file.
     * @param itemList the list of mapping items.
     * @return an object with the diagnosis of the generation of the mapping
     *          items.
     */
    protected abstract Diagnostic getNewMappingLists(IContainer rootFolder, EObject model,
            List<Map<String, String>> itemList);

    /**
     * Returns the standard MICOBS models folder name.
     * @param model the root object of the triggering model file.
     * @return the standard MICOBS models folder name.
     */
    protected String getModelFolderName() {
        return MICOBSPlugin.INSTANCE.getString("_MICOBSProject_models_foldername");
    };

    /**
     * Returns the {@link EClass} object corresponding to the root class of the
     * triggering model file.
     * @return the {@link EClass} object.
     */
    protected abstract EClass getModelEClass();

    /**
     * Returns the item provider adapter factory of the triggering model file.
     * @return the item provider adapter factory of the triggering model file.
     */
    protected abstract AdapterFactory getItemProviderAdapterFactory();

    protected Shell shell;

    @Override
    public Object execute(ExecutionEvent event) throws ExecutionException {

        ISelection selection = HandlerUtil.getCurrentSelection(event);

        if (selection instanceof IStructuredSelection) {
            final Object object = ((IStructuredSelection) selection).getFirstElement();
            if (object instanceof IResource) {
                shell = HandlerUtil.getActiveShell(event);
                final IRunnableContext context = new ProgressMonitorDialog(shell);
                final Exception except[] = new Exception[1];

                // First we obtain the model folder
                final IContainer modelFolder = ((IResource) object).getParent();

                if (!modelFolder.getName().equals(getModelFolderName())) {
                    MessageDialog.openError(shell,
                            MICOBSPlugin.INSTANCE
                                    .getString("_UI_UpdateResourcesHandler_ModelFolderNameMismatch_dialogTitle"),
                            getModelFolderErrorMessage());
                    return null;
                }

                final IContainer rootFolder = modelFolder.getParent();

                ResourceSet resourceSet = new ResourceSetImpl();
                Resource resource = resourceSet.getResource(
                        URI.createPlatformResourceURI(((IResource) object).getFullPath().toString(), true), true);

                final EObject model = resource.getContents().get(0);

                if (model.eClass() != getModelEClass()) {
                    MessageDialog.openError(shell,
                            MICOBSPlugin.INSTANCE
                                    .getString("_UI_UpdateResourcesHandler_ModelClassMismatch_dialogTitle"),
                            getModelClassErrorMessage());
                    return null;
                }

                Diagnostic diagnostic = MICOBSUtilProvider.getMICOBSUtil().validateResource(resource,
                        getItemProviderAdapterFactory());

                if (diagnostic.getSeverity() != Diagnostic.OK) {
                    handleDiagnostic(diagnostic);
                    return null;
                }

                if (!MessageDialog.openQuestion(shell,
                        MICOBSPlugin.INSTANCE.getString("_UI_UpdateResourcesHandler_ConfirmOperation_dialogTitle"),
                        getConfirmDialogMessage())) {
                    return null;
                }

                final BasicDiagnostic runningDiagnostics = new BasicDiagnostic(
                        MICOBSPlugin.INSTANCE.getSymbolicName(), 0, "Update Resources Handler", null);

                // Now that we have the OK and the model is fine, we can start
                // the action!

                shell.getDisplay().syncExec(new Runnable() {

                    @Override
                    public void run() {

                        try {
                            context.run(false, true, new IRunnableWithProgress() {

                                @Override
                                public void run(IProgressMonitor monitor)
                                        throws InvocationTargetException, InterruptedException {

                                    monitor.beginTask(MICOBSPlugin.INSTANCE
                                            .getString("_UI_UpdateResourcesHandler_Task_message"), 100);

                                    IFolder[] folders = getFoldersToUnlink(rootFolder, model);
                                    List<Map<String, String>> itemList = new ArrayList<Map<String, String>>();
                                    Diagnostic diag = getNewMappingLists(rootFolder, model, itemList);
                                    if (diag != null) {
                                        runningDiagnostics.add(diag);
                                    }
                                    if (runningDiagnostics.getSeverity() != Diagnostic.OK) {
                                        return;
                                    }

                                    if (folders.length == 0 || itemList.size() == 0) {
                                        return;
                                    }

                                    int step = (100 + folders.length - 1) / folders.length;

                                    for (int i = 0; i < folders.length; i++) {
                                        monitor.subTask(MICOBSPlugin.INSTANCE.getString(
                                                "_UI_UpdateResourcesHandler_UpdatingFolderSubTask_message",
                                                new Object[] { folders[i].getName() }));
                                        if (folders[i].exists() == false) {
                                            runningDiagnostics.add(CheckingDiagnostic.createError(
                                                    "Folder " + folders[i].getName() + " does not exist"));
                                            continue;
                                        }
                                        Collection<String> foldersToErase = new HashSet<String>();
                                        Map<String, String> oldItems = SVNUtil.getExternalItems(folders[i]);
                                        for (Iterator<String> m = oldItems.keySet().iterator(); m.hasNext();) {
                                            String key = m.next();
                                            if (!itemList.get(i).containsKey(key)) {
                                                // This means that it was a
                                                // linked resource that is no more
                                                foldersToErase.add(key);
                                            }
                                        }

                                        // Now we have to clean the externals
                                        SVNUtil.setExternalItems(folders[i], itemList.get(i));
                                        SVNUtil.updateResources(new IResource[] { folders[i] });
                                        monitor.worked(step / 2);

                                        // Now it's cleaned.. we have to erase
                                        // foldersToErase
                                        monitor.subTask(MICOBSPlugin.INSTANCE
                                                .getString("_UI_UpdateResourcesHandler_ErasingSubTask_message"));
                                        for (Iterator<String> f = foldersToErase.iterator(); f.hasNext();) {
                                            String erase = f.next();
                                            IFolder eraseFolder = folders[i].getFolder(new Path(erase));
                                            if (eraseFolder.exists()) {
                                                try {
                                                    eraseFolder.delete(true, new NullProgressMonitor());
                                                } catch (CoreException e) {
                                                    throw new InvocationTargetException(e);
                                                }
                                            }
                                        }
                                        monitor.worked(step / 2);
                                        if (monitor.isCanceled()) {
                                            return;
                                        }
                                    }

                                    try {
                                        ((IResource) object).getProject().refreshLocal(IProject.DEPTH_INFINITE,
                                                new NullProgressMonitor());
                                    } catch (CoreException e) {
                                        throw new InvocationTargetException(e);
                                    }

                                    monitor.done();

                                }
                            });
                        } catch (InvocationTargetException e) {
                            except[0] = e;
                        } catch (InterruptedException e) {
                            except[0] = e;
                        }
                    }
                });

                if (except[0] != null) {
                    MICOBSPlugin.INSTANCE.log(except[0]);
                    return null;
                }

                if (runningDiagnostics.getSeverity() != Diagnostic.OK) {
                    handleDiagnostic(runningDiagnostics);
                    return null;
                }
            }
        }
        return null;
    }

    /**
     * Handles the diagnostic of the triggering model file in case an error
     * is detected when triggering the transformation. This function will
     * display a diagnostic dialog in case an error or a warning is
     * encountered.
     * @param diagnostic the resulting diagnostic of the triggering model
     *                 check.
     */
    protected void handleDiagnostic(Diagnostic diagnostic) {
        int severity = diagnostic.getSeverity();
        String title = null;
        String message = null;

        if (severity == Diagnostic.ERROR || severity == Diagnostic.WARNING) {
            title = ModelingUtilPlugin.getString("_UI_ValidationProblems_title");
            message = ModelingUtilPlugin.getString("_UI_ValidationProblems_message");
        } else {
            title = ModelingUtilPlugin.getString("_UI_ValidationResults_title");
            message = ModelingUtilPlugin.getString(
                    severity == Diagnostic.OK ? "_UI_ValidationOK_message" : "_UI_ValidationResults_message");
        }

        if (diagnostic.getSeverity() == Diagnostic.OK) {
            MessageDialog.openInformation(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), title,
                    message);
        } else {
            DiagnosticDialog.open(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), title, message,
                    diagnostic);
        }
    }

}