com.microsoft.tfs.client.eclipse.ui.actions.ActionHelpers.java Source code

Java tutorial

Introduction

Here is the source code for com.microsoft.tfs.client.eclipse.ui.actions.ActionHelpers.java

Source

// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See License.txt in the repository root.

package com.microsoft.tfs.client.eclipse.ui.actions;

import java.text.MessageFormat;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.widgets.Shell;

import com.microsoft.tfs.client.common.framework.resources.Resources;
import com.microsoft.tfs.client.common.framework.resources.filter.ResourceFilter;
import com.microsoft.tfs.client.common.framework.resources.filter.ResourceFilters;
import com.microsoft.tfs.client.common.repository.TFSRepository;
import com.microsoft.tfs.client.common.ui.framework.helper.MessageBoxHelpers;
import com.microsoft.tfs.client.common.ui.framework.helper.SelectionUtils;
import com.microsoft.tfs.client.common.ui.teamexplorer.helpers.PendingChangesHelpers;
import com.microsoft.tfs.client.common.util.Adapters;
import com.microsoft.tfs.client.eclipse.TFSEclipseClientPlugin;
import com.microsoft.tfs.client.eclipse.repository.ResourceRepositoryMap;
import com.microsoft.tfs.client.eclipse.resource.PluginResourceHelpers;
import com.microsoft.tfs.client.eclipse.ui.Messages;
import com.microsoft.tfs.core.clients.versioncontrol.soapextensions.PendingChange;
import com.microsoft.tfs.jni.FileSystemUtils;
import com.microsoft.tfs.util.Check;

public abstract class ActionHelpers {
    private static final Log log = LogFactory.getLog(ActionHelpers.class);

    /**
     * Calculates this action's current enablement by filtering the current
     * array of resources, returning true if <em>any item</em> is accepted by
     * the filter.
     *
     * @param resources
     *        the resources to filter (must not be <code>null</code>)
     * @param filter
     *        the filter to use (must not be <code>null</code>)
     * @return true if this action should be enabled (the filter accepts
     *         <em>any item</em> in the selection), false if it should not be
     *         enabled (the filter rejects <em>all items</em> in the selection)
     */
    public static boolean filterAcceptsAnyResource(final IResource[] resources, final ResourceFilter filter) {
        for (int i = 0; i < resources.length; i++) {
            if (resources[i] == null) {
                continue;
            }

            if (filter.filter(resources[i]).isAccept()) {
                return true;
            }
        }

        return false;
    }

    /**
     * Calculates this action's current enablement by filtering the current
     * selection, returning true if <em>any item</em> is accepted by the filter.
     *
     * @param selection
     *        the selection to filter (must not be <code>null</code>)
     * @param filter
     *        the filter to use (must not be <code>null</code>)
     * @return true if this action should be enabled (the filter accepts
     *         <em>any item</em> in the selection), false if it should not be
     *         enabled (the filter rejects <em>all items</em> in the selection)
     */
    public static boolean filterAcceptsAnyResource(final ISelection selection, final ResourceFilter filter) {
        if (selection instanceof IStructuredSelection == false) {
            return false;
        }

        final IStructuredSelection ss = (IStructuredSelection) selection;

        /*
         * Adapt each item as we encounter it, so we can filter it directly, and
         * possibly return early in a large selection without adapting every
         * element.
         */

        @SuppressWarnings("rawtypes")
        final Iterator it;

        for (it = ss.iterator(); it.hasNext();) {
            final IResource resource = (IResource) Adapters.getAdapter(it.next(), IResource.class);

            if (resource == null) {
                continue;
            }

            if (filter.filter(resource).isAccept()) {
                return true;
            }
        }

        return false;
    }

