org.xmind.ui.internal.e4handlers.SaveWorkbookAsHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.xmind.ui.internal.e4handlers.SaveWorkbookAsHandler.java

Source

/* ******************************************************************************
 * Copyright (c) 2006-2016 XMind Ltd. and others.
 * 
 * This file is a part of XMind 3. XMind releases 3 and
 * above are dual-licensed under the Eclipse Public License (EPL),
 * which is available at http://www.eclipse.org/legal/epl-v10.html
 * and the GNU Lesser General Public License (LGPL), 
 * which is available at http://www.gnu.org/licenses/lgpl.html
 * See http://www.xmind.net/license.html for details.
 * 
 * Contributors:
 *     XMind Ltd. - initial API and implementation
 *******************************************************************************/
/**
 * 
 */
package org.xmind.ui.internal.e4handlers;

import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import javax.inject.Named;

import org.eclipse.core.expressions.IEvaluationContext;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.ui.services.IServiceConstants;
import org.eclipse.jface.dialogs.IDialogConstants;
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.preference.IPreferenceStore;
import org.eclipse.jface.viewers.IFilter;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.progress.IProgressService;
import org.eclipse.ui.services.IEvaluationService;
import org.eclipse.ui.services.IServiceLocator;
import org.xmind.core.Core;
import org.xmind.core.CoreException;
import org.xmind.core.IWorkbook;
import org.xmind.gef.ui.editor.IEditable;
import org.xmind.ui.internal.MindMapMessages;
import org.xmind.ui.internal.MindMapUIPlugin;
import org.xmind.ui.internal.dialogs.SaveWizardDialog;
import org.xmind.ui.internal.editor.DecryptionDialog;
import org.xmind.ui.internal.editor.IEncryptable;
import org.xmind.ui.internal.editor.SaveWizardManager.SaveWizardDescriptor;
import org.xmind.ui.mindmap.IWorkbookRef;
import org.xmind.ui.mindmap.IWorkbookRefFactory;
import org.xmind.ui.prefs.PrefConstants;
import org.xmind.ui.wizards.ISaveContext;
import org.xmind.ui.wizards.ISaveWizard;
import org.xmind.ui.wizards.ISaveWizard.SaveWizardNotAvailable;
import org.xmind.ui.wizards.SaveOptions;

/**
 * @author Frank Shaka
 * @since 3.6.50
 */
public class SaveWorkbookAsHandler {

    @Execute
    public void execute(@Named(IServiceConstants.ACTIVE_SELECTION) Object selection,
            @Optional IProgressService progressProvider, final @Optional IServiceLocator serviceLocator)
            throws InvocationTargetException {
        if (selection instanceof IStructuredSelection) {
            selection = ((IStructuredSelection) selection).getFirstElement();
        }
        if (selection instanceof IWorkbookRef) {
            saveWorkbookAs(new ISaveContext() {
                @Override
                public Object getContextVariable(String key) {
                    IEvaluationService service = serviceLocator.getService(IEvaluationService.class);
                    Assert.isNotNull(service);
                    Object variable = service.getCurrentState().getVariable(key);
                    return variable == IEvaluationContext.UNDEFINED_VARIABLE ? null : variable;
                }

                @Override
                public <T> T getContextVariable(Class<T> key) {
                    return serviceLocator.getService(key);
                }
            }, (IWorkbookRef) selection, progressProvider, null, false);
        }
    }

