[vcs] Refactor VcsLogAction

The getMode() stuff doesn't look very useful because requires all
sorts of clients assert and convert in actionPerformed.

Introduce 2 separate classes instead that makes assertions &
provides converted data to its descendants.
This commit is contained in:
Kirill Likhodedov
2014-08-05 15:33:24 +04:00
parent caa43aea98
commit ab9527873c
6 changed files with 129 additions and 108 deletions
@@ -20,9 +20,7 @@ import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.vcs.log.VcsFullCommitDetails;
import com.intellij.vcs.log.VcsLog;
@@ -30,27 +28,18 @@ import com.intellij.vcs.log.VcsLogDataKeys;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
public abstract class VcsLogAction<Repo extends Repository> extends DumbAwareAction {
protected enum Mode {
SINGLE_COMMIT,
SINGLE_PER_REPO
}
@Override
public void actionPerformed(AnActionEvent e) {
Project project = e.getRequiredData(CommonDataKeys.PROJECT);
VcsLog log = e.getRequiredData(VcsLogDataKeys.VSC_LOG);
List<VcsFullCommitDetails> details = log.getSelectedDetails();
MultiMap<Repo, VcsFullCommitDetails> grouped = groupByRoot(project, details);
MultiMap<Repo, VcsFullCommitDetails> grouped = groupByRootWithCheck(project, details);
assert grouped != null;
Map<Repo, VcsFullCommitDetails> singleElementMap = convertToSingleElementMap(grouped);
assert singleElementMap != null;
actionPerformed(project, singleElementMap);
actionPerformed(project, grouped);
}
@Override
@@ -63,40 +52,25 @@ public abstract class VcsLogAction<Repo extends Repository> extends DumbAwareAct
}
List<VcsFullCommitDetails> details = log.getSelectedDetails();
MultiMap<Repo, VcsFullCommitDetails> grouped = groupByRoot(project, details);
MultiMap<Repo, VcsFullCommitDetails> grouped = groupByRootWithCheck(project, details);
if (grouped == null) {
e.getPresentation().setEnabledAndVisible(false);
}
else {
e.getPresentation().setVisible(true);
e.getPresentation().setEnabled(isEnabled(grouped));
e.getPresentation().setEnabled(!grouped.isEmpty() && isEnabled(grouped));
}
}
private boolean isEnabled(@NotNull MultiMap<Repo, VcsFullCommitDetails> grouped) {
if (grouped.isEmpty()) {
return false;
}
switch (getMode()) {
case SINGLE_COMMIT:
return grouped.size() == 1;
case SINGLE_PER_REPO:
return allValuesAreSingletons(grouped);
default:
return false;
}
}
protected abstract void actionPerformed(@NotNull Project project, @NotNull MultiMap<Repo, VcsFullCommitDetails> grouped);
protected abstract boolean isEnabled(@NotNull MultiMap<Repo, VcsFullCommitDetails> grouped);
@Nullable
protected abstract Repo getRepositoryForRoot(@NotNull Project project, @NotNull VirtualFile root);
protected abstract void actionPerformed(@NotNull Project project, @NotNull Map<Repo, VcsFullCommitDetails> commits);
@NotNull
protected abstract Mode getMode();
@Nullable
private MultiMap<Repo, VcsFullCommitDetails> groupByRoot(@NotNull Project project, @NotNull List<VcsFullCommitDetails> commits) {
private MultiMap<Repo, VcsFullCommitDetails> groupByRootWithCheck(@NotNull Project project, @NotNull List<VcsFullCommitDetails> commits) {
MultiMap<Repo, VcsFullCommitDetails> map = MultiMap.create();
for (VcsFullCommitDetails commit : commits) {
Repo root = getRepositoryForRoot(project, commit.getRoot());
@@ -108,26 +82,4 @@ public abstract class VcsLogAction<Repo extends Repository> extends DumbAwareAct
return map;
}
private boolean allValuesAreSingletons(@NotNull MultiMap<Repo, VcsFullCommitDetails> grouped) {
return !ContainerUtil.exists(grouped.entrySet(), new Condition<Map.Entry<Repo, Collection<VcsFullCommitDetails>>>() {
@Override
public boolean value(Map.Entry<Repo, Collection<VcsFullCommitDetails>> entry) {
return entry.getValue().size() != 1;
}
});
}
@Nullable
private Map<Repo, VcsFullCommitDetails> convertToSingleElementMap(@NotNull MultiMap<Repo, VcsFullCommitDetails> groupedCommits) {
Map<Repo, VcsFullCommitDetails> map = ContainerUtil.newHashMap();
for (Map.Entry<Repo, Collection<VcsFullCommitDetails>> entry : groupedCommits.entrySet()) {
Collection<VcsFullCommitDetails> commits = entry.getValue();
if (commits.size() != 1) {
return null;
}
map.put(entry.getKey(), commits.iterator().next());
}
return map;
}
}
@@ -0,0 +1,69 @@
/*
* Copyright 2000-2014 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 com.intellij.dvcs.ui;
import com.intellij.dvcs.repo.Repository;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.vcs.log.VcsFullCommitDetails;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Map;
public abstract class VcsLogOneCommitPerRepoAction<Repo extends Repository> extends VcsLogAction<Repo> {
@Override
protected void actionPerformed(@NotNull Project project, @NotNull MultiMap<Repo, VcsFullCommitDetails> grouped) {
Map<Repo, VcsFullCommitDetails> singleElementMap = convertToSingleElementMap(grouped);
assert singleElementMap != null;
actionPerformed(project, singleElementMap);
}
@Override
protected boolean isEnabled(@NotNull MultiMap<Repo, VcsFullCommitDetails> grouped) {
return allValuesAreSingletons(grouped);
}
protected abstract void actionPerformed(@NotNull Project project, @NotNull Map<Repo, VcsFullCommitDetails> commits);
private boolean allValuesAreSingletons(@NotNull MultiMap<Repo, VcsFullCommitDetails> grouped) {
return !ContainerUtil.exists(grouped.entrySet(), new Condition<Map.Entry<Repo, Collection<VcsFullCommitDetails>>>() {
@Override
public boolean value(Map.Entry<Repo, Collection<VcsFullCommitDetails>> entry) {
return entry.getValue().size() != 1;
}
});
}
@Nullable
private Map<Repo, VcsFullCommitDetails> convertToSingleElementMap(@NotNull MultiMap<Repo, VcsFullCommitDetails> groupedCommits) {
Map<Repo, VcsFullCommitDetails> map = ContainerUtil.newHashMap();
for (Map.Entry<Repo, Collection<VcsFullCommitDetails>> entry : groupedCommits.entrySet()) {
Collection<VcsFullCommitDetails> commits = entry.getValue();
if (commits.size() != 1) {
return null;
}
map.put(entry.getKey(), commits.iterator().next());
}
return map;
}
}
@@ -0,0 +1,46 @@
/*
* Copyright 2000-2014 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 com.intellij.dvcs.ui;
import com.intellij.dvcs.repo.Repository;
import com.intellij.openapi.project.Project;
import com.intellij.util.containers.MultiMap;
import com.intellij.vcs.log.VcsFullCommitDetails;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Map;
public abstract class VcsLogSingleCommitAction<Repo extends Repository> extends VcsLogAction<Repo> {
@Override
protected boolean isEnabled(@NotNull MultiMap<Repo, VcsFullCommitDetails> grouped) {
return grouped.size() == 1;
}
@Override
protected void actionPerformed(@NotNull Project project, @NotNull MultiMap<Repo, VcsFullCommitDetails> grouped) {
assert grouped.size() == 1;
Map.Entry<Repo, Collection<VcsFullCommitDetails>> entry = grouped.entrySet().iterator().next();
Repo repository = entry.getKey();
Collection<VcsFullCommitDetails> commits = entry.getValue();
assert commits.size() == 1;
actionPerformed(repository, commits.iterator().next());
}
protected abstract void actionPerformed(@NotNull Repo repository, @NotNull VcsFullCommitDetails commit);
}
@@ -15,19 +15,16 @@
*/
package git4idea.actions;
import com.intellij.dvcs.ui.VcsLogAction;
import com.intellij.dvcs.ui.VcsLogSingleCommitAction;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.vcs.log.VcsFullCommitDetails;
import git4idea.repo.GitRepository;
import git4idea.repo.GitRepositoryManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
public abstract class GitLogSingleCommitAction extends VcsLogAction<GitRepository> {
public abstract class GitLogSingleCommitAction extends VcsLogSingleCommitAction<GitRepository> {
@Override
@Nullable
@@ -35,21 +32,4 @@ public abstract class GitLogSingleCommitAction extends VcsLogAction<GitRepositor
return ServiceManager.getService(project, GitRepositoryManager.class).getRepositoryForRoot(root);
}
@NotNull
@Override
protected Mode getMode() {
return Mode.SINGLE_COMMIT;
}
@Override
protected void actionPerformed(@NotNull Project project, @NotNull Map<GitRepository, VcsFullCommitDetails> commits) {
assert commits.size() == 1;
Map.Entry<GitRepository, VcsFullCommitDetails> entry = commits.entrySet().iterator().next();
GitRepository repository = entry.getKey();
VcsFullCommitDetails commit = entry.getValue();
actionPerformed(repository, commit);
}
protected abstract void actionPerformed(@NotNull GitRepository repository, @NotNull VcsFullCommitDetails commit);
}
@@ -15,7 +15,7 @@
*/
package git4idea.reset;
import com.intellij.dvcs.ui.VcsLogAction;
import com.intellij.dvcs.ui.VcsLogOneCommitPerRepoAction;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
@@ -31,7 +31,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.Map;
public class GitResetAction extends VcsLogAction<GitRepository> {
public class GitResetAction extends VcsLogOneCommitPerRepoAction<GitRepository> {
@Nullable
@Override
@@ -39,12 +39,6 @@ public class GitResetAction extends VcsLogAction<GitRepository> {
return getRepoManager(project).getRepositoryForRoot(root);
}
@NotNull
@Override
protected Mode getMode() {
return Mode.SINGLE_PER_REPO;
}
@Override
protected void actionPerformed(@NotNull final Project project, @NotNull final Map<GitRepository, VcsFullCommitDetails> commits) {
GitVcsSettings settings = GitVcsSettings.getInstance(project);
@@ -16,19 +16,16 @@
package org.zmlx.hg4idea.action;
import com.intellij.dvcs.ui.VcsLogAction;
import com.intellij.dvcs.ui.VcsLogSingleCommitAction;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.vcs.log.VcsFullCommitDetails;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.zmlx.hg4idea.repo.HgRepository;
import org.zmlx.hg4idea.repo.HgRepositoryManager;
import java.util.Map;
public abstract class HgLogSingleCommitAction extends VcsLogAction<HgRepository> {
public abstract class HgLogSingleCommitAction extends VcsLogSingleCommitAction<HgRepository> {
@Nullable
@Override
@@ -36,21 +33,4 @@ public abstract class HgLogSingleCommitAction extends VcsLogAction<HgRepository>
return ServiceManager.getService(project, HgRepositoryManager.class).getRepositoryForRoot(root);
}
@NotNull
@Override
protected Mode getMode() {
return Mode.SINGLE_COMMIT;
}
@Override
protected void actionPerformed(@NotNull Project project, @NotNull Map<HgRepository, VcsFullCommitDetails> commits) {
assert commits.size() == 1;
Map.Entry<HgRepository, VcsFullCommitDetails> entry = commits.entrySet().iterator().next();
HgRepository repository = entry.getKey();
VcsFullCommitDetails commit = entry.getValue();
actionPerformed(repository, commit);
}
protected abstract void actionPerformed(@NotNull HgRepository repository, @NotNull VcsFullCommitDetails commit);
}