KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > loaders > FilesSet


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.openide.loaders;
21
22 import java.util.*;
23
24 import org.openide.filesystems.FileObject;
25
26 /** This class is a lazy initialized set of FileObjects representing entries
27  * in MultiDataObject class. Primary file object is returned as the first from
28  * this set, the secondary fileobjects are sorted by <code>getNameExt()</code>
29  * method result alphabetically.
30  * <p>
31  * This class is an implementation of performance enhancement #16396.
32  *
33  * @see <a HREF="http://www.netbeans.org/issues/show_bug.cgi?id=16396">Issue #16396</a>
34  *
35  * @author Petr Hamernik
36  */

37 final class FilesSet implements Set<FileObject> {
38
39     /** MDO which created this set */
40     private MultiDataObject mymdo;
41     
42     /** A flag */
43     private boolean lazyWorkDone;
44
45     /** Primary file. It is returned first. */
46     private FileObject primaryFile;
47     
48     /** The link to secondary variable of MultiDataObject. Reading of the content
49      * must be synchronized on this map.
50      */

51     private Map<FileObject,MultiDataObject.Entry> secondary;
52
53     /** The set containing all files. It is <code>null</code> and is lazy initialized
54      * when necessary.
55      */

56     private TreeSet<FileObject> delegate;
57     
58     /** Creates a new instance of FilesSet for the MultiDataObject.
59      * @param primaryFile The primary file - this object is returned first.
60      * @param secondary the map of secondary file objects. It is used
61      * for initialization <code>delegate</code> variable when necessary.
62      */

63     public FilesSet(MultiDataObject mdo) {
64         
65         this.mymdo = mdo;
66         this.lazyWorkDone = false;
67         this.primaryFile = null;
68         this.secondary = null;
69     }
70
71     /** Does the work which was originally done in MDO.files() method. */
72     private void doLazyWork() {
73         synchronized (this) {
74             if (!lazyWorkDone) {
75                 lazyWorkDone = true;
76
77                 synchronized ( mymdo.synchObjectSecondary() ) {
78                     // cleans up invalid entries
79
mymdo.secondaryEntries();
80                     primaryFile = mymdo.getPrimaryFile();
81                     secondary = mymdo.getSecondary();
82                 }
83             }
84         }
85     }
86     
87     /** Perform lazy initialization of delegate TreeSet.
88      */

89     private Set<FileObject> getDelegate() {
90         doLazyWork();
91         // This synchronized block was moved from MultiDataObject.files() method,
92
// because of lazy initialization of delegate TreeSet.
93
// Hopefully won't cause threading problems.
94
synchronized (secondary) {
95             if (delegate == null) {
96                 delegate = new TreeSet<FileObject>(new FilesComparator());
97                 delegate.add(primaryFile);
98                 delegate.addAll(secondary.keySet());
99             }
100         }
101         return delegate;
102     }
103
104     // =====================================================================
105
// Implementation of Set interface methods
106
// =====================================================================
107

108     public boolean add(FileObject obj) {
109         return getDelegate().add(obj);
110     }
111     
112     public boolean addAll(Collection<? extends FileObject> collection) {
113         return getDelegate().addAll(collection);
114     }
115     
116     public void clear() {
117         getDelegate().clear();
118     }
119     
120     public boolean contains(Object JavaDoc obj) {
121         return getDelegate().contains(obj);
122     }
123     
124     public boolean containsAll(Collection<?> collection) {
125         return getDelegate().containsAll(collection);
126     }
127     
128     public boolean isEmpty() {
129         doLazyWork();
130         synchronized (secondary) {
131             return (delegate == null) ? false : delegate.isEmpty();
132         }
133     }
134     
135     public Iterator<FileObject> iterator() {
136         doLazyWork();
137         synchronized (secondary) {
138             return (delegate == null) ? new FilesIterator() : delegate.iterator();
139         }
140     }
141     
142     public boolean remove(Object JavaDoc obj) {
143         return getDelegate().remove(obj);
144     }
145     
146     public boolean removeAll(Collection<?> collection) {
147         return getDelegate().removeAll(collection);
148     }
149     
150     public boolean retainAll(Collection<?> collection) {
151         return getDelegate().retainAll(collection);
152     }
153     
154     public int size() {
155         doLazyWork();
156         synchronized (secondary) {
157             return (delegate == null) ? (secondary.size() + 1) : delegate.size();
158         }
159     }
160     
161     public Object JavaDoc[] toArray() {
162         return getDelegate().toArray();
163     }
164     
165     public <T> T[] toArray(T[] obj) {
166         return getDelegate().toArray(obj);
167     }
168
169     public boolean equals(Object JavaDoc obj) {
170         return getDelegate().equals(obj);
171     }
172
173     public String JavaDoc toString() {
174         return getDelegate().toString();
175     }
176
177     public int hashCode() {
178         return getDelegate().hashCode();
179     }
180
181     /** Iterator for FilesSet. It returns the primaryFile first and
182      * then initialize the delegate iterator for secondary files.
183      */

184     private final class FilesIterator implements Iterator<FileObject> {
185         /** Was the first element (primary file) already returned?
186          */

187         private boolean first = true;
188         
189         /** Delegation iterator for secondary files. It is lazy initialized after
190          * the first element is returned.
191          */

192         private Iterator<FileObject> itDelegate = null;
193         
194         FilesIterator() {}
195         
196         public boolean hasNext() {
197             return first ? true : getIteratorDelegate().hasNext();
198         }
199         
200         public FileObject next() {
201             if (first) {
202                 first = false;
203                 return FilesSet.this.primaryFile;
204             }
205             else {
206                 return getIteratorDelegate().next();
207             }
208         }
209
210         public void remove() {
211             getIteratorDelegate().remove();
212         }
213
214         /** Initialize the delegation iterator.
215          */

216         private Iterator<FileObject> getIteratorDelegate() {
217             if (itDelegate == null) {
218                 // this should return iterator of all files of the MultiDataObject...
219
itDelegate = FilesSet.this.getDelegate().iterator();
220                 // ..., so it is necessary to skip the primary file
221
itDelegate.next();
222             }
223             return itDelegate;
224         }
225     }
226     
227     /** Comparator for file objects. The primary file is less than any other file,
228      * so it is returned first. Other files are compared by getNameExt() method
229      * result.
230      */

231     private final class FilesComparator implements Comparator<FileObject> {
232         FilesComparator() {}
233         public int compare(FileObject f1, FileObject f2) {
234             if (f1 == f2)
235                 return 0;
236             
237             if (f1 == primaryFile)
238                 return -1;
239             
240             if (f2 == primaryFile)
241                 return 1;
242             
243             int res = f1.getNameExt().compareTo(f2.getNameExt());
244             
245             if (res == 0) {
246                 // check whether they both live on the same fs
247
try {
248                     if (f1.getFileSystem() == f2.getFileSystem()) {
249                         return 0;
250                     }
251                     // different fs --> compare the fs names
252
return f1.getFileSystem().getSystemName().compareTo(
253                         f2.getFileSystem().getSystemName());
254                 } catch (org.openide.filesystems.FileStateInvalidException fsie) {
255                     // should not happen - but the names were the same
256
// so we declare they are the same (even if the filesystems
257
// crashed meanwhile)
258
return 0;
259                 }
260             }
261             
262             return res;
263         }
264     }
265 }
266
Popular Tags