KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > editor > lib2 > DocumentsRegistry


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.netbeans.modules.editor.lib2;
21
22 import java.beans.PropertyChangeListener JavaDoc;
23 import java.beans.PropertyChangeSupport JavaDoc;
24 import java.lang.ref.WeakReference JavaDoc;
25 import java.util.ArrayList JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import javax.swing.text.JTextComponent JavaDoc;
28 import javax.swing.text.Document JavaDoc;
29
30 /**
31 * All the documents and components register here so that
32 * they become available to the processing that crosses
33 * different components and documents such as cross document
34 * position stack or word matching.
35 *
36 * @author Miloslav Metelka
37 * @version 1.00
38 */

39 public class DocumentsRegistry {
40
41     /** Identification of a document. */
42     public static final String JavaDoc DOCUMENT_ID_PROP = "id"; // NOI18N
43

44     /** Identification of a component. */
45     public static final String JavaDoc COMPONENT_ID_PROP = "componentId"; // NOI18N
46

47     private static final WeakReference JavaDoc[] EMPTY = new WeakReference JavaDoc[0];
48
49     /** Array of weak references to documents */
50     private static WeakReference JavaDoc[] docRefs = EMPTY;
51     
52     /** Number of the document references */
53     private static int docRefsCount;
54
55     /** Array of activated document numbers */
56     private static final ArrayList JavaDoc<Integer JavaDoc> docAct = new ArrayList JavaDoc<Integer JavaDoc>();
57
58     /** Array list of weak references to components */
59     private static WeakReference JavaDoc[] compRefs = EMPTY;
60
61     /** Number of the document references */
62     private static int compRefsCount;
63
64     /** Array of activated component numbers */
65     private static final ArrayList JavaDoc<Integer JavaDoc> compAct = new ArrayList JavaDoc<Integer JavaDoc>();
66     
67     /** The property fired when an active component changes. */
68     public static final String JavaDoc PROP_ACTIVE_COMPONENT = "org.netbeans.modules.editor.lib2.DocumentsRegistry.PROP_ACTIVE_COMPONENT"; //NOI18N
69

70     /** The property fired when an active document changes. */
71     public static final String JavaDoc PROP_ACTIVE_DOCUMENT = "org.netbeans.modules.editor.lib2.DocumentsRegistry.PROP_ACTIVE_DOCUMENT"; //NOI18N
72

73     /** List of the registered changes listeners */
74     private static final PropertyChangeSupport JavaDoc PCS = new PropertyChangeSupport JavaDoc(DocumentsRegistry.class);
75     
76     private static int consolidateCounter;
77
78     /** Add a listener to listen for changes in the registry.
79      *
80      * @param l listener to add
81      */

82     public static void addPropertyChangeListener(PropertyChangeListener JavaDoc l) {
83         PCS.addPropertyChangeListener(l);
84     }
85
86     /** Remove a listener.
87      *
88      * @param l listener to remove
89      */

90     public static void removePropertyChangeListener(PropertyChangeListener JavaDoc l) {
91         PCS.removePropertyChangeListener(l);
92     }
93
94     /** Get document ID from the document.
95      * @return document id or -1 if document was not yet added to the registry
96      * by <code>addDocument()</code>.
97      */

98     public static synchronized int getID(Document JavaDoc doc) {
99     Integer JavaDoc i = getIDInteger(doc);
100     return (i != null) ? i.intValue() : -1;
101     }
102     
103     /** Get component ID from the component.
104      * @return component id or -1 if component was not yet added to the registry
105      * by <code>addComponent()</code>.
106      */

107     public static synchronized int getID(JTextComponent JavaDoc c) {
108     return getIDImpl(c);
109     }
110
111     /** Get document when its ID is known.
112      * It's rather cheap operation.
113      * @param docID document ID. It can be retrieved from the document
114      * by <code>getID(doc)</code>.
115      * @return document instance or null when document no longer exists
116      */

117     public static synchronized Document JavaDoc getDocument(int docID) {
118         if (docID < 0 || docID >= docRefsCount) {
119             return null;
120         }
121
122     WeakReference JavaDoc wr = docRefs[docID];
123         return (wr != null) ? (Document JavaDoc)wr.get() : null;
124     }
125
126     /** Get component when its ID is known.
127      * It's rather cheap operation.
128      * @param compID component ID. It can be retrieved from the component
129      * by <code>getID(c)</code>.
130      * @return component instance or null when document no longer exists
131      */

132     public static synchronized JTextComponent JavaDoc getComponent(int compID) {
133         if (compID < 0 || compID >= compRefsCount) {
134             return null;
135         }
136
137     WeakReference JavaDoc wr = compRefs[compID];
138         return (wr != null) ? (JTextComponent JavaDoc)wr.get() : null;
139     }
140
141     /** Add document to registry. Doesn't search for repetitive
142      * adding.
143      * @return registry unique ID of the document
144      */

145     public static synchronized int addDocument(Document JavaDoc doc) {
146         Integer JavaDoc docID = getIDInteger(doc);
147         if (docID != null) { // already added
148
return docID.intValue();
149         }
150
151     if (docRefsCount >= docRefs.length) {
152         docRefs = realloc(docRefs);
153     }
154     
155         docRefs[docRefsCount] = new WeakReference JavaDoc<Document JavaDoc>(doc);
156         doc.putProperty(DOCUMENT_ID_PROP, new Integer JavaDoc(docRefsCount));
157     return docRefsCount++;
158     }
159
160     /** Add component to registry. If the component is already registered
161      * it returns the existing} ID. The document that is currently assigned
162      * to the component is _not_ registered automatically.
163      * @return ID of the component
164      */

165     public static synchronized int addComponent(JTextComponent JavaDoc c) {
166         int compID = getIDImpl(c);
167         if (compID != -1) {
168             if (compRefs[compID] == null) { // unregistered previously by removeComponent()
169
compRefs[compID] = new WeakReference JavaDoc<JTextComponent JavaDoc>(c);
170             }
171             return compID; // already registered
172
}
173     
174     if (compRefsCount >= compRefs.length) {
175         compRefs = realloc(compRefs);
176     }
177
178         compRefs[compRefsCount] = new WeakReference JavaDoc<JTextComponent JavaDoc>(c);
179         c.putClientProperty(COMPONENT_ID_PROP, new Integer JavaDoc(compRefsCount));
180         return compRefsCount++;
181     }
182
183     /** Remove component from registry. It's usually done when
184      * the UI of the component is being deinstalled.
185      * @return ID that the component had in the registry. The possible
186      * new ID will be different from this one. -1 will be returned
187      * if the component was not yet added to the registry.
188      */

189     public static synchronized int removeComponent(JTextComponent JavaDoc c) {
190         int compID = getIDImpl(c);
191     
192     if (compID != -1) {
193         compRefs[compID] = null;
194         // Search whether was activated
195
for (int i = compAct.size() - 1; i >= 0; i--) {
196         if (compAct.get(i) == compID) {
197             compAct.remove(i);
198             break;
199         }
200         }
201     }
202     
203         return compID;
204     }
205
206     /** Put the component to the first position in the array of last accessed
207     * components. The activate of document is also called automatically.
208     */

209     public static void activate(JTextComponent JavaDoc c) {
210         boolean activated = true;
211         synchronized (DocumentsRegistry.class) {
212             int compID = getIDImpl(c);
213             if (compID == -1) { // c not registered
214
return;
215             }
216             
217             int actSize = compAct.size();
218             int ind = 0;
219             while (ind < actSize) {
220                 int id = compAct.get(ind);
221                 if (id == compID) { // found
222
if (ind == 0) {
223                         break;
224                     }
225                     compAct.add(0, compAct.remove(ind));
226                     activated = true;
227                     break;
228                 }
229                 
230                 ind++;
231             }
232             
233             if (ind == actSize) {
234                 compAct.add(0, compID);
235                 activated = true;
236             }
237
238             // Try to activate component's document too
239
if (doActivate(c.getDocument())) {
240                 activated = true;
241             }
242         }
243         
244         if (activated) {
245             PCS.firePropertyChange(PROP_ACTIVE_COMPONENT, null, c);
246         }
247     }
248
249     /** Put the document to the first position in the array of last accessed
250      * documents. The document must be registered otherwise nothing
251      * is done.
252      * @param doc document to be activated
253      */

254     public static void activate(Document JavaDoc doc) {
255         boolean activated;
256         synchronized (DocumentsRegistry.class) {
257             activated = doActivate(doc);
258     }
259
260         if (activated) {
261             PCS.firePropertyChange(PROP_ACTIVE_DOCUMENT, null, doc);
262         }
263     }
264     
265     public static synchronized Document JavaDoc getMostActiveDocument() {
266         return getValidDoc(0, true);
267     }
268
269     public static synchronized Document JavaDoc getLeastActiveDocument() {
270         int lastInd = docAct.size() - 1;
271         return getValidDoc(lastInd, false);
272     }
273
274     public static Document JavaDoc getLessActiveDocument(Document JavaDoc doc) {
275         return getLessActiveDocument(getID(doc));
276     }
277
278     public static synchronized Document JavaDoc getLessActiveDocument(int docID) {
279         return getNextActiveDoc(docID, true);
280     }
281
282     public static Document JavaDoc getMoreActiveDocument(Document JavaDoc doc) {
283         return getMoreActiveDocument(getID(doc));
284     }
285
286     public static synchronized Document JavaDoc getMoreActiveDocument(int docID) {
287         return getNextActiveDoc(docID, false);
288     }
289
290     /** Get the iterator over the active documents. It starts with
291      * the most active document till the least active document.
292      * It's just the current snapshot so the iterator will
293      * not reflect future changes.
294      */

295     public static synchronized Iterator JavaDoc getDocumentIterator() {
296         consolidate();
297
298         ArrayList JavaDoc<Document JavaDoc> docList = new ArrayList JavaDoc<Document JavaDoc>();
299         int actSize = docAct.size();
300         for (int i = 0; i < actSize; i++) {
301             int ind = docAct.get(i);
302             WeakReference JavaDoc wr = docRefs[ind];
303             if (wr != null) {
304                 Object JavaDoc doc = wr.get();
305                 if (doc != null) {
306                     docList.add((Document JavaDoc)doc);
307                 }
308             }
309         }
310
311         return docList.iterator();
312     }
313
314     public static synchronized JTextComponent JavaDoc getMostActiveComponent() {
315         return getValidComp(0, true);
316     }
317
318     public static synchronized JTextComponent JavaDoc getLeastActiveComponent() {
319         int lastInd = compAct.size() - 1;
320         return getValidComp(lastInd, false);
321     }
322
323     public static JTextComponent JavaDoc getLessActiveComponent(JTextComponent JavaDoc c) {
324         return getLessActiveComponent(getID(c));
325     }
326
327     public static synchronized JTextComponent JavaDoc getLessActiveComponent(int compID) {
328         return getNextActiveComp(compID, true);
329     }
330
331     public static JTextComponent JavaDoc getMoreActiveComponent(JTextComponent JavaDoc c) {
332         return getMoreActiveComponent(getID(c));
333     }
334
335     public static synchronized JTextComponent JavaDoc getMoreActiveComponent(int compID) {
336         return getNextActiveComp(compID, false);
337     }
338
339     /** Get the iterator over the active components. It starts with
340     * the most active component till the least active component.
341     */

342     public static synchronized Iterator JavaDoc getComponentIterator() {
343     consolidate();
344
345         ArrayList JavaDoc<JTextComponent JavaDoc> compList = new ArrayList JavaDoc<JTextComponent JavaDoc>();
346         int actSize = compAct.size();
347         for (int i = 0; i < actSize; i++) {
348             int ind = compAct.get(i);
349             WeakReference JavaDoc wr = compRefs[ind];
350             if (wr != null) {
351                 Object JavaDoc comp = wr.get();
352                 if (comp != null) {
353                     compList.add((JTextComponent JavaDoc) comp);
354                 }
355             }
356         }
357
358         return compList.iterator();
359     }
360
361     private static WeakReference JavaDoc[] realloc(WeakReference JavaDoc[] refs) {
362     WeakReference JavaDoc[] tmp = new WeakReference JavaDoc[refs.length * 2 + 4];
363     System.arraycopy(refs, 0, tmp, 0, refs.length);
364     return tmp;
365     }
366     
367     private static void consolidate() {
368     while (++consolidateCounter >= 20) { // after every 20th call
369
consolidateCounter = 0;
370         
371         // Remove empty document references
372
for (int i = docAct.size() - 1; i >= 0; i--) {
373         int ind = docAct.get(i);
374         WeakReference JavaDoc wr = docRefs[ind];
375         if (wr != null) {
376             if (wr.get() == null) { // empty reference
377
docAct.remove(i);
378             docRefs[ind] = null;
379             }
380         }
381         }
382
383         // Remove empty component references
384
for (int i = compAct.size() - 1; i >= 0; i--) {
385         int ind = compAct.get(i);
386         WeakReference JavaDoc wr = compRefs[ind];
387         if (wr != null) {
388             if (wr.get() == null) { // empty reference
389
compAct.remove(i);
390             compRefs[ind] = null;
391             }
392         }
393         }
394     }
395     }
396
397     private static int getIDImpl(JTextComponent JavaDoc c) {
398         Integer JavaDoc id = c == null ? null : (Integer JavaDoc)c.getClientProperty(COMPONENT_ID_PROP);
399         return id == null ? -1 : id.intValue();
400     }
401
402     private static Integer JavaDoc getIDInteger(Document JavaDoc doc) {
403     if (doc == null) {
404             return null;
405         }
406
407         return (Integer JavaDoc)doc.getProperty(DOCUMENT_ID_PROP);
408     }
409
410     private static boolean doActivate(Document JavaDoc doc) {
411     Integer JavaDoc docIDInteger = getIDInteger(doc);
412     
413     if (docIDInteger == null) {
414         return false; // document not added to registry
415
}
416
417         int docID = (docIDInteger != null) ? docIDInteger.intValue() : -1;
418
419     int size = docAct.size();
420     for (int ind = 0; ind < size; ind++) {
421         int id = docAct.get(ind);
422         if (id == docID) {
423         if (ind == 0) { // no change
424
return false;
425         }
426
427         docAct.add(0, docAct.remove(ind));
428         return true;
429         }
430     }
431     
432         docAct.add(0, docIDInteger);
433     return true;
434     }
435
436     private static Document JavaDoc getValidDoc(int ind, boolean forward) {
437     consolidate();
438
439     int actSize = docAct.size();
440         while (ind >= 0 && ind < actSize) {
441             int docID = docAct.get(ind);
442         WeakReference JavaDoc wr = docRefs[docID];
443             Document JavaDoc doc = (wr != null) ? (Document JavaDoc)wr.get() : null;
444             if (doc != null) {
445                 return doc;
446             }
447             ind += forward ? +1 : -1;
448         }
449         return null;
450     }
451
452     private static Document JavaDoc getNextActiveDoc(int docID, boolean forward) {
453     consolidate();
454
455         int actSize = docAct.size();
456         int ind = forward ? 0 : (actSize - 1);
457         while (ind >= 0 && ind < actSize) {
458             if (docAct.get(ind) == docID) {
459                 ind += forward ? +1 : -1; // get next one
460
return getValidDoc(ind, forward);
461             }
462             ind += forward ? +1 : -1;
463         }
464         return null;
465     }
466
467     private static JTextComponent JavaDoc getValidComp(int ind, boolean forward) {
468     consolidate();
469
470     int actSize = compAct.size();
471         while (ind >= 0 && ind < actSize) {
472             int compID = compAct.get(ind);
473         WeakReference JavaDoc wr = compRefs[compID];
474             JTextComponent JavaDoc c = (wr != null) ? (JTextComponent JavaDoc)wr.get() : null;
475             if (c != null) {
476                 return c;
477             }
478             ind += forward ? +1 : -1;
479         }
480         return null;
481     }
482
483     private static JTextComponent JavaDoc getNextActiveComp(int compID, boolean forward) {
484         int actSize = compAct.size();
485         int ind = forward ? 0 : (actSize - 1);
486         while (ind >= 0 && ind < actSize) {
487             if (compAct.get(ind) == compID) {
488                 ind += forward ? +1 : -1;
489                 return getValidComp(ind, forward);
490             }
491             ind += forward ? +1 : -1;
492         }
493         return null;
494     }
495
496     /** Debug the registry into string. */
497     public static synchronized String JavaDoc registryToString() {
498         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
499         sb.append("Document References:\n"); // NOI18N
500
for (int i = 0; i < docRefsCount; i++) {
501             WeakReference JavaDoc wr = docRefs[i];
502             sb.append("docRefs[" + i + "]=" + ((wr != null) ? wr.get() : "null") + "\n"); // NOI18N
503
}
504         sb.append("Component References:\n"); // NOI18N
505
for (int i = 0; i < compRefsCount; i++) {
506             WeakReference JavaDoc wr = (WeakReference JavaDoc)compRefs[i];
507             sb.append("compRefs[" + i + "]=" + ((wr != null) ? wr.get() : "null") + "\n"); // NOI18N
508
}
509         sb.append("\nActive Document Indexes:\n"); // NOI18N
510
for (int i = 0; i < docAct.size(); i++) {
511             sb.append(docAct.get(i));
512             if (i != docAct.size() - 1) {
513                 sb.append(", "); // NOI18N
514
}
515         }
516         sb.append("\nActive Component Indexes:\n"); // NOI18N
517
for (int i = 0; i < compAct.size(); i++) {
518             sb.append(compAct.get(i));
519             if (i != compAct.size() - 1) {
520                 sb.append(", "); // NOI18N
521
}
522         }
523
524         return sb.toString();
525     }
526
527     private DocumentsRegistry() {
528         // to prevent creating instances
529
}
530 }
531
Popular Tags