simplify GTDUCollector a bit more
[idea/community.git] / java / idea-ui / src / com / intellij / openapi / roots / ui / configuration / libraries / impl / LibraryPresentationManagerImpl.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 package com.intellij.openapi.roots.ui.configuration.libraries.impl;
3
4 import com.intellij.openapi.Disposable;
5 import com.intellij.openapi.project.Project;
6 import com.intellij.openapi.roots.OrderRootType;
7 import com.intellij.openapi.roots.impl.libraries.LibraryEx;
8 import com.intellij.openapi.roots.libraries.*;
9 import com.intellij.openapi.roots.ui.configuration.libraries.LibraryPresentationManager;
10 import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer;
11 import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
12 import com.intellij.openapi.vfs.VirtualFile;
13 import com.intellij.util.PlatformIcons;
14 import com.intellij.util.SmartList;
15 import com.intellij.util.containers.ContainerUtil;
16 import org.jetbrains.annotations.Nls;
17 import org.jetbrains.annotations.NotNull;
18 import org.jetbrains.annotations.Nullable;
19
20 import javax.swing.*;
21 import java.util.*;
22
23 final class LibraryPresentationManagerImpl extends LibraryPresentationManager implements Disposable {
24   private volatile Map<LibraryKind, LibraryPresentationProvider<?>> myPresentationProviders;
25
26   public LibraryPresentationManagerImpl() {
27     Runnable listener = () -> myPresentationProviders = null;
28     LibraryType.EP_NAME.addChangeListener(listener, this);
29     LibraryPresentationProvider.EP_NAME.addChangeListener(listener, this);
30   }
31
32   public static List<LibraryKind> getLibraryKinds(@NotNull Library library, @Nullable StructureConfigurableContext context) {
33     final List<LibraryKind> result = new SmartList<>();
34     final LibraryKind kind = ((LibraryEx)library).getKind();
35     if (kind != null) {
36       result.add(kind);
37     }
38     final VirtualFile[] files = getLibraryFiles(library, context);
39     LibraryDetectionManager.getInstance().processProperties(Arrays.asList(files), new LibraryDetectionManager.LibraryPropertiesProcessor() {
40       @Override
41       public <P extends LibraryProperties> boolean processProperties(@NotNull LibraryKind kind, @NotNull P properties) {
42         result.add(kind);
43         return true;
44       }
45     });
46     return result;
47   }
48
49   private static VirtualFile @NotNull [] getLibraryFiles(@NotNull Library library, @Nullable StructureConfigurableContext context) {
50     if (((LibraryEx)library).isDisposed()) {
51       return VirtualFile.EMPTY_ARRAY;
52     }
53     return context != null ? context.getLibraryFiles(library, OrderRootType.CLASSES) : library.getFiles(OrderRootType.CLASSES);
54   }
55
56   private <P extends LibraryProperties> LibraryPresentationProvider<P> getPresentationProvider(LibraryKind kind) {
57     Map<LibraryKind, LibraryPresentationProvider<?>> providers = myPresentationProviders;
58     if (providers == null) {
59       providers = new HashMap<>();
60       for (LibraryType<?> type : LibraryType.EP_NAME.getExtensions()) {
61         providers.put(type.getKind(), type);
62       }
63       for (LibraryPresentationProvider provider : LibraryPresentationProvider.EP_NAME.getExtensions()) {
64         providers.put(provider.getKind(), provider);
65       }
66       myPresentationProviders = providers;
67     }
68     //noinspection unchecked
69     return (LibraryPresentationProvider<P>)providers.get(kind);
70   }
71
72   @NotNull
73   @Override
74   public Icon getNamedLibraryIcon(@NotNull Library library, @Nullable StructureConfigurableContext context) {
75     final Icon icon = getCustomIcon(library, context);
76     return icon != null ? icon : PlatformIcons.LIBRARY_ICON;
77   }
78
79   @Override
80   public Icon getCustomIcon(@NotNull Library library, StructureConfigurableContext context) {
81     LibraryEx libraryEx = (LibraryEx)library;
82     final LibraryKind kind = libraryEx.getKind();
83     if (kind != null) {
84       return LibraryType.findByKind(kind).getIcon(libraryEx.getProperties());
85     }
86     final List<Icon> icons = getCustomIcons(library, context);
87     if (icons.size() == 1) {
88       return icons.get(0);
89     }
90     return null;
91   }
92
93   @NotNull
94   @Override
95   public List<Icon> getCustomIcons(@NotNull Library library, StructureConfigurableContext context) {
96     final VirtualFile[] files = getLibraryFiles(library, context);
97     final List<Icon> icons = new SmartList<>();
98     LibraryDetectionManager.getInstance().processProperties(Arrays.asList(files), new LibraryDetectionManager.LibraryPropertiesProcessor() {
99       @Override
100       public <P extends LibraryProperties> boolean processProperties(@NotNull LibraryKind kind, @NotNull P properties) {
101         final LibraryPresentationProvider<P> provider = getPresentationProvider(kind);
102         if (provider != null) {
103           ContainerUtil.addIfNotNull(icons, provider.getIcon(properties));
104         }
105         return true;
106       }
107     });
108     return icons;
109   }
110
111   @Override
112   public boolean isLibraryOfKind(@NotNull List<? extends VirtualFile> files, @NotNull final LibraryKind kind) {
113     return !LibraryDetectionManager.getInstance().processProperties(files, new LibraryDetectionManager.LibraryPropertiesProcessor() {
114       @Override
115       public <P extends LibraryProperties> boolean processProperties(@NotNull LibraryKind processedKind, @NotNull P properties) {
116         return !kind.equals(processedKind);
117       }
118     });
119   }
120
121   @Override
122   public boolean isLibraryOfKind(@NotNull Library library,
123                                  @NotNull LibrariesContainer librariesContainer,
124                                  @NotNull final Set<? extends LibraryKind> acceptedKinds) {
125     final LibraryKind type = ((LibraryEx)library).getKind();
126     if (type != null && acceptedKinds.contains(type)) return true;
127
128     final VirtualFile[] files = librariesContainer.getLibraryFiles(library, OrderRootType.CLASSES);
129     return !LibraryDetectionManager.getInstance().processProperties(Arrays.asList(files), new LibraryDetectionManager.LibraryPropertiesProcessor() {
130       @Override
131       public <P extends LibraryProperties> boolean processProperties(@NotNull LibraryKind processedKind, @NotNull P properties) {
132         return !acceptedKinds.contains(processedKind);
133       }
134     });
135   }
136
137   @NotNull
138   @Override
139   public List<String> getDescriptions(@NotNull Library library, StructureConfigurableContext context) {
140     final VirtualFile[] files = getLibraryFiles(library, context);
141     return getDescriptions(files, Collections.emptySet());
142   }
143
144   @NotNull
145   @Override
146   public List<@Nls String> getDescriptions(VirtualFile @NotNull [] classRoots, final Set<? extends LibraryKind> excludedKinds) {
147     final SmartList<@Nls String> result = new SmartList<>();
148     LibraryDetectionManager.getInstance().processProperties(Arrays.asList(classRoots), new LibraryDetectionManager.LibraryPropertiesProcessor() {
149       @Override
150       public <P extends LibraryProperties> boolean processProperties(@NotNull LibraryKind kind, @NotNull P properties) {
151         if (!excludedKinds.contains(kind)) {
152           final LibraryPresentationProvider<P> provider = getPresentationProvider(kind);
153           if (provider != null) {
154             ContainerUtil.addIfNotNull(result, provider.getDescription(properties));
155           }
156         }
157         return true;
158       }
159     });
160     return result;
161   }
162
163   @Override
164   public List<Library> getLibraries(@NotNull Set<? extends LibraryKind> kinds, @NotNull Project project, @Nullable StructureConfigurableContext context) {
165     List<Library> libraries = new ArrayList<>();
166     if (context != null) {
167       Collections.addAll(libraries, context.getProjectLibrariesProvider().getModifiableModel().getLibraries());
168       Collections.addAll(libraries, context.getGlobalLibrariesProvider().getModifiableModel().getLibraries());
169     }
170     else {
171       final LibraryTablesRegistrar registrar = LibraryTablesRegistrar.getInstance();
172       Collections.addAll(libraries, registrar.getLibraryTable(project).getLibraries());
173       Collections.addAll(libraries, registrar.getLibraryTable().getLibraries());
174     }
175
176     final Iterator<Library> iterator = libraries.iterator();
177     while (iterator.hasNext()) {
178       Library library = iterator.next();
179       final List<LibraryKind> libraryKinds = getLibraryKinds(library, context);
180       if (!ContainerUtil.intersects(libraryKinds, kinds)) {
181         iterator.remove();
182       }
183     }
184     return libraries;
185   }
186
187   @Override
188   public void dispose() {
189   }
190 }