simplify GTDUCollector a bit more
[idea/community.git] / platform / projectModel-api / src / com / intellij / openapi / roots / libraries / LibraryUtil.java
1 // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2
3 package com.intellij.openapi.roots.libraries;
4
5 import com.intellij.openapi.module.Module;
6 import com.intellij.openapi.module.ModuleManager;
7 import com.intellij.openapi.project.Project;
8 import com.intellij.openapi.roots.*;
9 import com.intellij.openapi.roots.impl.libraries.LibraryEx;
10 import com.intellij.openapi.util.Ref;
11 import com.intellij.openapi.vfs.VfsUtilCore;
12 import com.intellij.openapi.vfs.VirtualFile;
13 import com.intellij.projectModel.ProjectModelBundle;
14 import com.intellij.util.PathUtil;
15 import com.intellij.util.containers.ContainerUtil;
16 import com.intellij.util.text.StringTokenizer;
17 import org.jetbrains.annotations.Nls;
18 import org.jetbrains.annotations.NonNls;
19 import org.jetbrains.annotations.NotNull;
20 import org.jetbrains.annotations.Nullable;
21
22 import java.util.Arrays;
23 import java.util.HashSet;
24 import java.util.List;
25 import java.util.Set;
26
27 public final class LibraryUtil {
28   private LibraryUtil() {
29   }
30
31   public static boolean isClassAvailableInLibrary(@NotNull Library library, @NotNull String fqn) {
32     return isClassAvailableInLibrary(library.getFiles(OrderRootType.CLASSES), fqn);
33   }
34
35   public static boolean isClassAvailableInLibrary(VirtualFile @NotNull [] files, @NotNull String fqn) {
36     return isClassAvailableInLibrary(Arrays.asList(files), fqn);
37   }
38
39   public static boolean isClassAvailableInLibrary(@NotNull List<? extends VirtualFile> files, @NotNull String fqn) {
40     for (VirtualFile file : files) {
41       if (findInFile(file, new StringTokenizer(fqn, "."))) return true;
42     }
43     return false;
44   }
45
46   @Nullable
47   public static Library findLibraryByClass(@NotNull String fqn, @Nullable Project project) {
48     if (project != null) {
49       final LibraryTable projectTable = LibraryTablesRegistrar.getInstance().getLibraryTable(project);
50       Library library = findInTable(projectTable, fqn);
51       if (library != null) {
52         return library;
53       }
54     }
55     final LibraryTable table = LibraryTablesRegistrar.getInstance().getLibraryTable();
56     return findInTable(table, fqn);
57   }
58
59
60   private static boolean findInFile(@NotNull VirtualFile file, @NotNull StringTokenizer tokenizer) {
61     if (!tokenizer.hasMoreTokens()) return true;
62     @NonNls StringBuilder name = new StringBuilder(tokenizer.nextToken());
63     if (!tokenizer.hasMoreTokens()) {
64       name.append(".class");
65     }
66     final VirtualFile child = file.findChild(name.toString());
67     return child != null && findInFile(child, tokenizer);
68   }
69
70   @Nullable
71   private static Library findInTable(@NotNull LibraryTable table, @NotNull String fqn) {
72     for (Library library : table.getLibraries()) {
73       if (isClassAvailableInLibrary(library, fqn)) {
74         return library;
75       }
76     }
77     return null;
78   }
79
80   @NotNull
81   public static Library createLibrary(@NotNull LibraryTable libraryTable, @NonNls @NotNull String baseName) {
82     String name = baseName;
83     int count = 2;
84     while (libraryTable.getLibraryByName(name) != null) {
85       name = baseName + " (" + count++ + ")";
86     }
87     return libraryTable.createLibrary(name);
88   }
89
90   public static VirtualFile @NotNull [] getLibraryRoots(@NotNull Project project) {
91     return getLibraryRoots(project, true, true);
92   }
93
94   public static VirtualFile @NotNull [] getLibraryRoots(@NotNull Project project, final boolean includeSourceFiles, final boolean includeJdk) {
95     return getLibraryRoots(ModuleManager.getInstance(project).getModules(), includeSourceFiles, includeJdk);
96   }
97
98   public static VirtualFile @NotNull [] getLibraryRoots(Module @NotNull [] modules, final boolean includeSourceFiles, final boolean includeJdk) {
99     Set<VirtualFile> roots = new HashSet<>();
100     for (Module module : modules) {
101       final ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
102       final OrderEntry[] orderEntries = moduleRootManager.getOrderEntries();
103       for (OrderEntry entry : orderEntries) {
104         if (entry instanceof LibraryOrderEntry){
105           final Library library = ((LibraryOrderEntry)entry).getLibrary();
106           if (library != null) {
107             VirtualFile[] files = includeSourceFiles ? library.getFiles(OrderRootType.SOURCES) : null;
108             if (files == null || files.length == 0) {
109               files = library.getFiles(OrderRootType.CLASSES);
110             }
111             ContainerUtil.addAll(roots, files);
112           }
113         } else if (includeJdk && entry instanceof JdkOrderEntry) {
114           JdkOrderEntry jdkEntry = (JdkOrderEntry)entry;
115           VirtualFile[] files = includeSourceFiles ? jdkEntry.getRootFiles(OrderRootType.SOURCES) : null;
116           if (files == null || files.length == 0) {
117             files = jdkEntry.getRootFiles(OrderRootType.CLASSES);
118           }
119           ContainerUtil.addAll(roots, files);
120         }
121       }
122     }
123     return VfsUtilCore.toVirtualFileArray(roots);
124   }
125
126   @Nullable
127   public static Library findLibrary(@NotNull Module module, @NotNull final String name) {
128     final Ref<Library> result = Ref.create(null);
129     OrderEnumerator.orderEntries(module).forEachLibrary(library -> {
130       if (name.equals(library.getName())) {
131         result.set(library);
132         return false;
133       }
134       return true;
135     });
136     return result.get();
137   }
138
139   @Nullable
140   public static OrderEntry findLibraryEntry(@NotNull VirtualFile file, @NotNull Project project) {
141     List<OrderEntry> entries = ProjectRootManager.getInstance(project).getFileIndex().getOrderEntriesForFile(file);
142     for (OrderEntry entry : entries) {
143       if (entry instanceof LibraryOrderEntry || entry instanceof JdkOrderEntry) {
144         return entry;
145       }
146     }
147     return null;
148   }
149
150   @NotNull
151   public static @Nls(capitalization = Nls.Capitalization.Title) String getPresentableName(@NotNull Library library) {
152     final String name = library.getName();
153     if (name != null) {
154       return name;
155     }
156     if (library instanceof LibraryEx && ((LibraryEx)library).isDisposed()) {
157       return ProjectModelBundle.message("disposed.library.title");
158     }
159     String[] urls = library.getUrls(OrderRootType.CLASSES);
160     if (urls.length > 0) {
161       return PathUtil.getFileName(VfsUtilCore.urlToPath(urls[0]));
162     }
163     return ProjectModelBundle.message("empty.library.title");
164   }
165 }