1 package com
.intellij
.openapi
.roots
.impl
.libraries
;
3 import com
.intellij
.openapi
.Disposable
;
4 import com
.intellij
.openapi
.application
.ApplicationManager
;
5 import com
.intellij
.openapi
.components
.PersistentStateComponent
;
6 import com
.intellij
.openapi
.diagnostic
.Logger
;
7 import com
.intellij
.openapi
.roots
.OrderRootType
;
8 import com
.intellij
.openapi
.roots
.libraries
.Library
;
9 import com
.intellij
.openapi
.roots
.libraries
.LibraryTable
;
10 import com
.intellij
.openapi
.util
.*;
11 import com
.intellij
.util
.EventDispatcher
;
12 import com
.intellij
.util
.containers
.HashSet
;
13 import org
.jdom
.Element
;
14 import org
.jetbrains
.annotations
.NonNls
;
15 import org
.jetbrains
.annotations
.NotNull
;
16 import org
.jetbrains
.annotations
.Nullable
;
20 public abstract class LibraryTableBase
implements PersistentStateComponent
<Element
>, LibraryTable
, Disposable
{
21 private static final Logger LOG
= Logger
.getInstance("#com.intellij.openapi.roots.impl.libraries.LibraryTableBase");
22 private final EventDispatcher
<Listener
> myDispatcher
= EventDispatcher
.create(Listener
.class);
23 private LibraryModel myModel
= new LibraryModel();
24 private boolean myFirstLoad
= true;
26 public ModifiableModel
getModifiableModel() {
27 return new LibraryModel(myModel
);
30 public Element
getState() {
31 final Element element
= new Element("state");
33 myModel
.writeExternal(element
);
35 catch (WriteExternalException e
) {
41 public void loadState(final Element element
) {
44 myModel
.readExternal(element
);
47 final LibraryModel model
= new LibraryModel();
48 model
.readExternal(element
);
54 catch (InvalidDataException e
) {
55 throw new RuntimeException(e
);
60 public Library
[] getLibraries() {
61 return myModel
.getLibraries();
65 public Iterator
<Library
> getLibraryIterator() {
66 return myModel
.getLibraryIterator();
69 public Library
getLibraryByName(@NotNull String name
) {
70 return myModel
.getLibraryByName(name
);
73 public void addListener(Listener listener
) {
74 myDispatcher
.addListener(listener
);
77 public void addListener(Listener listener
, Disposable parentDisposable
) {
78 myDispatcher
.addListener(listener
, parentDisposable
);
81 public void removeListener(Listener listener
) {
82 myDispatcher
.removeListener(listener
);
85 private void fireLibraryAdded (Library library
) {
86 if (LOG
.isDebugEnabled()) {
87 LOG
.debug("fireLibraryAdded: " + library
);
89 myDispatcher
.getMulticaster().afterLibraryAdded(library
);
92 private void fireBeforeLibraryRemoved (Library library
) {
93 if (LOG
.isDebugEnabled()) {
94 LOG
.debug("fireBeforeLibraryRemoved: " + library
);
96 myDispatcher
.getMulticaster().beforeLibraryRemoved(library
);
99 public void dispose() {
100 for (Library library
: getLibraries()) {
101 Disposer
.dispose(library
);
105 public Library
createLibrary() {
106 ApplicationManager
.getApplication().assertWriteAccessAllowed();
107 return createLibrary(null);
110 public void fireLibraryRenamed(LibraryImpl library
) {
111 myDispatcher
.getMulticaster().afterLibraryRenamed(library
);
114 public Library
createLibrary(String name
) {
115 final ModifiableModel modifiableModel
= getModifiableModel();
116 final Library library
= modifiableModel
.createLibrary(name
);
117 modifiableModel
.commit();
121 public void removeLibrary(@NotNull Library library
) {
122 final ModifiableModel modifiableModel
= getModifiableModel();
123 modifiableModel
.removeLibrary(library
);
124 modifiableModel
.commit();
127 private void commit(LibraryModel model
) {
128 ApplicationManager
.getApplication().assertWriteAccessAllowed();
129 List
<Library
> addedLibraries
= new ArrayList
<Library
>(model
.myLibraries
);
130 addedLibraries
.removeAll(myModel
.myLibraries
);
131 List
<Library
> removedLibraries
= new ArrayList
<Library
>(myModel
.myLibraries
);
132 removedLibraries
.removeAll(model
.myLibraries
);
134 for (Library library
: removedLibraries
) {
135 fireBeforeLibraryRemoved(library
);
138 // dispose newly created instances of same (equals()) libraries
139 for (final Library library
: model
.myLibraries
) {
140 if (addedLibraries
.contains(library
)) continue;
141 for (final Library oldLibrary
: myModel
.myLibraries
) {
142 if (library
.equals(oldLibrary
) && library
!= oldLibrary
) {
143 final int index
= model
.myLibraries
.indexOf(library
);
144 Disposer
.dispose(library
);
146 // keep old library if somebody cached old instance
147 model
.myLibraries
.set(index
, oldLibrary
);
154 for (Library library
: removedLibraries
) {
155 Disposer
.dispose(library
);
156 fireAfterLibraryRemoved(library
);
158 for (Library library
: addedLibraries
) {
159 fireLibraryAdded(library
);
163 private void fireAfterLibraryRemoved(Library library
) {
164 myDispatcher
.getMulticaster().afterLibraryRemoved(library
);
167 public void readExternal(final Element element
) throws InvalidDataException
{
168 myModel
= new LibraryModel();
169 myModel
.readExternal(element
);
172 public void writeExternal(final Element element
) throws WriteExternalException
{
173 myModel
.writeExternal(element
);
176 public class LibraryModel
implements ModifiableModel
, JDOMExternalizable
{
177 private final ArrayList
<Library
> myLibraries
= new ArrayList
<Library
>();
178 private boolean myWritable
;
180 private LibraryModel() {
184 private LibraryModel(LibraryModel that
) {
186 myLibraries
.addAll(that
.myLibraries
);
189 public void commit() {
191 LibraryTableBase
.this.commit(this);
195 public Iterator
<Library
> getLibraryIterator() {
196 return Collections
.unmodifiableList(myLibraries
).iterator();
200 public Library
getLibraryByName(@NotNull String name
) {
201 for (Library myLibrary
: myLibraries
) {
202 LibraryImpl library
= (LibraryImpl
)myLibrary
;
203 if (Comparing
.equal(name
, library
.getName())) return library
;
205 @NonNls final String libraryPrefix
= "library.";
206 final String libPath
= System
.getProperty(libraryPrefix
+ name
);
207 if (libPath
!= null) {
208 final LibraryImpl library
= new LibraryImpl(name
, LibraryTableBase
.this, null);
209 library
.addRoot(libPath
, OrderRootType
.CLASSES
);
217 public Library
[] getLibraries() {
218 return myLibraries
.toArray(new Library
[myLibraries
.size()]);
221 private void assertWritable() {
222 LOG
.assertTrue(myWritable
);
225 public Library
createLibrary(String name
) {
227 final LibraryImpl library
= new LibraryImpl(name
, LibraryTableBase
.this, null);
228 myLibraries
.add(library
);
232 public void removeLibrary(@NotNull Library library
) {
234 myLibraries
.remove(library
);
237 public boolean isChanged() {
238 if (!myWritable
) return false;
239 Set
<Library
> thisLibraries
= new HashSet
<Library
>(myLibraries
);
240 Set
<Library
> thatLibraries
= new HashSet
<Library
>(myModel
.myLibraries
);
241 return !thisLibraries
.equals(thatLibraries
);
244 public void readExternal(Element element
) throws InvalidDataException
{
245 HashMap
<String
, Library
> libraries
= new HashMap
<String
, Library
>();
246 for (Library library
: myLibraries
) {
247 libraries
.put(library
.getName(), library
);
250 final List libraryElements
= element
.getChildren(LibraryImpl
.ELEMENT
);
251 for (Object libraryElement1
: libraryElements
) {
252 Element libraryElement
= (Element
)libraryElement1
;
253 final LibraryImpl library
= new LibraryImpl(LibraryTableBase
.this, libraryElement
, null);
254 if (library
.getName() != null) {
255 Library oldLibrary
= libraries
.get(library
.getName());
256 if (oldLibrary
!= null) {
257 removeLibrary(oldLibrary
);
260 myLibraries
.add(library
);
261 fireLibraryAdded(library
);
266 public void writeExternal(Element element
) throws WriteExternalException
{
267 for (Library library
: myLibraries
) {
268 if (library
.getName() != null) {
269 library
.writeExternal(element
);