    /**
     * @param context
     *            the context where this operation happens
     * @param workbookRef
     *            the source workbook ref to be saved
     * @param runner
     *            an {@link IRunnableContext} to run the job
     * @param optionFilter
     *            <code>null</code> to accept all options at beginning, or an
     *            {@link IFilter} instance that selects available option ids
     * @param onlyToLocal
     *            is only save to local
     * @return a new workbook ref that is filled with contents from the source
     *         workbook ref
     * @throws InvocationTargetException
     */
    public static IWorkbookRef saveWorkbookAs(ISaveContext context, final IWorkbookRef workbookRef,
            IRunnableContext runner, IFilter optionFilter, boolean onlyToLocal) throws InvocationTargetException {
        Assert.isLegal(context != null);

        Shell shell = context.getContextVariable(Shell.class);

        // list all available location options
        List<SaveWizardDescriptor> wizards = MindMapUIPlugin.getDefault().getSaveWizardManager().getWizards();
        if (wizards.isEmpty()) {
            // no location options available....
            // should not happen?
            // no need to extract strings
            MessageDialog.openWarning(shell, "Save As", //$NON-NLS-1$
                    "No 'Save As' options available in this application. " //$NON-NLS-1$
                            + "Please contact the software provider for this issue."); //$NON-NLS-1$
            return null;
        }

        // make a new array so that we can remove unavailable ones
        wizards = new ArrayList<SaveWizardDescriptor>(wizards);
        if (optionFilter != null) {
            Iterator<SaveWizardDescriptor> locationProviderIt = wizards.iterator();
            while (locationProviderIt.hasNext()) {
                SaveWizardDescriptor locationProvider = locationProviderIt.next();
                if (!optionFilter.select(locationProvider.getId())) {
                    locationProviderIt.remove();
                }
            }
        }

        sortLocationProviders(wizards);

        // ensure runnable context available
        if (runner == null) {
            runner = new ProgressMonitorDialog(shell);
        }

        // prepare save options
        String oldName = workbookRef.getName();
        if (oldName == null) {
            IWorkbook workbook = workbookRef.getWorkbook();
            if (workbook != null) {
                oldName = workbook.getPrimarySheet().getRootTopic().getTitleText();
            }
            if (oldName == null)
                oldName = MindMapMessages.SaveWorkbookAsHandler_oldName_default;
        }

        while (true) {
            if (wizards.isEmpty()) {
                // tried out all possible location options....
                // should not happen?
                // no need to extract strings
                MessageDialog.openError(shell, "Save As", //$NON-NLS-1$
                        "No 'Save As' options available now for this workbook. " //$NON-NLS-1$
                                + "Please contact the software provider for this issue."); //$NON-NLS-1$
                return null;
            }

            SaveOptions options = SaveOptions.getDefault() //
                    .proposalName(oldName) //
                    .oldURI(workbookRef.getURI());

            SaveWizardDescriptor wizard;
            if (onlyToLocal || wizards.size() == 1) {
                wizard = wizards.get(0);
            } else {
                String oldWizardId = workbookRef.getSaveWizardId();
                SaveWizardDescriptor defaultWizard = oldWizardId == null ? null
                        : findSaveWizard(wizards, oldWizardId, false);
                if (defaultWizard == null) {
                    int maxPriority = 0;
                    for (SaveWizardDescriptor wizardDescriptor : wizards) {
                        /// sort by priority
                        /// choose highest priority
                        /// exclude those whose priority < 0
                        int priority = wizardDescriptor.getWizard().getPriorityFor(context, options);
                        if (priority > maxPriority) {
                            maxPriority = priority;
                            defaultWizard = wizardDescriptor;
                        }
                        if (priority < 0)
                            wizards.remove(wizardDescriptor);
                    }

                }
                if (defaultWizard == null) {
                    defaultWizard = wizards.get(0);
                }
                SaveWizardDialog dialog = new SaveWizardDialog(shell, wizards, defaultWizard, options);
                if (dialog.open() != SaveWizardDialog.OK)
                    // canceled
                    return null;

                wizard = dialog.getTargetWizard();
                options = dialog.getTargetOptions();
            }

            ISaveWizard wizardImpl = wizard.getWizard();
            Assert.isNotNull(wizardImpl);

            URI newURI;
            try {
                newURI = wizardImpl.askForTargetURI(context, options);
            } catch (SaveWizardNotAvailable na) {

                wizards.remove(wizard);

                String saveText;
                if (wizards.size() == 0) {
                    MessageDialog.openInformation(shell, "No options", //$NON-NLS-1$
                            na.getMessage());
                    return null;
                } else if (wizards.size() == 1) {
                    saveText = NLS.bind(MindMapMessages.SaveWorkbookAsHandler_saveToOtherDialog_saveTo_text,
                            wizards.get(0).getName());
                } else {
                    saveText = MindMapMessages.SaveWorkbookAsHandler_saveToOtherDialog_saveToAnother_text;
                }

                MessageDialog dialog = new MessageDialog(

                        shell,

                        MindMapMessages.SaveWorkbookAsHandler_saveToOtherDialog_title,

                        null,

                        na.getMessage(),

                        MessageDialog.CONFIRM,

                        new String[] {

                                saveText,

                                IDialogConstants.CANCEL_LABEL

                        }, 0

                );

                if (dialog.open() != MessageDialog.OK)
                    return null;

                continue;
            }
            if (newURI == null)
                // canceled
                return null;

            IWorkbookRefFactory workbookRefFactory = MindMapUIPlugin.getDefault().getWorkbookRefFactory();
            final IWorkbookRef newWorkbookRef = workbookRefFactory.createWorkbookRef(newURI, null);
            Assert.isNotNull(newWorkbookRef);
            if (!newWorkbookRef.isInState(IEditable.CLOSED)) {
                MessageDialog.openWarning(shell, MindMapMessages.SaveWorkbookAsHandler_warningDialog_title,
                        MindMapMessages.SaveWorkbookAsHandler_warningDialog_description);
                continue;
            }

            newWorkbookRef.setActiveContext(workbookRef.getActiveContext());

            if (newWorkbookRef.equals(workbookRef)) {
                // same location
                // just save the old workbook ref
                if (!workbookRef.isInState(IWorkbookRef.CLOSED)) {
                    try {
                        runner.run(true, true, new IRunnableWithProgress() {
                            @Override
                            public void run(IProgressMonitor monitor)
                                    throws InvocationTargetException, InterruptedException {
                                workbookRef.save(monitor);
                            }
                        });
                    } catch (InterruptedException e) {
                        // canceled
                        return null;
                    }
                }
                return newWorkbookRef;
            }

            if (!newWorkbookRef.canImportFrom(workbookRef)) {
                MessageDialog.openError(shell, MindMapMessages.SaveWorkbookAsHandler_saveAsDialog_title,
                        MindMapMessages.SaveWorkbookAsHandler_saveAsDialog_description);
                wizards.remove(wizard);
                continue;
            }

            try {
                runner.run(true, true, new IRunnableWithProgress() {
                    public void run(IProgressMonitor monitor)
                            throws InvocationTargetException, InterruptedException {
                        doSaveAs(monitor, workbookRef, newWorkbookRef, 0);
                    }
                });
            } catch (InterruptedException e) {
                // canceled
                return null;
            }

            // should return here in normal cases
            return newWorkbookRef;
        }
    }

