openide.util/src/org/openide/util/Enumerations.java
author Jesse Glick <jglick@netbeans.org>
Wed, 27 Jan 2010 17:46:23 -0500
changeset 971 b3ae88304dd0
permissions -rw-r--r--
Checking params for null.
jglick@971
     1
/*
jglick@971
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
jglick@971
     3
 *
jglick@971
     4
 * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
jglick@971
     5
 *
jglick@971
     6
 * The contents of this file are subject to the terms of either the GNU
jglick@971
     7
 * General Public License Version 2 only ("GPL") or the Common
jglick@971
     8
 * Development and Distribution License("CDDL") (collectively, the
jglick@971
     9
 * "License"). You may not use this file except in compliance with the
jglick@971
    10
 * License. You can obtain a copy of the License at
jglick@971
    11
 * http://www.netbeans.org/cddl-gplv2.html
jglick@971
    12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
jglick@971
    13
 * specific language governing permissions and limitations under the
jglick@971
    14
 * License.  When distributing the software, include this License Header
jglick@971
    15
 * Notice in each file and include the License file at
jglick@971
    16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
jglick@971
    17
 * particular file as subject to the "Classpath" exception as provided
jglick@971
    18
 * by Sun in the GPL Version 2 section of the License file that
jglick@971
    19
 * accompanied this code. If applicable, add the following below the
jglick@971
    20
 * License Header, with the fields enclosed by brackets [] replaced by
jglick@971
    21
 * your own identifying information:
jglick@971
    22
 * "Portions Copyrighted [year] [name of copyright owner]"
jglick@971
    23
 *
jglick@971
    24
 * Contributor(s):
jglick@971
    25
 *
jglick@971
    26
 * The Original Software is NetBeans. The Initial Developer of the Original
jglick@971
    27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
jglick@971
    28
 * Microsystems, Inc. All Rights Reserved.
jglick@971
    29
 *
jglick@971
    30
 * If you wish your version of this file to be governed by only the CDDL
jglick@971
    31
 * or only the GPL Version 2, indicate your decision by adding
jglick@971
    32
 * "[Contributor] elects to include this software in this distribution
jglick@971
    33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
jglick@971
    34
 * single choice of license, a recipient has the option to distribute
jglick@971
    35
 * your version of this file under either the CDDL, the GPL Version 2 or
jglick@971
    36
 * to extend the choice of license to its licensees as provided above.
jglick@971
    37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
jglick@971
    38
 * Version 2 license, then the option applies only if the new code is
jglick@971
    39
 * made subject to such option by the copyright holder.
jglick@971
    40
 */
jglick@971
    41
jglick@971
    42
package org.openide.util;
jglick@971
    43
jglick@971
    44
import java.util.ArrayList;
jglick@971
    45
import java.util.Arrays;
jglick@971
    46
import java.util.Collection;
jglick@971
    47
import java.util.Collections;
jglick@971
    48
import java.util.Enumeration;
jglick@971
    49
import java.util.HashSet;
jglick@971
    50
import java.util.Iterator;
jglick@971
    51
import java.util.NoSuchElementException;
jglick@971
    52
import java.util.Set;
jglick@971
    53
jglick@971
    54
/**
jglick@971
    55
 * Factory methods for various types of {@link Enumeration}.
jglick@971
    56
 * Allows composition of existing enumerations, filtering their contents, and/or modifying them.
jglick@971
    57
 * All of this is designed to be done lazily, i.e. elements created on demand.
jglick@971
    58
 * @since 4.37
jglick@971
    59
 * @author Jaroslav Tulach
jglick@971
    60
 * @see NbCollections#checkedEnumerationByFilter
jglick@971
    61
 * @see NbCollections#iterable(Enumeration)
jglick@971
    62
 */
jglick@971
    63
