Checking params for null.
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4 * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
6 * The contents of this file are subject to the terms of either the GNU
7 * General Public License Version 2 only ("GPL") or the Common
8 * Development and Distribution License("CDDL") (collectively, the
9 * "License"). You may not use this file except in compliance with the
10 * License. You can obtain a copy of the License at
11 * http://www.netbeans.org/cddl-gplv2.html
12 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13 * specific language governing permissions and limitations under the
14 * License. When distributing the software, include this License Header
15 * Notice in each file and include the License file at
16 * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17 * particular file as subject to the "Classpath" exception as provided
18 * by Sun in the GPL Version 2 section of the License file that
19 * accompanied this code. If applicable, add the following below the
20 * License Header, with the fields enclosed by brackets [] replaced by
21 * your own identifying information:
22 * "Portions Copyrighted [year] [name of copyright owner]"
26 * The Original Software is NetBeans. The Initial Developer of the Original
27 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28 * Microsystems, Inc. All Rights Reserved.
30 * If you wish your version of this file to be governed by only the CDDL
31 * or only the GPL Version 2, indicate your decision by adding
32 * "[Contributor] elects to include this software in this distribution
33 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34 * single choice of license, a recipient has the option to distribute
35 * your version of this file under either the CDDL, the GPL Version 2 or
36 * to extend the choice of license to its licensees as provided above.
37 * However, if you add GPL Version 2 code and therefore, elected the GPL
38 * Version 2 license, then the option applies only if the new code is
39 * made subject to such option by the copyright holder.
42 package org.openide.util;
44 import java.util.ArrayList;
45 import java.util.Arrays;
46 import java.util.Collection;
47 import java.util.Collections;
48 import java.util.Enumeration;
49 import java.util.HashSet;
50 import java.util.Iterator;
51 import java.util.NoSuchElementException;
55 * Factory methods for various types of {@link Enumeration}.
56 * Allows composition of existing enumerations, filtering their contents, and/or modifying them.
57 * All of this is designed to be done lazily, i.e. elements created on demand.
59 * @author Jaroslav Tulach
60 * @see NbCollections#checkedEnumerationByFilter
61 * @see NbCollections#iterable(Enumeration)
63 public final class Enumerations extends Object {
65 private Enumerations() {
69 * An empty enumeration.
70 * Always returns <code>false</code> from
71 * <code>empty().hasMoreElements()</code> and throws <code>NoSuchElementException</code>
72 * from <code>empty().nextElement()</code>.
73 * @return the enumeration
75 public static final <T> Enumeration<T> empty() {
76 Collection<T> emptyL = Collections.emptyList();
77 return Collections.enumeration(emptyL);
81 * Creates an enumeration with one element.
82 * @param obj the element to be present in the enumeration.
85 public static <T> Enumeration<T> singleton(T obj) {
86 return Collections.enumeration(Collections.singleton(obj));
90 * Concatenates the content of two enumerations into one.
92 * end of <code>en1</code> is reached its elements are being served.
93 * As soon as the <code>en1</code> has no more elements, the content
94 * of <code>en2</code> is being returned.
96 * @param en1 first enumeration
97 * @param en2 second enumeration
100 public static <T> Enumeration<T> concat(Enumeration<? extends T> en1, Enumeration<? extends T> en2) {
101 ArrayList<Enumeration<? extends T>> two = new ArrayList<Enumeration<? extends T>>();
104 return new SeqEn<T>(Collections.enumeration(two));
108 * Concatenates the content of many enumerations.
110 * is enumeration of Enumeration elements and the result is composed
111 * all their content. Each of the provided enumeration is fully read
112 * and their content returned before the next enumeration is asked for
115 * @param enumOfEnums Enumeration of Enumeration elements
116 * @return enumeration
118 public static <T> Enumeration<T> concat(Enumeration<? extends Enumeration<? extends T>> enumOfEnums) {
119 return new SeqEn<T>(enumOfEnums);
123 * Filters the input enumeration to new one that should contain
124 * each of the provided elements just once.
125 * The elements are compared
126 * using their default <code>equals</code> and <code>hashCode</code> methods.
128 * @param en enumeration to filter
129 * @return enumeration without duplicated items
131 public static <T> Enumeration<T> removeDuplicates(Enumeration<T> en) {
132 class RDupls implements Processor<T,T> {
133 private Set<T> set = new HashSet<T>();
135 public T process(T o, Collection<T> nothing) {
136 return set.add(o) ? o : null;
140 return filter(en, new RDupls());
144 * Returns an enumeration that iterates over provided array.
145 * @param arr the array of object
146 * @return enumeration of those objects
148 public static <T> Enumeration<T> array(T... arr) {
149 return Collections.enumeration(Arrays.asList(arr));
153 * Removes all <code>null</code>s from the input enumeration.
154 * @param en enumeration that can contain nulls
155 * @return new enumeration without null values
157 public static <T> Enumeration<T> removeNulls(Enumeration<T> en) {
158 return filter(en, new RNulls<T>());
162 * For each element of the input enumeration <code>en</code> asks the
163 * {@link Processor} to provide a replacement.
164 * The <code>toAdd</code> argument of the processor is always null.
166 * Example to convert any objects into strings:
168 * Processor convertToString = new Processor() {
169 * public Object process(Object obj, Collection alwaysNull) {
170 * return obj.toString(); // converts to string
173 * Enumeration strings = Enumerations.convert(elems, convertToString);
176 * @param en enumeration of any objects
177 * @param processor a callback processor for the elements (its toAdd arguments is always null)
178 * @return new enumeration where all elements has been processed
180 public static <T,R> Enumeration<R> convert(Enumeration<? extends T> en, Processor<T,R> processor) {
181 return new AltEn<T,R>(en, processor);
185 * Filters some elements out from the input enumeration.
187 * {@link Processor} return <code>null</code>. Please notice the <code>toAdd</code>
188 * argument of the processor is always <code>null</code>.
190 * Example to remove all objects that are not strings:
192 * Processor onlyString = new Processor() {
193 * public Object process(Object obj, Collection alwaysNull) {
194 * if (obj instanceof String) {
201 * Enumeration strings = Enumerations.filter(elems, onlyString);
204 * @param en enumeration of any objects
205 * @param filter a callback processor for the elements (its toAdd arguments is always null)
206 * @return new enumeration which does not include non-processed (returned null from processor) elements
207 * @see NbCollections#checkedEnumerationByFilter
209 public static <T,R> Enumeration<R> filter(Enumeration<? extends T> en, Processor<T,R> filter) {
210 Parameters.notNull("en", en);
211 Parameters.notNull("filter", filter);
212 return new FilEn<T,R>(en, filter);
216 * Support for breadth-first enumerating.
217 * Before any element is returned
218 * for the resulting enumeration it is processed in the {@link Processor} and
219 * the processor is allowed to modify it and also add additional elements
220 * at the (current) end of the <q>queue</q> by calling <code>toAdd.add</code>
221 * or <code>toAdd.addAll</code>. No other methods can be called on the
222 * provided <code>toAdd</code> collection.
224 * Example of doing breadth-first walk through a tree:
226 * Processor queueSubnodes = new Processor() {
227 * public Object process(Object obj, Collection toAdd) {
228 * Node n = (Node)obj;
229 * toAdd.addAll (n.getChildrenList());
233 * Enumeration strings = Enumerations.queue(elems, queueSubnodes);
236 * @param en initial content of the resulting enumeration
237 * @param filter the processor that is called for each element and can
238 * add and addAll elements to its toAdd Collection argument and
239 * also change the value to be returned
240 * @return enumeration with the initial and queued content (it can contain
241 * <code>null</code> if the filter returned <code>null</code> from its
242 * {@link Processor#process} method.
244 public static <T,R> Enumeration<R> queue(Enumeration<? extends T> en, Processor<T,R> filter) {
245 QEn<T,R> q = new QEn<T,R>(filter);
247 while (en.hasMoreElements()) {
248 q.put(en.nextElement());
255 * Processor interface that can filter out objects from the enumeration,
256 * change them or add aditional objects to the end of the current enumeration.
258 public static interface Processor<T,R> {
259 /** @param original the object that is going to be returned from the enumeration right now
260 * @return a replacement for this object
261 * @param toAdd can be non-null if one can add new objects at the end of the enumeration
263 public R process(T original, Collection<T> toAdd);
266 /** Altering enumeration implementation */
267 private static final class AltEn<T,R> extends Object implements Enumeration<R> {
268 /** enumeration to filter */
269 private Enumeration<? extends T> en;
272 private Processor<T,R> process;
275 * @param en enumeration to filter
277 public AltEn(Enumeration<? extends T> en, Processor<T,R> process) {
279 this.process = process;
282 /** @return true if there is more elements in the enumeration
284 public boolean hasMoreElements() {
285 return en.hasMoreElements();
288 /** @return next object in the enumeration
289 * @exception NoSuchElementException can be thrown if there is no next object
292 public R nextElement() {
293 return process.process(en.nextElement(), null);
298 /** Sequence of enumerations */
299 private static final class SeqEn<T> extends Object implements Enumeration<T> {
300 /** enumeration of Enumerations */
301 private Enumeration<? extends Enumeration<? extends T>> en;
303 /** current enumeration */
304 private Enumeration<? extends T> current;
306 /** is {@link #current} up-to-date and has more elements?
307 * The combination <CODE>current == null</CODE> and
308 * <CODE>checked == true means there are no more elements
309 * in this enumeration.
311 private boolean checked = false;
313 /** Constructs new enumeration from already existing. The elements
314 * of <CODE>en</CODE> should be also enumerations. The resulting
315 * enumeration contains elements of such enumerations.
317 * @param en enumeration of Enumerations that should be sequenced
319 public SeqEn(Enumeration<? extends Enumeration <? extends T>> en) {
323 /** Ensures that current enumeration is set. If there aren't more
324 * elements in the Enumerations, sets the field <CODE>current</CODE> to null.
326 private void ensureCurrent() {
327 while ((current == null) || !current.hasMoreElements()) {
328 if (en.hasMoreElements()) {
329 current = en.nextElement();
331 // no next valid enumeration
339 /** @return true if we have more elements */
340 public boolean hasMoreElements() {
346 return current != null;
349 /** @return next element
350 * @exception NoSuchElementException if there is no next element
352 public T nextElement() {
357 if (current != null) {
360 return current.nextElement();
363 throw new java.util.NoSuchElementException();
371 private static class QEn<T,R> extends Object implements Enumeration<R> {
372 /** next object to be returned */
373 private ListItem<T> next = null;
375 /** last object in the queue */
376 private ListItem<T> last = null;
378 /** processor to use */
379 private Processor<T,R> processor;
381 public QEn(Processor<T,R> p) {
385 /** Put adds new object to the end of queue.
386 * @param o the object to add
388 public void put(T o) {
390 ListItem<T> li = new ListItem<T>(o);
394 next = last = new ListItem<T>(o);
398 /** Adds array of objects into the queue.
399 * @param arr array of objects to put into the queue
401 public void put(Collection<? extends T> arr) {
407 /** Is there any next object?
408 * @return true if there is next object, false otherwise
410 public boolean hasMoreElements() {
414 /** @return next object in enumeration
415 * @exception NoSuchElementException if there is no next object
417 public R nextElement() {
419 throw new NoSuchElementException();
424 if ((next = next.next) == null) {
430 ToAdd<T,R> toAdd = new ToAdd<T,R>(this);
431 R out = processor.process(res, toAdd);
437 /** item in linked list of Objects */
438 private static final class ListItem<T> {
442 /** @param o the object for this item */
448 /** Temporary collection that supports only add and addAll operations*/
449 private static final class ToAdd<T,R> extends Object implements Collection<T> {
452 public ToAdd(QEn<T,R> q) {
456 public void finish() {
460 public boolean add(T o) {
466 public boolean addAll(Collection<? extends T> c) {
472 private String msg() {
473 return "Only add and addAll are implemented"; // NOI18N
476 public void clear() {
477 throw new UnsupportedOperationException(msg());
480 public boolean contains(Object o) {
481 throw new UnsupportedOperationException(msg());
484 public boolean containsAll(Collection c) {
485 throw new UnsupportedOperationException(msg());
488 public boolean isEmpty() {
489 throw new UnsupportedOperationException(msg());
492 public Iterator<T> iterator() {
493 throw new UnsupportedOperationException(msg());
496 public boolean remove(Object o) {
497 throw new UnsupportedOperationException(msg());
500 public boolean removeAll(Collection c) {
501 throw new UnsupportedOperationException(msg());
504 public boolean retainAll(Collection c) {
505 throw new UnsupportedOperationException(msg());
509 throw new UnsupportedOperationException(msg());
512 public Object[] toArray() {
513 throw new UnsupportedOperationException(msg());
516 public<X> X[] toArray(X[] a) {
517 throw new UnsupportedOperationException(msg());
524 /** Filtering enumeration */
525 private static final class FilEn<T,R> extends Object implements Enumeration<R> {
526 /** marker object stating there is no nexte element prepared */
527 private static final Object EMPTY = new Object();
529 /** enumeration to filter */
530 private Enumeration<? extends T> en;
532 /** element to be returned next time or {@link #EMPTY} if there is
533 * no such element prepared */
534 private R next = empty();
536 /** the set to use as filter */
537 private Processor<T,R> filter;
540 * @param en enumeration to filter
542 public FilEn(Enumeration<? extends T> en, Processor<T,R> filter) {
544 this.filter = filter;
547 /** @return true if there is more elements in the enumeration
549 public boolean hasMoreElements() {
550 if (next != empty()) {
551 // there is a object already prepared
555 while (en.hasMoreElements()) {
557 next = filter.process(en.nextElement(), null);
560 // if the object is accepted
572 /** @return next object in the enumeration
573 * @exception NoSuchElementException can be thrown if there is no next object
576 public R nextElement() {
577 if ((next == EMPTY) && !hasMoreElements()) {
578 throw new NoSuchElementException();
587 @SuppressWarnings("unchecked")
594 /** Returns true from contains if object is not null */
595 private static class RNulls<T> implements Processor<T,T> {
596 public T process(T original, Collection<T> toAdd) {