org.community.intellij.plugins.communitycase.actions.RepositoryAction.java Source code

Java tutorial

Introduction

Here is the source code for org.community.intellij.plugins.communitycase.actions.RepositoryAction.java

Source

/*
 * Copyright 2000-2009 JetBrains s.r.o.
 *
 * 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 org.community.intellij.plugins.communitycase.actions;

import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vcs.AbstractVcsHelper;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.TransactionRunnable;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vfs.VirtualFile;
import org.community.intellij.plugins.communitycase.Util;
import org.community.intellij.plugins.communitycase.Vcs;
import org.community.intellij.plugins.communitycase.i18n.Bundle;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Base class for actions that affect the entire repository.
 * The action is available if there is at least one root.
 */
public abstract class RepositoryAction extends DumbAwareAction {
    /**
     * The task delayed until end of the primary action. These tasks happen after repository refresh.
     */
    final List<TransactionRunnable> myDelayedTasks = new ArrayList<TransactionRunnable>();

    protected RepositoryAction() {
    }

    protected RepositoryAction(String text) {
        super(text);
    }

    protected RepositoryAction(String text, String description, Icon icon) {
        super(text, description, icon);
    }

    /**
     * {@inheritDoc}
     */
    public void actionPerformed(final AnActionEvent e) {
        myDelayedTasks.clear();
        ApplicationManager.getApplication().runWriteAction(new Runnable() {
            public void run() {
                FileDocumentManager.getInstance().saveAllDocuments();
            }
        });
        DataContext dataContext = e.getDataContext();
        final Project project = PlatformDataKeys.PROJECT.getData(dataContext);
        if (project == null) {
            return;
        }
        Vcs vcs = Vcs.getInstance(project);
        final List<VirtualFile> roots = getRoots(project, vcs);
        if (roots == null)
            return;
        // get default root
        final VirtualFile[] vFiles = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY);
        VirtualFile defaultRootVar = null;
        if (vFiles != null) {
            for (VirtualFile file : vFiles) {
                final VirtualFile root = Util.rootOrNull(file);
                if (root != null) {
                    defaultRootVar = root;
                    break;
                }
            }
        }
        if (defaultRootVar == null) {
            defaultRootVar = roots.get(0);
        }
        final VirtualFile defaultRoot = defaultRootVar;
        final Set<VirtualFile> affectedRoots = new HashSet<VirtualFile>();
        String actionName = getActionName();
        AbstractVcsHelper helper = AbstractVcsHelper.getInstance(project);
        //Runs the runnable inside the vcs transaction (if needed), collects all exceptions, commits/rollbacks transaction and returns all exceptions together.
        List<VcsException> exceptions = helper.runTransactionRunnable(vcs, new TransactionRunnable() {
            public void run(List<VcsException> exceptions) {
                //noinspection unchecked
                try {
                    perform(project, roots, defaultRoot, affectedRoots, exceptions);
                } catch (VcsException e) {
                    exceptions.add(e);
                }
                Util.refreshFiles(project, affectedRoots);
                for (TransactionRunnable task : myDelayedTasks) {
                    task.run(exceptions);
                }
            }
        }, null);
        myDelayedTasks.clear();
        vcs.showErrors(exceptions, actionName);
    }

    /**
     * Get roots for the project. The method shows dialogs in the case when roots cannot be retrieved, so it should be called
     * from the event dispatch thread.
     *
     * @param project the project
     * @param vcs     the Vcs
     * @return the list of the roots, or null
     */
    @Nullable
    public static List<VirtualFile> getRoots(Project project, Vcs vcs) {
        List<VirtualFile> roots;
        try {
            roots = Util.getRoots(project, vcs);
        } catch (VcsException e) {
            Messages.showErrorDialog(project, e.getMessage(),
                    Bundle.getString("repository.action.missing.roots.title"));
            return null;
        }
        return roots;
    }

    /**
     * Delay task to be executed after refresh
     *
     * @param task the task to run
     */
    public final void delayTask(@NotNull TransactionRunnable task) {
        myDelayedTasks.add(task);
    }

    /**
     * Get name of action (for error reporting)
     *
     * @return the name of action
     */
    @NotNull
    protected abstract String getActionName();

    /**
     * Perform action for some repositories
     *
     * @param project       a context project
     * @param Roots      a roots that affect the current project (sorted by {@link VirtualFile#getPresentableUrl()})
     * @param defaultRoot   a guessed default root (based on the currently selected file list)
     * @param affectedRoots a set of roots affected by the action
     * @param exceptions    a list of exceptions from running
     * @throws VcsException if there is a problem with running (this exception is considered to be added to the end of the exception list)
     */
    protected abstract void perform(@NotNull Project project, @NotNull List<VirtualFile> Roots,
            @NotNull VirtualFile defaultRoot, final Set<VirtualFile> affectedRoots, List<VcsException> exceptions)
            throws VcsException;

    /**
     * {@inheritDoc}
     */
    @Override
    public void update(final AnActionEvent e) {
        super.update(e);
        Presentation presentation = e.getPresentation();
        DataContext dataContext = e.getDataContext();
        Project project = PlatformDataKeys.PROJECT.getData(dataContext);
        if (project == null) {
            presentation.setEnabled(false);
            presentation.setVisible(false);
            return;
        }
        Vcs vcs = Vcs.getInstance(project);
        final VirtualFile[] roots = ProjectLevelVcsManager.getInstance(project).getRootsUnderVcs(vcs);
        if (roots == null || roots.length == 0) {
            presentation.setEnabled(false);
            presentation.setVisible(false);
            return;
        }
        presentation.setEnabled(true);
        presentation.setVisible(true);
    }
}