    /**
     * <p>
     * Adapts the current selection to a set of different classes which are
     * returned in an {@link AdaptedSelectionInfo}:
     * </p>
     * <p>
     * <ul>
     * <li>The {@link IResource}s that matched the current selection</li>
     * <li>The {@link TFSRepository}s that contain the matched resources</li>
     * <li>The {@link PendingChange}s that belong to the matched resources</li>
     * </ul>
     * </p>
     * <p>
     * Pending change information may be excluded from the results to improve
     * execution speed of this method.
     * </p>
     *
     * @param selection
     *        the selection to adapt (must not be <code>null</code>)
     * @param resourceFilter
     *        the {@link ResourceFilter} to use for filtering {@link IResource}s
     *        (must not be <code>null</code>)
     * @param includePendingChanges
     *        if true, pending change information is included in the info, if
     *        false the pending changes in the info will always be empty
     * @return a new {@link AdaptedSelectionInfo} with the resources that
     *         correspond to this object's current {@link ISelection}
     */
    public static AdaptedSelectionInfo adaptSelectionToStandardResources(final ISelection selection,
            final ResourceFilter resourceFilter, final boolean includePendingChanges) {
        Check.notNull(selection, "selection"); //$NON-NLS-1$
        Check.notNull(resourceFilter, "resourceFilter"); //$NON-NLS-1$

        final long start = System.currentTimeMillis();

        IResource[] resources = (IResource[]) SelectionUtils.adaptSelectionToArray(selection, IResource.class);
        resources = Resources.filter(resources, resourceFilter);

        final ResourceRepositoryMap resourceRepositoryMap = PluginResourceHelpers.mapResources(resources);

        final AdaptedSelectionInfo info = new AdaptedSelectionInfo(resources,
                resourceRepositoryMap.getRepositories(),
                (includePendingChanges) ? resourceRepositoryMap.getPendingChangesMap().getAllChanges()
                        : new PendingChange[0]);

        final String messageFormat = "adapt info took {0} ms"; //$NON-NLS-1$
        final String message = MessageFormat.format(messageFormat, (System.currentTimeMillis() - start));
        log.trace(message);
        return info;
    }

    /**
     * Checks that the given {@link EclipsePluginAction.AdaptedSelectionInfo}
     * contains one or more resources contained in exactly one repository which
     * is online, showing an error message if these conditions are not met.
     *
     * @param info
     *        the {@link EclipsePluginAction.AdaptedSelectionInfo} to check
     *        (must not be <code>null</code>)
     * @param shell
     *        the shell to use to display error dialogs (must not be
     *        <code>null</code>)
     * @return true if the {@link EclipsePluginAction.AdaptedSelectionInfo}
     *         contains one or more resources and exactly one repository, false
     *         otherwise (an error was shown to the user)
     */
    public static boolean ensureNonZeroResourceCountAndSingleRepository(final AdaptedSelectionInfo info,
            final Shell shell) {
        Check.notNull(info, "info"); //$NON-NLS-1$
        Check.notNull(shell, "shell"); //$NON-NLS-1$

        if (info.getResources().length == 0) {
            MessageBoxHelpers.messageBox(shell, Messages.getString("ActionHelpers.NoEligibleResourceDialogTitle"), //$NON-NLS-1$
                    Messages.getString("ActionHelpers.NoEligibleResourceDialogText")); //$NON-NLS-1$

            return false;
        }

        if (info.getRepositories().length == 0) {
            MessageBoxHelpers.messageBox(shell, Messages.getString("ActionHelpers.NoTfsRepositoryDialogTitle"), //$NON-NLS-1$
                    Messages.getString("ActionHelpers.NoTfsRepositoryDialogText")); //$NON-NLS-1$

            return false;
        }

        if (info.getRepositories().length > 1) {
            MessageBoxHelpers.messageBox(shell, Messages.getString("ActionHelpers.MultTfsRepositoriesDialogTitle"), //$NON-NLS-1$
                    Messages.getString("ActionHelpers.MultTfsRepositoriesDialogText")); //$NON-NLS-1$

            return false;
        }

        // TODO check info.getRepositories()[0].isOffline() and error about it

        return true;
    }

    /**
     * Checks that the resources in the given
     * {@link EclipsePluginAction.AdaptedSelectionInfo} reside in exactly one
     * {@link IProject}.
     *
     * @param info
     *        the {@link EclipsePluginAction.AdaptedSelectionInfo} to check
     *        (must not be <code>null</code>)
     * @param shell
     *        the shell to use to display error dialogs (must not be
     *        <code>null</code>)
     * @return true if the {@link EclipsePluginAction.AdaptedSelectionInfo}
     *         contains resources from exactly one {@link IProject}, false
     *         otherwise (an error was shown to the user)
     */
    public static boolean ensureSingleProject(final AdaptedSelectionInfo info, final Shell shell) {
        Check.notNull(info, "info"); //$NON-NLS-1$
        Check.notNull(shell, "shell"); //$NON-NLS-1$

        final IResource[] allResources = info.getResources();

        if (allResources.length == 0) {
            MessageBoxHelpers.messageBox(shell, Messages.getString("ActionHelpers.NoEligibleResourceDialogTitle"), //$NON-NLS-1$
                    Messages.getString("ActionHelpers.NoEligibleResourceDialogText")); //$NON-NLS-1$

            return false;
        }

        /*
         * The workspace root has a null project and we want to error about that
         * case later.
         */
        if (allResources.length == 1 && allResources[0].getProject() != null) {
            return true;
        }

        final IProject firstProject = allResources[0].getProject();

        if (firstProject == null) {
            MessageBoxHelpers.messageBox(shell, Messages.getString("ActionHelpers.NoEligibleResourceDialogTitle"), //$NON-NLS-1$
                    Messages.getString("ActionHelpers.WorkspaceRootCannotBeUsed")); //$NON-NLS-1$
        }

        // Start at the second item
        for (int i = 1; i < allResources.length; i++) {
            if (firstProject.equals(allResources[i].getProject()) == false) {
                MessageBoxHelpers.messageBox(shell, Messages.getString("ActionHelpers.MultProjectsDialogTitle"), //$NON-NLS-1$
                        Messages.getString("ActionHelpers.MultProjectsDialogText")); //$NON-NLS-1$

                return false;
            }
        }

        return true;
    }