public final class Enumerations extends Object {
jglick@971
    64
    /** No instances */
jglick@971
    65
    private Enumerations() {
jglick@971
    66
    }
jglick@971
    67
jglick@971
    68
    /**
jglick@971
    69
     * An empty enumeration.
jglick@971
    70
     * Always returns <code>false</code> from
jglick@971
    71
     * <code>empty().hasMoreElements()</code> and throws <code>NoSuchElementException</code>
jglick@971
    72
     * from <code>empty().nextElement()</code>.
jglick@971
    73
     * @return the enumeration
jglick@971
    74
     */
jglick@971
    75
    public static final <T> Enumeration<T> empty() {
jglick@971
    76
        Collection<T> emptyL = Collections.emptyList();
jglick@971
    77
        return Collections.enumeration(emptyL);
jglick@971
    78
    }
jglick@971
    79
jglick@971
    80
    /**
jglick@971
    81
     * Creates an enumeration with one element.
jglick@971
    82
     * @param obj the element to be present in the enumeration.
jglick@971
    83
     * @return enumeration
jglick@971
    84
     */
jglick@971
    85
    public static <T> Enumeration<T> singleton(T obj) {
jglick@971
    86
        return Collections.enumeration(Collections.singleton(obj));
jglick@971
    87
    }
jglick@971
    88
jglick@971
    89
    /**
jglick@971
    90
     * Concatenates the content of two enumerations into one.
jglick@971
    91
     * Until the
jglick@971
    92
     * end of <code>en1</code> is reached its elements are being served.
jglick@971
    93
     * As soon as the <code>en1</code> has no more elements, the content
jglick@971
    94
     * of <code>en2</code> is being returned.
jglick@971
    95
     *
jglick@971
    96
     * @param en1 first enumeration
jglick@971
    97
     * @param en2 second enumeration
jglick@971
    98
     * @return enumeration
jglick@971
    99
     */
jglick@971
   100
    public static <T> Enumeration<T> concat(Enumeration<? extends T> en1, Enumeration<? extends T> en2) {
jglick@971
   101
        ArrayList<Enumeration<? extends T>> two = new ArrayList<Enumeration<? extends T>>();
jglick@971
   102
        two.add(en1);
jglick@971
   103
        two.add(en2);
jglick@971
   104
        return new SeqEn<T>(Collections.enumeration(two));
jglick@971
   105
    }
jglick@971
   106
jglick@971
   107
    /**
jglick@971
   108
     * Concatenates the content of many enumerations.
jglick@971
   109
     * The input value
jglick@971
   110
     * is enumeration of Enumeration elements and the result is composed
jglick@971
   111
     * all their content. Each of the provided enumeration is fully read
jglick@971
   112
     * and their content returned before the next enumeration is asked for
jglick@971
   113
     * their elements.
jglick@971
   114
     *
jglick@971
   115
     * @param enumOfEnums Enumeration of Enumeration elements
jglick@971
   116
     * @return enumeration
jglick@971
   117
     */
jglick@971
   118
    public static <T> Enumeration<T> concat(Enumeration<? extends Enumeration<? extends T>> enumOfEnums) {
jglick@971
   119
        return new SeqEn<T>(enumOfEnums);
jglick@971
   120
    }
jglick@971
   121
jglick@971
   122
    /**
jglick@971
   123
     * Filters the input enumeration to new one that should contain
jglick@971
   124
     * each of the provided elements just once.
jglick@971
   125
     * The elements are compared
jglick@971
   126
     * using their default <code>equals</code> and <code>hashCode</code> methods.
jglick@971
   127
     *
jglick@971
   128
     * @param en enumeration to filter
jglick@971
   129
     * @return enumeration without duplicated items
jglick@971
   130
     */
jglick@971
   131
    public static <T> Enumeration<T> removeDuplicates(Enumeration<T> en) {
jglick@971
   132
        class RDupls implements Processor<T,T> {
jglick@971
   133
            private Set<T> set = new HashSet<T>();
jglick@971
   134
jglick@971
   135
            public T process(T o, Collection<T> nothing) {
jglick@971
   136
                return set.add(o) ? o : null;
jglick@971
   137
            }
jglick@971
   138
        }
jglick@971
   139
jglick@971
   140
        return filter(en, new RDupls());
jglick@971
   141
    }
jglick@971
   142
jglick@971
   143
    /**
jglick@971
   144
     * Returns an enumeration that iterates over provided array.
jglick@971
   145
     * @param arr the array of object
jglick@971
   146
     * @return enumeration of those objects
jglick@971
   147
     */
jglick@971
   148
    public static <T> Enumeration<T> array(T... arr) {
jglick@971
   149
        return Collections.enumeration(Arrays.asList(arr));
jglick@971
   150
    }
jglick@971
   151
jglick@971
   152
    /**
jglick@971
   153
     * Removes all <code>null</code>s from the input enumeration.
jglick@971
   154
     * @param en enumeration that can contain nulls
jglick@971
   155
     * @return new enumeration without null values
jglick@971
   156
     */
jglick@971
   157
    public static <T> Enumeration<T> removeNulls(Enumeration<T> en) {
jglick@971
   158
        return filter(en, new RNulls<T>());
jglick@971
   159
    }
jglick@971
   160
jglick@971
   161
    /**
jglick@971
   162
     * For each element of the input enumeration <code>en</code> asks the
jglick@971
   163
     * {@link Processor} to provide a replacement.
jglick@971
   164
     * The <code>toAdd</code> argument of the processor is always null.
jglick@971
   165
     * <p>
jglick@971
   166
     * Example to convert any objects into strings:
jglick@971
   167
     * <pre>
jglick@971
   168
     * Processor convertToString = new Processor() {
jglick@971
   169
     *     public Object process(Object obj, Collection alwaysNull) {
jglick@971
   170
     *         return obj.toString(); // converts to string
jglick@971
   171
     *     }
jglick@971
   172
     * };
jglick@971
   173
     * Enumeration strings = Enumerations.convert(elems, convertToString);
jglick@971
   174
     * </pre>
jglick@971
   175
     *
jglick@971
   176
     * @param en enumeration of any objects
jglick@971
   177
     * @param processor a callback processor for the elements (its toAdd arguments is always null)
jglick@971
   178
     * @return new enumeration where all elements has been processed
jglick@971
   179
     */
jglick@971
   180
    public static <T,R> Enumeration<R> convert(Enumeration<? extends T> en, Processor<T,R> processor) {
jglick@971
   181
        return new AltEn<T,R>(en, processor);
jglick@971
   182
    }
jglick@971
   183
jglick@971
   184
    /**
jglick@971
   185
     * Filters some elements out from the input enumeration.
jglick@971
   186
     * Just make the
jglick@971
   187
     * {@link Processor} return <code>null</code>. Please notice the <code>toAdd</code>
jglick@971
   188
     * argument of the processor is always <code>null</code>.
jglick@971
   189
     * <p>
jglick@971
   190
     * Example to remove all objects that are not strings:
jglick@971
   191
     * <pre>
jglick@971
   192
     * Processor onlyString = new Processor() {
jglick@971
   193
     *     public Object process(Object obj, Collection alwaysNull) {
jglick@971
   194
     *         if (obj instanceof String) {
jglick@971
   195
     *             return obj;
jglick@971
   196
     *         } else {
jglick@971
   197
     *             return null;
jglick@971
   198
     *         }
jglick@971
   199
     *     }
jglick@971
   200
     * };
jglick@971
   201
     * Enumeration strings = Enumerations.filter(elems, onlyString);
jglick@971
   202
     * </pre>
jglick@971
   203
     *
jglick@971
   204
     * @param en enumeration of any objects
jglick@971
   205
     * @param filter a callback processor for the elements (its toAdd arguments is always null)
jglick@971
   206
     * @return new enumeration which does not include non-processed (returned null from processor) elements
jglick@971
   207
     * @see NbCollections#checkedEnumerationByFilter
jglick@971
   208
     */
jglick@971
   209
    public static <T,R> Enumeration<R> filter(Enumeration<? extends T> en, Processor<T,R> filter) {
jglick@971
   210
        Parameters.notNull("en", en);
jglick@971
   211
        Parameters.notNull("filter", filter);
jglick@971
   212
        return new FilEn<T,R>(en, filter);
jglick@971
   213
    }
jglick@971
   214
jglick@971
   215
    /**
jglick@971
   216
     * Support for breadth-first enumerating.
jglick@971
   217
     * Before any element is returned
jglick@971
   218
     * for the resulting enumeration it is processed in the {@link Processor} and
jglick@971
   219
     * the processor is allowed to modify it and also add additional elements
jglick@971
   220
     * at the (current) end of the <q>queue</q> by calling <code>toAdd.add</code>
jglick@971
   221
     * or <code>toAdd.addAll</code>. No other methods can be called on the
jglick@971
   222
     * provided <code>toAdd</code> collection.
jglick@971
   223
     * <p>
jglick@971
   224
     * Example of doing breadth-first walk through a tree:
jglick@971
   225
     * <pre>
jglick@971
   226
     * Processor queueSubnodes = new Processor() {
jglick@971
   227
     *     public Object process(Object obj, Collection toAdd) {
jglick@971
   228
     *         Node n = (Node)obj;
jglick@971
   229
     *         toAdd.addAll (n.getChildrenList());
jglick@971
   230
     *         return n;
jglick@971
   231
     *     }
jglick@971
   232
     * };
jglick@971
   233
     * Enumeration strings = Enumerations.queue(elems, queueSubnodes);
jglick@971
   234
     * </pre>
jglick@971
   235
     *
jglick@971
   236
     * @param en initial content of the resulting enumeration
jglick@971
   237
     * @param filter the processor that is called for each element and can
jglick@971
   238
     *        add and addAll elements to its toAdd Collection argument and
jglick@971
   239
     *        also change the value to be returned
jglick@971
   240
     * @return enumeration with the initial and queued content (it can contain
jglick@971
   241
     *       <code>null</code> if the filter returned <code>null</code> from its
jglick@971
   242
     *       {@link Processor#process} method.
jglick@971
   243
     */
jglick@971
   244
    public static <T,R> Enumeration<R> queue(Enumeration<? extends T> en, Processor<T,R> filter) {
jglick@971
   245
        QEn<T,R> q = new QEn<T,R>(filter);
jglick@971
   246
jglick@971
   247
        while (en.hasMoreElements()) {
jglick@971
   248
            q.put(en.nextElement());
jglick@971
   249
        }
jglick@971
   250
jglick@971
   251
        return q;
jglick@971
   252
    }
jglick@971
   253
jglick@971
   254
    /**
jglick@971
   255
     * Processor interface that can filter out objects from the enumeration,
jglick@971
   256
     * change them or add aditional objects to the end of the current enumeration.
jglick@971
   257
     */
jglick@971
   258
    public static interface Processor<T,R> {
jglick@971
   259
        /** @param original the object that is going to be returned from the enumeration right now
jglick@971
   260
         * @return a replacement for this object
jglick@971
   261
         * @param toAdd can be non-null if one can add new objects at the end of the enumeration
jglick@971
   262
         */
jglick@971
   263
        public R process(T original, Collection<T> toAdd);
jglick@971
   264
    }
jglick@971
   265
jglick@971
   266
    /** Altering enumeration implementation */
jglick@971
   267
    private static final class AltEn<T,R> extends Object implements Enumeration<R> {
jglick@971
   268
        /** enumeration to filter */
jglick@971
   269
        private Enumeration<? extends T> en;
jglick@971
   270
jglick@971
   271
        /** map to alter */
jglick@971
   272
        private Processor<T,R> process;
jglick@971
   273
jglick@971
   274
        /**
jglick@971
   275
        * @param en enumeration to filter
jglick@971
   276
        */
jglick@971
   277
        public AltEn(Enumeration<? extends T> en, Processor<T,R> process) {
jglick@971
   278
            this.en = en;
jglick@971
   279
            this.process = process;
jglick@971
   280
        }
jglick@971
   281
jglick@971
   282
        /** @return true if there is more elements in the enumeration
jglick@971
   283
        */
jglick@971
   284
        public boolean hasMoreElements() {
jglick@971
   285
            return en.hasMoreElements();
jglick@971
   286
        }
jglick@971
   287
jglick@971
   288
        /** @return next object in the enumeration
jglick@971
   289
        * @exception NoSuchElementException can be thrown if there is no next object
jglick@971
   290
        *   in the enumeration
jglick@971
   291
        */
jglick@971
   292
        public R nextElement() {
jglick@971
   293
            return process.process(en.nextElement(), null);
jglick@971
   294
        }
jglick@971
   295
    }
jglick@971
   296
     // end of AltEn
jglick@971
   297
jglick@971
   298
    /** Sequence of enumerations */
jglick@971
   299
    private static final class SeqEn<T> extends Object implements Enumeration<T> {
jglick@971
   300
        /** enumeration of Enumerations */
jglick@971
   301
        private Enumeration<? extends Enumeration<? extends T>> en;
jglick@971
   302
jglick@971
   303
        /** current enumeration */
jglick@971
   304
        private Enumeration<? extends T> current;
jglick@971
   305
jglick@971
   306
        /** is {@link #current} up-to-date and has more elements?
jglick@971
   307
        * The combination <CODE>current == null</CODE> and
jglick@971
   308
        * <CODE>checked == true means there are no more elements
jglick@971
   309
        * in this enumeration.
jglick@971
   310
        */
jglick@971
   311
        private boolean checked = false;
jglick@971
   312
jglick@971
   313
        /** Constructs new enumeration from already existing. The elements
jglick@971
   314
        * of <CODE>en</CODE> should be also enumerations. The resulting
jglick@971
   315
        * enumeration contains elements of such enumerations.
jglick@971
   316
        *
jglick@971
   317
        * @param en enumeration of Enumerations that should be sequenced
jglick@971
   318
        */
jglick@971
   319
        public SeqEn(Enumeration<? extends Enumeration <? extends T>> en) {
jglick@971
   320
            this.en = en;
jglick@971
   321
        }
jglick@971
   322
jglick@971
   323
        /** Ensures that current enumeration is set. If there aren't more
jglick@971
   324
        * elements in the Enumerations, sets the field <CODE>current</CODE> to null.
jglick@971
   325
        */
jglick@971
   326
        private void ensureCurrent() {
jglick@971
   327
            while ((current == null) || !current.hasMoreElements()) {
jglick@971
   328
                if (en.hasMoreElements()) {
jglick@971
   329
                    current = en.nextElement();
jglick@971
   330
                } else {
jglick@971
   331
                    // no next valid enumeration
jglick@971
   332
                    current = null;
jglick@971
   333
jglick@971
   334
                    return;
jglick@971
   335
                }
jglick@971
   336
            }
jglick@971
   337
        }
jglick@971
   338
jglick@971
   339
        /** @return true if we have more elements */
jglick@971
   340
        public boolean hasMoreElements() {
jglick@971
   341
            if (!checked) {
jglick@971
   342
                ensureCurrent();
jglick@971
   343
                checked = true;
jglick@971
   344
            }
jglick@971
   345
jglick@971
   346
            return current != null;
jglick@971
   347
        }
jglick@971
   348
jglick@971
   349
        /** @return next element
jglick@971
   350
        * @exception NoSuchElementException if there is no next element
jglick@971
   351
        */
jglick@971
   352
        public T nextElement() {
jglick@971
   353
            if (!checked) {
jglick@971
   354
                ensureCurrent();
jglick@971
   355
            }
jglick@971
   356
jglick@971
   357
            if (current != null) {
jglick@971
   358
                checked = false;
jglick@971
   359
jglick@971
   360
                return current.nextElement();
jglick@971
   361
            } else {
jglick@971
   362
                checked = true;
jglick@971
   363
                throw new java.util.NoSuchElementException();
jglick@971
   364
            }
jglick@971
   365
        }
jglick@971
   366
    }
jglick@971
   367
     // end of SeqEn
jglick@971
   368
jglick@971
   369
    /** QueueEnumeration
jglick@971
   370
     */
jglick@971
   371
    private static class QEn<T,R> extends Object implements Enumeration<R> {
jglick@971
   372
        /** next object to be returned */
jglick@971
   373
        private ListItem<T> next = null;
jglick@971
   374
jglick@971
   375
        /** last object in the queue */
jglick@971
   376
        private ListItem<T> last = null;
jglick@971
   377
jglick@971
   378
        /** processor to use */
jglick@971
   379
        private Processor<T,R> processor;
jglick@971
   380
jglick@971
   381
        public QEn(Processor<T,R> p) {
jglick@971
   382
            this.processor = p;
jglick@971
   383
        }
jglick@971
   384
jglick@971
   385
        /** Put adds new object to the end of queue.
jglick@971
   386
        * @param o the object to add
jglick@971
   387
        */
jglick@971
   388
        public void put(T o) {
jglick@971
   389
            if (last != null) {
jglick@971
   390
                ListItem<T> li = new ListItem<T>(o);
jglick@971
   391
                last.next = li;
jglick@971
   392
                last = li;
jglick@971
   393
            } else {
jglick@971
   394
                next = last = new ListItem<T>(o);
jglick@971
   395
            }
jglick@971
   396
        }
jglick@971
   397
jglick@971
   398
        /** Adds array of objects into the queue.
jglick@971
   399
        * @param arr array of objects to put into the queue
jglick@971
   400
        */
jglick@971
   401
        public void put(Collection<? extends T> arr) {
jglick@971
   402
            for (T e : arr) {
jglick@971
   403
                put(e);
jglick@971
   404
            }
jglick@971
   405
        }
jglick@971
   406
jglick@971
   407
        /** Is there any next object?
jglick@971
   408
        * @return true if there is next object, false otherwise
jglick@971
   409
        */
jglick@971
   410
        public boolean hasMoreElements() {
jglick@971
   411
            return next != null;
jglick@971
   412
        }
jglick@971
   413
jglick@971
   414
        /** @return next object in enumeration
jglick@971
   415
        * @exception NoSuchElementException if there is no next object
jglick@971
   416
        */
jglick@971
   417
        public R nextElement() {
jglick@971
   418
            if (next == null) {
jglick@971
   419
                throw new NoSuchElementException();
jglick@971
   420
            }
jglick@971
   421
jglick@971
   422
            T res = next.object;
jglick@971
   423
jglick@971
   424
            if ((next = next.next) == null) {
jglick@971
   425
                last = null;
jglick@971
   426
            }
jglick@971
   427
jglick@971
   428
            ;
jglick@971
   429
jglick@971
   430
            ToAdd<T,R> toAdd = new ToAdd<T,R>(this);
jglick@971
   431
            R out = processor.process(res, toAdd);
jglick@971
   432
            toAdd.finish();
jglick@971
   433
jglick@971
   434
            return out;
jglick@971
   435
        }
jglick@971
   436
jglick@971
   437
        /** item in linked list of Objects */
jglick@971
   438
        private static final class ListItem<T> {
jglick@971
   439
            T object;
jglick@971
   440
            ListItem<T> next;
jglick@971
   441
jglick@971
   442
            /** @param o the object for this item */
jglick@971
   443
            ListItem(T o) {
jglick@971
   444
                object = o;
jglick@971
   445
            }
jglick@971
   446
        }
jglick@971
   447
jglick@971
   448
        /** Temporary collection that supports only add and addAll operations*/
jglick@971
   449
        private static final class ToAdd<T,R> extends Object implements Collection<T> {
jglick@971
   450
            private QEn<T,R> q;
jglick@971
   451
jglick@971
   452
            public ToAdd(QEn<T,R> q) {
jglick@971
   453
                this.q = q;
jglick@971
   454
            }
jglick@971
   455
jglick@971
   456
            public void finish() {
jglick@971
   457
                this.q = null;
jglick@971
   458
            }
jglick@971
   459
jglick@971
   460
            public boolean add(T o) {
jglick@971
   461
                q.put(o);
jglick@971
   462
jglick@971
   463
                return true;
jglick@971
   464
            }
jglick@971
   465
jglick@971
   466
            public boolean addAll(Collection<? extends T> c) {
jglick@971
   467
                q.put(c);
jglick@971
   468
jglick@971
   469
                return true;
jglick@971
   470
            }
jglick@971
   471
jglick@971
   472
            private String msg() {
jglick@971
   473
                return "Only add and addAll are implemented"; // NOI18N
jglick@971
   474
            }
jglick@971
   475
jglick@971
   476
            public void clear() {
jglick@971
   477
                throw new UnsupportedOperationException(msg());
jglick@971
   478
            }
jglick@971
   479
jglick@971
   480
            public boolean contains(Object o) {
jglick@971
   481
                throw new UnsupportedOperationException(msg());
jglick@971
   482
            }
jglick@971
   483
jglick@971
   484
            public boolean containsAll(Collection c) {
jglick@971
   485
                throw new UnsupportedOperationException(msg());
jglick@971
   486
            }
jglick@971
   487
jglick@971
   488
            public boolean isEmpty() {
jglick@971
   489
                throw new UnsupportedOperationException(msg());
jglick@971
   490
            }
jglick@971
   491
jglick@971
   492
            public Iterator<T> iterator() {
jglick@971
   493
                throw new UnsupportedOperationException(msg());
jglick@971
   494
            }
jglick@971
   495
jglick@971
   496
            public boolean remove(Object o) {
jglick@971
   497
                throw new UnsupportedOperationException(msg());
jglick@971
   498
            }
jglick@971
   499
jglick@971
   500
            public boolean removeAll(Collection c) {
jglick@971
   501
                throw new UnsupportedOperationException(msg());
jglick@971
   502
            }
jglick@971
   503
jglick@971
   504
            public boolean retainAll(Collection c) {
jglick@971
   505
                throw new UnsupportedOperationException(msg());
jglick@971
   506
            }
jglick@971
   507
jglick@971
   508
            public int size() {
jglick@971
   509
                throw new UnsupportedOperationException(msg());
jglick@971
   510
            }
jglick@971
   511
jglick@971
   512
            public Object[] toArray() {
jglick@971
   513
                throw new UnsupportedOperationException(msg());
jglick@971
   514
            }
jglick@971
   515
jglick@971
   516
            public<X> X[] toArray(X[] a) {
jglick@971
   517
                throw new UnsupportedOperationException(msg());
jglick@971
   518
            }
jglick@971
   519
        }
jglick@971
   520
         // end of ToAdd
jglick@971
   521
    }
jglick@971
   522
     // end of QEn
jglick@971
   523
jglick@971
   524
    /** Filtering enumeration */
jglick@971
   525
    private static final class FilEn<T,R> extends Object implements Enumeration<R> {
jglick@971
   526
        /** marker object stating there is no nexte element prepared */
jglick@971
   527
        private static final Object EMPTY = new Object();
jglick@971
   528
jglick@971
   529
        /** enumeration to filter */
jglick@971
   530
        private Enumeration<? extends T> en;
jglick@971
   531
jglick@971
   532
        /** element to be returned next time or {@link #EMPTY} if there is
jglick@971
   533
        * no such element prepared */
jglick@971
   534
        private R next = empty();
jglick@971
   535
jglick@971
   536
        /** the set to use as filter */
jglick@971
   537
        private Processor<T,R> filter;
jglick@971
   538
jglick@971
   539
        /**
jglick@971
   540
        * @param en enumeration to filter
jglick@971
   541
        */
jglick@971
   542
        public FilEn(Enumeration<? extends T> en, Processor<T,R> filter) {
jglick@971
   543
            this.en = en;
jglick@971
   544
            this.filter = filter;
jglick@971
   545
        }
jglick@971
   546
jglick@971
   547
        /** @return true if there is more elements in the enumeration
jglick@971
   548
        */
jglick@971
   549
        public boolean hasMoreElements() {
jglick@971
   550
            if (next != empty()) {
jglick@971
   551
                // there is a object already prepared
jglick@971
   552
                return true;
jglick@971
   553
            }
jglick@971
   554
jglick@971
   555
            while (en.hasMoreElements()) {
jglick@971
   556
                // read next
jglick@971
   557
                next = filter.process(en.nextElement(), null);
jglick@971
   558
jglick@971
   559
                if (next != null) {
jglick@971
   560
                    // if the object is accepted
jglick@971
   561
                    return true;
jglick@971
   562
                }
jglick@971
   563
jglick@971
   564
                ;
jglick@971
   565
            }
jglick@971
   566
jglick@971
   567
            next = empty();
jglick@971
   568
jglick@971
   569
            return false;
jglick@971
   570
        }
jglick@971
   571
jglick@971
   572
        /** @return next object in the enumeration
jglick@971
   573
        * @exception NoSuchElementException can be thrown if there is no next object
jglick@971
   574
        *   in the enumeration
jglick@971
   575
        */
jglick@971
   576
        public R nextElement() {
jglick@971
   577
            if ((next == EMPTY) && !hasMoreElements()) {
jglick@971
   578
                throw new NoSuchElementException();
jglick@971
   579
            }
jglick@971
   580
jglick@971
   581
            R res = next;
jglick@971
   582
            next = empty();
jglick@971
   583
jglick@971
   584
            return res;
jglick@971
   585
        }
jglick@971
   586
jglick@971
   587
        @SuppressWarnings("unchecked")
jglick@971
   588
        private R empty() {
jglick@971
   589
            return (R)EMPTY;
jglick@971
   590
        }
jglick@971
   591
    }
jglick@971
   592
     // end of FilEn
jglick@971
   593
jglick@971
   594
    /** Returns true from contains if object is not null */
jglick@971
   595
    private static class RNulls<T> implements Processor<T,T> {
jglick@971
   596
        public T process(T original, Collection<T> toAdd) {
jglick@971
   597
            return original;
jglick@971
   598
        }
jglick@971
   599
    }
jglick@971
   600
     // end of RNulls
jglick@971
   601
}