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