    private static void doSaveAs(final IProgressMonitor monitor, final IWorkbookRef oldWorkbookRef,
            final IWorkbookRef newWorkbookRef, int times) {
        SubMonitor subMonitor = SubMonitor.convert(monitor, 100);
        try {
            oldWorkbookRef.open(subMonitor.newChild(15));
            newWorkbookRef.importFrom(subMonitor.newChild(80), oldWorkbookRef);
        } catch (final InvocationTargetException e) {
            CoreException coreEx = getCoreException(e);
            if (coreEx != null) {
                int errType = coreEx.getType();
                if (errType == Core.ERROR_WRONG_PASSWORD) {
                    openDecryptionDialog(oldWorkbookRef, newWorkbookRef, monitor,
                            MindMapMessages.MindMapEditor_passwordPrompt_message2, times);
                    return;
                }
                return;
            }
        } catch (InterruptedException e) {
            return;
        } finally {
            subMonitor.setWorkRemaining(5);
            try {
                oldWorkbookRef.close(subMonitor.newChild(5));
            } catch (InvocationTargetException e) {
            } catch (InterruptedException e) {
            }
        }
    }

    private static CoreException getCoreException(Throwable e) {
        if (e == null)
            return null;
        if (e instanceof CoreException)
            return (CoreException) e;
        return getCoreException(e.getCause());
    }

    private static void openDecryptionDialog(final IWorkbookRef oldWorkbookRef, final IWorkbookRef newWorkbookRef,
            final IProgressMonitor monitor, String message, final int times) {
        final int nextTime = times + 1;
        final IEncryptable encryptable = oldWorkbookRef.getAdapter(IEncryptable.class);

        Display.getDefault().asyncExec(new Runnable() {

            public void run() {
                new DecryptionDialog(Display.getDefault().getActiveShell(), oldWorkbookRef.getName(),
                        encryptable.getPasswordHint(), times) {
                    protected void okPressed() {
                        super.okPressed();

                        encryptable.setPassword(getPassword());
                        doSaveAs(monitor, oldWorkbookRef, newWorkbookRef, nextTime);
                    };

                    protected void cancelPressed() {
                        super.cancelPressed();
                    };
                }.open();

            }
        });
    }

    private static void sortLocationProviders(List<SaveWizardDescriptor> list) {
        IPreferenceStore pref = MindMapUIPlugin.getDefault().getPreferenceStore();
        List<SaveWizardDescriptor> preferredWizards = new ArrayList<SaveWizardDescriptor>();
        List<SaveWizardDescriptor> nameSortedWizards = new ArrayList<SaveWizardDescriptor>();

        String[] preferredWizardIds = getPreferredSaveWizardIds(pref);
        if (preferredWizardIds != null) {
            for (String wizardId : preferredWizardIds) {
                SaveWizardDescriptor wizard = findSaveWizard(list, wizardId, true);
                if (wizard != null) {
                    preferredWizards.add(wizard);
                }
            }
        }

        nameSortedWizards.addAll(list);
        if (!nameSortedWizards.isEmpty()) {
            Collections.sort(nameSortedWizards, new Comparator<SaveWizardDescriptor>() {
                @Override
                public int compare(SaveWizardDescriptor w1, SaveWizardDescriptor w2) {
                    return w1.getName().compareTo(w2.getName());
                }
            });
        }

        list.clear();
        list.addAll(preferredWizards);
        list.addAll(nameSortedWizards);
    }

    /**
     * @param list
     * @param id
     * @param remove
     * @return
     */
    private static SaveWizardDescriptor findSaveWizard(List<SaveWizardDescriptor> list, String id, boolean remove) {
        Iterator<SaveWizardDescriptor> it = list.iterator();
        while (it.hasNext()) {
            SaveWizardDescriptor wizard = it.next();
            if (id.equals(wizard.getId())) {
                if (remove)
                    it.remove();
                return wizard;
            }
        }
        return null;
    }

    private static String[] getPreferredSaveWizardIds(IPreferenceStore pref) {
        String preferredWizardIds = pref.getString(PrefConstants.SAVE_WIZARDS);
        if (preferredWizardIds != null && !"".equals(preferredWizardIds)) { //$NON-NLS-1$
            return preferredWizardIds.split(","); //$NON-NLS-1$
        }
        return null;
    }

}