    /**
     * Returns the {@link IProject}s that are contained in this selection.
     *
     * @param selection
     *        The selected resources (not <code>null</code>)
     * @return All {@link IProject}s contained by the selection (never
     *         <code>null</code>)
     */
    public static IProject[] getProjectsFromSelection(final ISelection selection) {
        Check.notNull(selection, "selection"); //$NON-NLS-1$

        if (!(selection instanceof IStructuredSelection)) {
            return new IProject[0];
        }

        final Set<IProject> projectSet = new HashSet<IProject>();

        @SuppressWarnings("rawtypes")
        final Iterator i;

        for (i = ((IStructuredSelection) selection).iterator(); i.hasNext();) {
            final IResource resource = (IResource) i.next();

            final IProject project = resource.getProject();

            if (project != null) {
                projectSet.add(project);
            }
        }

        return projectSet.toArray(new IProject[projectSet.size()]);
    }

    /**
     * Gets the {@link TFSRepository}s contained in the selection, if any are
     * connected.
     *
     * @param selection
     *        The selected {@link IResource}s (not <code>null/code>)
     * @return An array of {@link TFSRepository}s containing the selection
     *         (never <code>null</code>)
     */
    public static TFSRepository[] getRepositoriesFromSelection(final ISelection selection) {
        Check.notNull(selection, "selection"); //$NON-NLS-1$

        if (!(selection instanceof IStructuredSelection)) {
            return new TFSRepository[0];
        }

        final Set<TFSRepository> repositorySet = new HashSet<TFSRepository>();

        @SuppressWarnings("rawtypes")
        final Iterator i;

        for (i = ((IStructuredSelection) selection).iterator(); i.hasNext();) {
            final IResource resource = (IResource) i.next();
            final IProject project = resource.getProject();

            if (project != null) {
                final TFSRepository repository = TFSEclipseClientPlugin.getDefault().getProjectManager()
                        .getRepository(project);

                if (repository != null) {
                    repositorySet.add(repository);
                }
            }
        }

        return repositorySet.toArray(new TFSRepository[repositorySet.size()]);
    }

    public static String getFirstSelectedPath(final ISelection selection) {
        final AdaptedSelectionInfo selectionInfo = ActionHelpers.adaptSelectionToStandardResources(selection,
                ResourceFilters.LINKED_RESOURCES_FILTER, false);

        if (selectionInfo == null || selectionInfo.getRepositories() == null
                || selectionInfo.getRepositories().length == 0) {
            return null;
        }

        final IResource resources[] = selectionInfo.getResources();

        if (resources == null || resources.length == 0) {
            return null;
        }

        return resources[0] == null ? null : resources[0].getLocationURI().getPath();
    }

    /**
     * Test whether the selection is symlink
     *
     * @param selection
     * @return
     */
    public static boolean linkSelected(final ISelection selection) {
        final String path = getFirstSelectedPath(selection);
        if (path == null) {
            return false;
        } else {
            return FileSystemUtils.getInstance().getAttributes(path).isSymbolicLink();
        }
    }

    /**
     * Test whether the selection is pending add
     *
     * @param selection
     * @return
     */
    public static boolean pendingAddSelected(final ISelection selection) {
        final AdaptedSelectionInfo selectionInfo = ActionHelpers.adaptSelectionToStandardResources(selection,
                ResourceFilters.LINKED_RESOURCES_FILTER, false);

        if (selectionInfo == null || selectionInfo.getRepositories() == null
                || selectionInfo.getRepositories().length == 0) {
            return false;
        }

        final TFSRepository repository = selectionInfo.getRepositories()[0];

        final String path = getFirstSelectedPath(selection);
        if (path == null || repository == null) {
            return false;
        } else {
            return PendingChangesHelpers.isPendingAdd(repository, path);
        }
    }
}