| /* |
| * Copyright 2000-2011 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.openapi.roots.libraries.ui.impl; |
| |
| import com.intellij.ide.util.ChooseElementsDialog; |
| import com.intellij.openapi.application.ApplicationNamesInfo; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.progress.ProcessCanceledException; |
| import com.intellij.openapi.progress.ProgressIndicator; |
| import com.intellij.openapi.progress.Task; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.roots.OrderRootType; |
| import com.intellij.openapi.roots.libraries.LibraryRootType; |
| import com.intellij.openapi.roots.libraries.ui.DetectedLibraryRoot; |
| import com.intellij.openapi.roots.libraries.ui.LibraryRootsComponentDescriptor; |
| import com.intellij.openapi.roots.libraries.ui.LibraryRootsDetector; |
| import com.intellij.openapi.roots.libraries.ui.OrderRoot; |
| import com.intellij.openapi.util.Pair; |
| import com.intellij.openapi.util.text.StringUtil; |
| import com.intellij.openapi.vfs.VirtualFile; |
| import com.intellij.xml.util.XmlStringUtil; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import java.awt.*; |
| import java.util.*; |
| import java.util.List; |
| |
| /** |
| * @author nik |
| */ |
| public class RootDetectionUtil { |
| private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.ui.configuration.libraryEditor.RootDetectionUtil"); |
| |
| private RootDetectionUtil() { |
| } |
| |
| @NotNull |
| public static List<OrderRoot> detectRoots(@NotNull final Collection<VirtualFile> rootCandidates, |
| @Nullable Component parentComponent, |
| @Nullable Project project, |
| @NotNull final LibraryRootsComponentDescriptor rootsComponentDescriptor) { |
| return detectRoots(rootCandidates, parentComponent, project, rootsComponentDescriptor.getRootsDetector(), |
| rootsComponentDescriptor.getRootTypes()); |
| } |
| |
| @NotNull |
| public static List<OrderRoot> detectRoots(@NotNull final Collection<VirtualFile> rootCandidates, @Nullable Component parentComponent, |
| @Nullable Project project, @NotNull final LibraryRootsDetector detector, |
| @NotNull OrderRootType[] rootTypesAllowedToBeSelectedByUserIfNothingIsDetected) { |
| final List<OrderRoot> result = new ArrayList<OrderRoot>(); |
| final List<SuggestedChildRootInfo> suggestedRoots = new ArrayList<SuggestedChildRootInfo>(); |
| new Task.Modal(project, "Scanning for Roots", true) { |
| @Override |
| public void run(@NotNull ProgressIndicator indicator) { |
| try { |
| for (VirtualFile rootCandidate : rootCandidates) { |
| final Collection<DetectedLibraryRoot> roots = detector.detectRoots(rootCandidate, indicator); |
| if (!roots.isEmpty() && allRootsHaveOneTypeAndEqualToOrAreDirectParentOf(roots, rootCandidate)) { |
| for (DetectedLibraryRoot root : roots) { |
| final LibraryRootType libraryRootType = root.getTypes().get(0); |
| result.add(new OrderRoot(root.getFile(), libraryRootType.getType(), libraryRootType.isJarDirectory())); |
| } |
| } |
| else { |
| for (DetectedLibraryRoot root : roots) { |
| final HashMap<LibraryRootType, String> names = new HashMap<LibraryRootType, String>(); |
| for (LibraryRootType type : root.getTypes()) { |
| final String typeName = detector.getRootTypeName(type); |
| LOG.assertTrue(typeName != null, "Unexpected root type " + type.getType().name() + (type.isJarDirectory() ? " (JAR directory)" : "") + ", detectors: " + detector); |
| names.put(type, typeName); |
| } |
| suggestedRoots.add(new SuggestedChildRootInfo(rootCandidate, root, names)); |
| } |
| } |
| } |
| } |
| catch (ProcessCanceledException ignored) { |
| } |
| } |
| }.queue(); |
| |
| if (!suggestedRoots.isEmpty()) { |
| final DetectedRootsChooserDialog dialog = parentComponent != null |
| ? new DetectedRootsChooserDialog(parentComponent, suggestedRoots) |
| : new DetectedRootsChooserDialog(project, suggestedRoots); |
| dialog.show(); |
| if (!dialog.isOK()) { |
| return Collections.emptyList(); |
| } |
| for (SuggestedChildRootInfo rootInfo : dialog.getChosenRoots()) { |
| final LibraryRootType selectedRootType = rootInfo.getSelectedRootType(); |
| result.add(new OrderRoot(rootInfo.getDetectedRoot().getFile(), selectedRootType.getType(), selectedRootType.isJarDirectory())); |
| } |
| } |
| |
| if (result.isEmpty() && rootTypesAllowedToBeSelectedByUserIfNothingIsDetected.length > 0) { |
| Map<String, Pair<OrderRootType, Boolean>> types = new HashMap<String, Pair<OrderRootType, Boolean>>(); |
| for (OrderRootType type : rootTypesAllowedToBeSelectedByUserIfNothingIsDetected) { |
| for (boolean isJarDirectory : new boolean[]{false, true}) { |
| final String typeName = detector.getRootTypeName(new LibraryRootType(type, isJarDirectory)); |
| if (typeName != null) { |
| types.put(StringUtil.capitalizeWords(typeName, true), Pair.create(type, isJarDirectory)); |
| } |
| } |
| } |
| LOG.assertTrue(!types.isEmpty(), "No allowed root types found for " + detector); |
| List<String> names = new ArrayList<String>(types.keySet()); |
| String title = "Choose Categories of Selected Files"; |
| String description = XmlStringUtil.wrapInHtml(ApplicationNamesInfo.getInstance().getProductName() + " cannot determine what kind of files the chosen items contain.<br>" + |
| "Choose the appropriate categories from the list."); |
| ChooseElementsDialog<String> dialog; |
| if (parentComponent != null) { |
| dialog = new ChooseRootTypeElementsDialog(parentComponent, names, title, description); |
| } |
| else { |
| dialog = new ChooseRootTypeElementsDialog(project, names, title, description); |
| } |
| for (String rootType : dialog.showAndGetResult()) { |
| final Pair<OrderRootType, Boolean> pair = types.get(rootType); |
| for (VirtualFile candidate : rootCandidates) { |
| result.add(new OrderRoot(candidate, pair.getFirst(), pair.getSecond())); |
| } |
| } |
| } |
| |
| return result; |
| } |
| |
| private static boolean allRootsHaveOneTypeAndEqualToOrAreDirectParentOf(Collection<DetectedLibraryRoot> roots, VirtualFile candidate) { |
| for (DetectedLibraryRoot root : roots) { |
| if (root.getTypes().size() > 1 || !root.getFile().equals(candidate) && !root.getFile().equals(candidate.getParent())) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| private static class ChooseRootTypeElementsDialog extends ChooseElementsDialog<String> { |
| public ChooseRootTypeElementsDialog(Project project, List<String> names, String title, String description) { |
| super(project, names, title, description, true); |
| } |
| |
| private ChooseRootTypeElementsDialog(Component parent, List<String> names, String title, String description) { |
| super(parent, names, title, description, true); |
| } |
| |
| @Override |
| protected String getItemText(String item) { |
| return item; |
| } |
| |
| @Nullable |
| @Override |
| protected Icon getItemIcon(String item) { |
| return null; |
| } |
| } |
| } |