IdentityFilePointer should be removed from myUrlToIdentity cache on dispose
[idea/community.git] / java / idea-ui / src / com / intellij / openapi / roots / ui / configuration / libraryEditor / NewLibraryEditor.java
1 /*
2  * Copyright 2000-2010 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.openapi.roots.ui.configuration.libraryEditor;
17
18 import com.intellij.openapi.roots.OrderRootType;
19 import com.intellij.openapi.roots.impl.libraries.JarDirectories;
20 import com.intellij.openapi.roots.impl.libraries.LibraryEx;
21 import com.intellij.openapi.roots.impl.libraries.LibraryImpl;
22 import com.intellij.openapi.roots.libraries.LibraryProperties;
23 import com.intellij.openapi.roots.libraries.LibraryType;
24 import com.intellij.openapi.vfs.VfsUtilCore;
25 import com.intellij.openapi.vfs.VirtualFile;
26 import com.intellij.openapi.vfs.impl.LightFilePointer;
27 import com.intellij.util.ArrayUtil;
28 import com.intellij.util.containers.MultiMap;
29 import org.jetbrains.annotations.NotNull;
30 import org.jetbrains.annotations.Nullable;
31
32 import java.util.*;
33
34 /**
35  * @author nik
36  */
37 public class NewLibraryEditor extends LibraryEditorBase {
38   private String myLibraryName;
39   private final MultiMap<OrderRootType, LightFilePointer> myRoots;
40   private final Set<LightFilePointer> myExcludedRoots;
41   private final JarDirectories myJarDirectories = new JarDirectories();
42   private LibraryType myType;
43   private LibraryProperties myProperties;
44
45   public NewLibraryEditor() {
46     this(null, null);
47   }
48
49   public NewLibraryEditor(@Nullable LibraryType type, @Nullable LibraryProperties properties) {
50     myType = type;
51     myProperties = properties;
52     myRoots = new MultiMap<>();
53     myExcludedRoots = new LinkedHashSet<>();
54   }
55
56   @Override
57   public Collection<OrderRootType> getOrderRootTypes() {
58     return myRoots.keySet();
59   }
60
61   @Override
62   @Nullable
63   public LibraryType<?> getType() {
64     return myType;
65   }
66
67   @Override
68   public void setType(@NotNull LibraryType<?> type) {
69     myType = type;
70   }
71
72   @Override
73   public LibraryProperties getProperties() {
74     return myProperties;
75   }
76
77   @Override
78   public void setProperties(LibraryProperties properties) {
79     myProperties = properties;
80   }
81
82   @Override
83   public String getName() {
84     return myLibraryName;
85   }
86
87   @Override
88   public String[] getUrls(OrderRootType rootType) {
89     return pointersToUrls(myRoots.get(rootType));
90   }
91
92   private static String[] pointersToUrls(Collection<LightFilePointer> pointers) {
93     List<String> urls = new ArrayList<>(pointers.size());
94     for (LightFilePointer pointer : pointers) {
95       urls.add(pointer.getUrl());
96     }
97     return ArrayUtil.toStringArray(urls);
98   }
99
100   @Override
101   public VirtualFile[] getFiles(OrderRootType rootType) {
102     List<VirtualFile> result = new ArrayList<>();
103     for (LightFilePointer pointer : myRoots.get(rootType)) {
104       final VirtualFile file = pointer.getFile();
105       if (file == null) {
106         continue;
107       }
108
109       if (file.isDirectory()) {
110         final String url = file.getUrl();
111         if (myJarDirectories.contains(rootType, url)) {
112           LibraryImpl.collectJarFiles(file, result, myJarDirectories.isRecursive(rootType, url));
113           continue;
114         }
115       }
116       result.add(file);
117     }
118     return VfsUtilCore.toVirtualFileArray(result);
119   }
120
121   @Override
122   public String[] getExcludedRootUrls() {
123     return pointersToUrls(myExcludedRoots);
124   }
125
126   @Override
127   public void setName(String name) {
128     myLibraryName = name;
129   }
130
131   @Override
132   public void addRoot(VirtualFile file, OrderRootType rootType) {
133     myRoots.putValue(rootType, new LightFilePointer(file));
134   }
135
136   @Override
137   public void addRoot(String url, OrderRootType rootType) {
138     myRoots.putValue(rootType, new LightFilePointer(url));
139   }
140
141   @Override
142   public void addJarDirectory(VirtualFile file, boolean recursive, OrderRootType rootType) {
143     addJarDirectory(file.getUrl(), recursive, rootType);
144   }
145
146   @Override
147   public void addExcludedRoot(@NotNull String url) {
148     myExcludedRoots.add(new LightFilePointer(url));
149   }
150
151   @Override
152   public void removeExcludedRoot(@NotNull String url) {
153     myExcludedRoots.remove(new LightFilePointer(url));
154   }
155
156   @Override
157   public void addJarDirectory(final String url, boolean recursive, OrderRootType rootType) {
158     addRoot(url, rootType);
159     myJarDirectories.add(rootType, url, recursive);
160   }
161
162   @Override
163   public void removeRoot(String url, OrderRootType rootType) {
164     myRoots.remove(rootType, new LightFilePointer(url));
165     Iterator<LightFilePointer> iterator = myExcludedRoots.iterator();
166     while (iterator.hasNext()) {
167       LightFilePointer pointer = iterator.next();
168       if (!isUnderRoots(pointer.getUrl())) {
169         iterator.remove();
170       }
171     }
172     myJarDirectories.remove(rootType, url);
173   }
174
175   private boolean isUnderRoots(@NotNull String url) {
176     for (LightFilePointer pointer : myRoots.values()) {
177       if (VfsUtilCore.isEqualOrAncestor(pointer.getUrl(), url)) {
178         return true;
179       }
180     }
181     return false;
182   }
183
184   @Override
185   public boolean hasChanges() {
186     return true;
187   }
188
189   @Override
190   public boolean isJarDirectory(String url, OrderRootType rootType) {
191     return myJarDirectories.contains(rootType, url);
192   }
193
194   @Override
195   public boolean isValid(String url, OrderRootType orderRootType) {
196     final Collection<LightFilePointer> pointers = myRoots.get(orderRootType);
197     for (LightFilePointer pointer : pointers) {
198       if (pointer.getUrl().equals(url)) {
199         return pointer.isValid();
200       }
201     }
202     return false;
203   }
204
205   public void applyTo(LibraryEx.ModifiableModelEx model) {
206     model.setProperties(myProperties);
207     for (OrderRootType type : myRoots.keySet()) {
208       for (LightFilePointer pointer : myRoots.get(type)) {
209         if (!myJarDirectories.contains(type, pointer.getUrl())) {
210           model.addRoot(pointer.getUrl(), type);
211         }
212       }
213     }
214     for (OrderRootType rootType : myJarDirectories.getRootTypes()) {
215       for (String url : myJarDirectories.getDirectories(rootType)) {
216         model.addJarDirectory(url, myJarDirectories.isRecursive(rootType, url), rootType);
217       }
218     }
219   }
220
221   public void applyTo(LibraryEditorBase editor) {
222     editor.setProperties(myProperties);
223     for (OrderRootType type : myRoots.keySet()) {
224       for (LightFilePointer pointer : myRoots.get(type)) {
225         if (!myJarDirectories.contains(type, pointer.getUrl())) {
226           editor.addRoot(pointer.getUrl(), type);
227         }
228       }
229     }
230     for (OrderRootType rootType : myJarDirectories.getRootTypes()) {
231       for (String url : myJarDirectories.getDirectories(rootType)) {
232         editor.addJarDirectory(url, myJarDirectories.isRecursive(rootType, url), rootType);
233       }
234     }
235   }
236 }