Iterators.java revision 641:63c89fbee619
1/*
2 * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.xml.internal.xsom.impl.scd;
27
28import java.util.Iterator;
29import java.util.NoSuchElementException;
30import java.util.Set;
31import java.util.HashSet;
32import java.util.Collections;
33
34/**
35 * Various convenient {@link Iterator} implementations.
36 * @author Kohsuke Kawaguchi
37 */
38public class Iterators {
39
40    static abstract class ReadOnly<T> implements Iterator<T> {
41        public final void remove() {
42            throw new UnsupportedOperationException();
43        }
44    }
45
46    // we need to run on JDK 1.4
47    private static final Iterator EMPTY = Collections.EMPTY_LIST.iterator();
48
49    public static <T> Iterator<T> empty() {
50        return EMPTY;
51    }
52
53    public static <T> Iterator<T> singleton(T value) {
54        return new Singleton<T>(value);
55    }
56
57    /**
58     * {@link Iterator} that returns a single (or no) value.
59     */
60    static final class Singleton<T> extends ReadOnly<T> {
61        private T next;
62
63        Singleton(T next) {
64            this.next = next;
65        }
66
67        public boolean hasNext() {
68            return next!=null;
69        }
70
71        public T next() {
72            T r = next;
73            next = null;
74            return r;
75        }
76    }
77
78    /**
79     * {@link Iterator} that wraps another {@link Iterator} and changes its type.
80     */
81    public static abstract class Adapter<T,U> extends ReadOnly<T> {
82        private final Iterator<? extends U> core;
83
84        public Adapter(Iterator<? extends U> core) {
85            this.core = core;
86        }
87
88        public boolean hasNext() {
89            return core.hasNext();
90        }
91
92        public T next() {
93            return filter(core.next());
94        }
95
96        protected abstract T filter(U u);
97    }
98
99    /**
100     * For each U, apply {@code U->Iterator<T>} function and then iterate all
101     * the resulting T.
102     */
103    public static abstract class Map<T,U> extends ReadOnly<T> {
104        private final Iterator<? extends U> core;
105
106        private Iterator<? extends T> current;
107
108        protected Map(Iterator<? extends U> core) {
109            this.core = core;
110        }
111
112        public boolean hasNext() {
113            while(current==null || !current.hasNext()) {
114                if(!core.hasNext())
115                    return false;   // nothing more to enumerate
116                current = apply(core.next());
117            }
118            return true;
119        }
120
121        public T next() {
122            return current.next();
123        }
124
125        protected abstract Iterator<? extends T> apply(U u);
126    }
127
128    /**
129     * Filter out objects from another iterator.
130     */
131    public static abstract class Filter<T> extends ReadOnly<T> {
132        private final Iterator<? extends T> core;
133        private T next;
134
135        protected Filter(Iterator<? extends T> core) {
136            this.core = core;
137        }
138
139        /**
140         * Return true to retain the value.
141         */
142        protected abstract boolean matches(T value);
143
144        public boolean hasNext() {
145            while(core.hasNext() && next==null) {
146                next = core.next();
147                if(!matches(next))
148                    next = null;
149            }
150
151            return next!=null;
152        }
153
154        public T next() {
155            if(next==null)      throw new NoSuchElementException();
156            T r = next;
157            next = null;
158            return r;
159        }
160    }
161
162    /**
163     * Only return unique items.
164     */
165    static final class Unique<T> extends Filter<T> {
166        private Set<T> values = new HashSet<T>();
167        public Unique(Iterator<? extends T> core) {
168            super(core);
169        }
170
171        protected boolean matches(T value) {
172            return values.add(value);
173        }
174    }
175
176    /**
177     * Union of two iterators.
178     */
179    public static final class Union<T> extends ReadOnly<T> {
180        private final Iterator<? extends T> first,second;
181
182        public Union(Iterator<? extends T> first, Iterator<? extends T> second) {
183            this.first = first;
184            this.second = second;
185        }
186
187        public boolean hasNext() {
188            return first.hasNext() || second.hasNext();
189        }
190
191        public T next() {
192            if(first.hasNext())     return first.next();
193            else                    return second.next();
194        }
195    }
196
197    /**
198     * Array iterator.
199     */
200    public static final class Array<T> extends ReadOnly<T> {
201        private final T[] items;
202        private int index=0;
203        public Array(T[] items) {
204            this.items = items;
205        }
206
207        public boolean hasNext() {
208            return index<items.length;
209        }
210
211        public T next() {
212            return items[index++];
213        }
214    }
215}
216