KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > util > Enumerations


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.util;
21
22 import java.util.ArrayList JavaDoc;
23 import java.util.Arrays JavaDoc;
24 import java.util.Collection JavaDoc;
25 import java.util.Collections JavaDoc;
26 import java.util.Enumeration JavaDoc;
27 import java.util.HashSet JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.NoSuchElementException JavaDoc;
30 import java.util.Set JavaDoc;
31
32 /**
33  * Factory methods for various types of {@link Enumeration}.
34  * Allows composition of existing enumerations, filtering their contents, and/or modifying them.
35  * All of this is designed to be done lazily, i.e. elements created on demand.
36  * @since 4.37
37  * @author Jaroslav Tulach
38  * @see NbCollections#checkedEnumerationByFilter
39  * @see NbCollections#iterable(Enumeration)
40  */

41 public final class Enumerations extends Object JavaDoc {
42     /** No instances */
43     private Enumerations() {
44     }
45
46     /**
47      * An empty enumeration.
48      * Always returns <code>false</code> from
49      * <code>empty().hasMoreElements()</code> and throws <code>NoSuchElementException</code>
50      * from <code>empty().nextElement()</code>.
51      * @return the enumeration
52      */

53     public static final <T> Enumeration JavaDoc<T> empty() {
54         Collection JavaDoc<T> emptyL = Collections.emptyList();
55         return Collections.enumeration(emptyL);
56     }
57
58     /**
59      * Creates an enumeration with one element.
60      * @param obj the element to be present in the enumeration.
61      * @return enumeration
62      */

63     public static <T> Enumeration JavaDoc<T> singleton(T obj) {
64         return Collections.enumeration(Collections.singleton(obj));
65     }
66
67     /**
68      * Concatenates the content of two enumerations into one.
69      * Until the
70      * end of <code>en1</code> is reached its elements are being served.
71      * As soon as the <code>en1</code> has no more elements, the content
72      * of <code>en2</code> is being returned.
73      *
74      * @param en1 first enumeration
75      * @param en2 second enumeration
76      * @return enumeration
77      */

78     public static <T> Enumeration JavaDoc<T> concat(Enumeration JavaDoc<? extends T> en1, Enumeration JavaDoc<? extends T> en2) {
79         ArrayList JavaDoc<Enumeration JavaDoc<? extends T>> two = new ArrayList JavaDoc<Enumeration JavaDoc<? extends T>>();
80         two.add(en1);
81         two.add(en2);
82         return new SeqEn<T>(Collections.enumeration(two));
83     }
84
85     /**
86      * Concatenates the content of many enumerations.
87      * The input value
88      * is enumeration of Enumeration elements and the result is composed
89      * all their content. Each of the provided enumeration is fully read
90      * and their content returned before the next enumeration is asked for
91      * their elements.
92      *
93      * @param enumOfEnums Enumeration of Enumeration elements
94      * @return enumeration
95      */

96     public static <T> Enumeration JavaDoc<T> concat(Enumeration JavaDoc<? extends Enumeration JavaDoc<? extends T>> enumOfEnums) {
97         return new SeqEn<T>(enumOfEnums);
98     }
99
100     /**
101      * Filters the input enumeration to new one that should contain
102      * each of the provided elements just once.
103      * The elements are compared
104      * using their default <code>equals</code> and <code>hashCode</code> methods.
105      *
106      * @param en enumeration to filter
107      * @return enumeration without duplicated items
108      */

109     public static <T> Enumeration JavaDoc<T> removeDuplicates(Enumeration JavaDoc<T> en) {
110         class RDupls implements Processor<T,T> {
111             private Set JavaDoc<T> set = new HashSet JavaDoc<T>();
112
113             public T process(T o, Collection JavaDoc<T> nothing) {
114                 return set.add(o) ? o : null;
115             }
116         }
117
118         return filter(en, new RDupls());
119     }
120
121     /**
122      * Returns an enumeration that iterates over provided array.
123      * @param arr the array of object
124      * @return enumeration of those objects
125      */

126     public static <T> Enumeration JavaDoc<T> array(T... arr) {
127         return Collections.enumeration(Arrays.asList(arr));
128     }
129
130     /**
131      * Removes all <code>null</code>s from the input enumeration.
132      * @param en enumeration that can contain nulls
133      * @return new enumeration without null values
134      */

135     public static <T> Enumeration JavaDoc<T> removeNulls(Enumeration JavaDoc<T> en) {
136         return filter(en, new RNulls<T>());
137     }
138
139     /**
140      * For each element of the input enumeration <code>en</code> asks the
141      * {@link Processor} to provide a replacement.
142      * The <code>toAdd</code> argument of the processor is always null.
143      * <p>
144      * Example to convert any objects into strings:
145      * <pre>
146      * Processor convertToString = new Processor() {
147      * public Object process(Object obj, Collection alwaysNull) {
148      * return obj.toString(); // converts to string
149      * }
150      * };
151      * Enumeration strings = Enumerations.convert(elems, convertToString);
152      * </pre>
153      *
154      * @param en enumeration of any objects
155      * @param processor a callback processor for the elements (its toAdd arguments is always null)
156      * @return new enumeration where all elements has been processed
157      */

158     public static <T,R> Enumeration JavaDoc<R> convert(Enumeration JavaDoc<? extends T> en, Processor<T,R> processor) {
159         return new AltEn<T,R>(en, processor);
160     }
161
162     /**
163      * Filters some elements out from the input enumeration.
164      * Just make the
165      * {@link Processor} return <code>null</code>. Please notice the <code>toAdd</code>
166      * argument of the processor is always <code>null</code>.
167      * <p>
168      * Example to remove all objects that are not strings:
169      * <pre>
170      * Processor onlyString = new Processor() {
171      * public Object process(Object obj, Collection alwaysNull) {
172      * if (obj instanceof String) {
173      * return obj;
174      * } else {
175      * return null;
176      * }
177      * }
178      * };
179      * Enumeration strings = Enumerations.filter(elems, onlyString);
180      * </pre>
181      *
182      * @param en enumeration of any objects
183      * @param filter a callback processor for the elements (its toAdd arguments is always null)
184      * @return new enumeration which does not include non-processed (returned null from processor) elements
185      * @see NbCollections#checkedEnumerationByFilter
186      */

187     public static <T,R> Enumeration JavaDoc<R> filter(Enumeration JavaDoc<? extends T> en, Processor<T,R> filter) {
188         return new FilEn<T,R>(en, filter);
189     }
190
191     /**
192      * Support for breadth-first enumerating.
193      * Before any element is returned
194      * for the resulting enumeration it is processed in the {@link Processor} and
195      * the processor is allowed to modify it and also add additional elements
196      * at the (current) end of the <q>queue</q> by calling <code>toAdd.add</code>
197      * or <code>toAdd.addAll</code>. No other methods can be called on the
198      * provided <code>toAdd</code> collection.
199      * <p>
200      * Example of doing breadth-first walk through a tree:
201      * <pre>
202      * Processor queueSubnodes = new Processor() {
203      * public Object process(Object obj, Collection toAdd) {
204      * Node n = (Node)obj;
205      * toAdd.addAll (n.getChildrenList());
206      * return n;
207      * }
208      * };
209      * Enumeration strings = Enumerations.queue(elems, queueSubnodes);
210      * </pre>
211      *
212      * @param en initial content of the resulting enumeration
213      * @param filter the processor that is called for each element and can
214      * add and addAll elements to its toAdd Collection argument and
215      * also change the value to be returned
216      * @return enumeration with the initial and queued content (it can contain
217      * <code>null</code> if the filter returned <code>null</code> from its
218      * {@link Processor#process} method.
219      */

220     public static <T,R> Enumeration JavaDoc<R> queue(Enumeration JavaDoc<? extends T> en, Processor<T,R> filter) {
221         QEn<T,R> q = new QEn<T,R>(filter);
222
223         while (en.hasMoreElements()) {
224             q.put(en.nextElement());
225         }
226
227         return q;
228     }
229
230     /**
231      * Processor interface that can filter out objects from the enumeration,
232      * change them or add aditional objects to the end of the current enumeration.
233      */

234     public static interface Processor<T,R> {
235         /** @param original the object that is going to be returned from the enumeration right now
236          * @return a replacement for this object
237          * @param toAdd can be non-null if one can add new objects at the end of the enumeration
238          */

239         public R process(T original, Collection JavaDoc<T> toAdd);
240     }
241
242     /** Altering enumeration implementation */
243     private static final class AltEn<T,R> extends Object JavaDoc implements Enumeration JavaDoc<R> {
244         /** enumeration to filter */
245         private Enumeration JavaDoc<? extends T> en;
246
247         /** map to alter */
248         private Processor<T,R> process;
249
250         /**
251         * @param en enumeration to filter
252         */

253         public AltEn(Enumeration JavaDoc<? extends T> en, Processor<T,R> process) {
254             this.en = en;
255             this.process = process;
256         }
257
258         /** @return true if there is more elements in the enumeration
259         */

260         public boolean hasMoreElements() {
261             return en.hasMoreElements();
262         }
263
264         /** @return next object in the enumeration
265         * @exception NoSuchElementException can be thrown if there is no next object
266         * in the enumeration
267         */

268         public R nextElement() {
269             return process.process(en.nextElement(), null);
270         }
271     }
272      // end of AltEn
273

274     /** Sequence of enumerations */
275     private static final class SeqEn<T> extends Object JavaDoc implements Enumeration JavaDoc<T> {
276         /** enumeration of Enumerations */
277         private Enumeration JavaDoc<? extends Enumeration JavaDoc<? extends T>> en;
278
279         /** current enumeration */
280         private Enumeration JavaDoc<? extends T> current;
281
282         /** is {@link #current} up-to-date and has more elements?
283         * The combination <CODE>current == null</CODE> and
284         * <CODE>checked == true means there are no more elements
285         * in this enumeration.
286         */

287         private boolean checked = false;
288
289         /** Constructs new enumeration from already existing. The elements
290         * of <CODE>en</CODE> should be also enumerations. The resulting
291         * enumeration contains elements of such enumerations.
292         *
293         * @param en enumeration of Enumerations that should be sequenced
294         */

295         public SeqEn(Enumeration JavaDoc<? extends Enumeration JavaDoc <? extends T>> en) {
296             this.en = en;
297         }
298
299         /** Ensures that current enumeration is set. If there aren't more
300         * elements in the Enumerations, sets the field <CODE>current</CODE> to null.
301         */

302         private void ensureCurrent() {
303             while ((current == null) || !current.hasMoreElements()) {
304                 if (en.hasMoreElements()) {
305                     current = en.nextElement();
306                 } else {
307                     // no next valid enumeration
308
current = null;
309
310                     return;
311                 }
312             }
313         }
314
315         /** @return true if we have more elements */
316         public boolean hasMoreElements() {
317             if (!checked) {
318                 ensureCurrent();
319                 checked = true;
320             }
321
322             return current != null;
323         }
324
325         /** @return next element
326         * @exception NoSuchElementException if there is no next element
327         */

328         public T nextElement() {
329             if (!checked) {
330                 ensureCurrent();
331             }
332
333             if (current != null) {
334                 checked = false;
335
336                 return current.nextElement();
337             } else {
338                 checked = true;
339                 throw new java.util.NoSuchElementException JavaDoc();
340             }
341         }
342     }
343      // end of SeqEn
344

345     /** QueueEnumeration
346      */

347     private static class QEn<T,R> extends Object JavaDoc implements Enumeration JavaDoc<R> {
348         /** next object to be returned */
349         private ListItem<T> next = null;
350
351         /** last object in the queue */
352         private ListItem<T> last = null;
353
354         /** processor to use */
355         private Processor<T,R> processor;
356
357         public QEn(Processor<T,R> p) {
358             this.processor = p;
359         }
360
361         /** Put adds new object to the end of queue.
362         * @param o the object to add
363         */

364         public void put(T o) {
365             if (last != null) {
366                 ListItem<T> li = new ListItem<T>(o);
367                 last.next = li;
368                 last = li;
369             } else {
370                 next = last = new ListItem<T>(o);
371             }
372         }
373
374         /** Adds array of objects into the queue.
375         * @param arr array of objects to put into the queue
376         */

377         public void put(Collection JavaDoc<? extends T> arr) {
378             for (T e : arr) {
379                 put(e);
380             }
381         }
382
383         /** Is there any next object?
384         * @return true if there is next object, false otherwise
385         */

386         public boolean hasMoreElements() {
387             return next != null;
388         }
389
390         /** @return next object in enumeration
391         * @exception NoSuchElementException if there is no next object
392         */

393         public R nextElement() {
394             if (next == null) {
395                 throw new NoSuchElementException JavaDoc();
396             }
397
398             T res = next.object;
399
400             if ((next = next.next) == null) {
401                 last = null;
402             }
403
404             ;
405
406             ToAdd<T,R> toAdd = new ToAdd<T,R>(this);
407             R out = processor.process(res, toAdd);
408             toAdd.finish();
409
410             return out;
411         }
412
413         /** item in linked list of Objects */
414         private static final class ListItem<T> {
415             T object;
416             ListItem<T> next;
417
418             /** @param o the object for this item */
419             ListItem(T o) {
420                 object = o;
421             }
422         }
423
424         /** Temporary collection that supports only add and addAll operations*/
425         private static final class ToAdd<T,R> extends Object JavaDoc implements Collection JavaDoc<T> {
426             private QEn<T,R> q;
427
428             public ToAdd(QEn<T,R> q) {
429                 this.q = q;
430             }
431
432             public void finish() {
433                 this.q = null;
434             }
435
436             public boolean add(T o) {
437                 q.put(o);
438
439                 return true;
440             }
441
442             public boolean addAll(Collection JavaDoc<? extends T> c) {
443                 q.put(c);
444
445                 return true;
446             }
447
448             private String JavaDoc msg() {
449                 return "Only add and addAll are implemented"; // NOI18N
450
}
451
452             public void clear() {
453                 throw new UnsupportedOperationException JavaDoc(msg());
454             }
455
456             public boolean contains(Object JavaDoc o) {
457                 throw new UnsupportedOperationException JavaDoc(msg());
458             }
459
460             public boolean containsAll(Collection JavaDoc c) {
461                 throw new UnsupportedOperationException JavaDoc(msg());
462             }
463
464             public boolean isEmpty() {
465                 throw new UnsupportedOperationException JavaDoc(msg());
466             }
467
468             public Iterator JavaDoc<T> iterator() {
469                 throw new UnsupportedOperationException JavaDoc(msg());
470             }
471
472             public boolean remove(Object JavaDoc o) {
473                 throw new UnsupportedOperationException JavaDoc(msg());
474             }
475
476             public boolean removeAll(Collection JavaDoc c) {
477                 throw new UnsupportedOperationException JavaDoc(msg());
478             }
479
480             public boolean retainAll(Collection JavaDoc c) {
481                 throw new UnsupportedOperationException JavaDoc(msg());
482             }
483
484             public int size() {
485                 throw new UnsupportedOperationException JavaDoc(msg());
486             }
487
488             public Object JavaDoc[] toArray() {
489                 throw new UnsupportedOperationException JavaDoc(msg());
490             }
491
492             public<X> X[] toArray(X[] a) {
493                 throw new UnsupportedOperationException JavaDoc(msg());
494             }
495         }
496          // end of ToAdd
497
}
498      // end of QEn
499

500     /** Filtering enumeration */
501     private static final class FilEn<T,R> extends Object JavaDoc implements Enumeration JavaDoc<R> {
502         /** marker object stating there is no nexte element prepared */
503         private static final Object JavaDoc EMPTY = new Object JavaDoc();
504
505         /** enumeration to filter */
506         private Enumeration JavaDoc<? extends T> en;
507
508         /** element to be returned next time or {@link #EMPTY} if there is
509         * no such element prepared */

510         private R next = empty();
511
512         /** the set to use as filter */
513         private Processor<T,R> filter;
514
515         /**
516         * @param en enumeration to filter
517         */

518         public FilEn(Enumeration JavaDoc<? extends T> en, Processor<T,R> filter) {
519             this.en = en;
520             this.filter = filter;
521         }
522
523         /** @return true if there is more elements in the enumeration
524         */

525         public boolean hasMoreElements() {
526             if (next != empty()) {
527                 // there is a object already prepared
528
return true;
529             }
530
531             while (en.hasMoreElements()) {
532                 // read next
533
next = filter.process(en.nextElement(), null);
534
535                 if (next != null) {
536                     // if the object is accepted
537
return true;
538                 }
539
540                 ;
541             }
542
543             next = empty();
544
545             return false;
546         }
547
548         /** @return next object in the enumeration
549         * @exception NoSuchElementException can be thrown if there is no next object
550         * in the enumeration
551         */

552         public R nextElement() {
553             if ((next == EMPTY) && !hasMoreElements()) {
554                 throw new NoSuchElementException JavaDoc();
555             }
556
557             R res = next;
558             next = empty();
559
560             return res;
561         }
562
563         @SuppressWarnings JavaDoc("unchecked")
564         private R empty() {
565             return (R)EMPTY;
566         }
567     }
568      // end of FilEn
569

570     /** Returns true from contains if object is not null */
571     private static class RNulls<T> implements Processor<T,T> {
572         public T process(T original, Collection JavaDoc<T> toAdd) {
573             return original;
574         }
575     }
576      // end of RNulls
577
}
578
Popular Tags