1 /*
   2  * Copyright (c) 1997, 2012, 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 
  26 package com.sun.xml.internal.xsom.impl.scd;
  27 
  28 import java.util.Iterator;
  29 import java.util.NoSuchElementException;
  30 import java.util.Set;
  31 import java.util.HashSet;
  32 import java.util.Collections;
  33 
  34 /**
  35  * Various convenient {@link Iterator} implementations.
  36  * @author Kohsuke Kawaguchi
  37  */
  38 public 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 U->Iterator&lt;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 }