KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jgrapht > util > PrefetchIterator


1 /* ==========================================
2  * JGraphT : a free Java graph-theory library
3  * ==========================================
4  *
5  * Project Info: http://jgrapht.sourceforge.net/
6  * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh)
7  *
8  * (C) Copyright 2003-2006, by Barak Naveh and Contributors.
9  *
10  * This library is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU Lesser General Public License as published by
12  * the Free Software Foundation; either version 2.1 of the License, or
13  * (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18  * License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with this library; if not, write to the Free Software Foundation,
22  * Inc.,
23  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
24  */

25 /* -----------------
26  * PrefetchIterator.java
27  * -----------------
28  * (C) Copyright 2005-2006, by Assaf Lehr and Contributors.
29  *
30  * Original Author: Assaf Lehr
31  * Contributor(s): -
32  *
33  * $Id: PrefetchIterator.java 504 2006-07-03 02:37:26Z perfecthash $
34  *
35  * Changes
36  * -------
37  */

38 package org.jgrapht.util;
39
40 import java.util.*;
41
42
43 /**
44  * Utility class to help implement an iterator/enumerator in which the hasNext()
45  * method needs to calculate the next elements ahead of time.
46  *
47  * <p>Many classes which implement an iterator face a common problem: if there
48  * is no easy way to calculate hasNext() other than to call getNext(), then they
49  * save the result for fetching in the next call to getNext(). This utility
50  * helps in doing just that.
51  *
52  * <p><b>Usage:</b> The new iterator class will hold this class as a member
53  * variable and forward the hasNext() and next() to it. When creating an
54  * instance of this class, you supply it with a functor that is doing the real
55  * job of calculating the next element.
56  *
57  * <pre><code>
58     //This class supllies enumeration of integer till 100.
59     public class iteratorExample implements Enumeration{
60     private int counter=0;
61     private PrefetchIterator nextSupplier;
62         
63         iteratorExample()
64         {
65             nextSupplier = new PrefetchIterator(new PrefetchIterator.NextElementFunctor(){
66                 
67                 public Object nextElement() throws NoSuchElementException {
68                     counter++;
69                     if (counter>=100)
70                         throw new NoSuchElementException();
71                     else
72                         return new Integer(counter);
73                 }
74             
75             });
76         }
77         //forwarding to nextSupplier and return its returned value
78         public boolean hasMoreElements() {
79             return this.nextSupplier.hasMoreElements();
80         }
81     // forwarding to nextSupplier and return its returned value
82         public Object nextElement() {
83             return this.nextSupplier.nextElement();
84         }
85   }</pre></code>
86  *
87  * @author Assaf_Lehr
88  */

89 public class PrefetchIterator<E>
90     implements Iterator<E>, Enumeration<E>
91 {
92
93     //~ Instance fields -------------------------------------------------------
94

95     private NextElementFunctor<E> innerEnum;
96     private E getNextLastResult;
97     private boolean isGetNextLastResultUpToDate = false;
98     private boolean endOfEnumerationReached = false;
99     private boolean flagIsEnumerationStartedEmpty = true;
100     private int innerFunctorUsageCounter = 0;
101
102     //~ Constructors ----------------------------------------------------------
103

104     public PrefetchIterator(NextElementFunctor<E> aEnum)
105     {
106         innerEnum = aEnum;
107     }
108
109     //~ Methods ---------------------------------------------------------------
110

111     /**
112      * Serves as one contact place to the functor; all must use it and not
113      * directly the NextElementFunctor.
114      */

115     private E getNextElementFromInnerFunctor()
116     {
117         innerFunctorUsageCounter++;
118         E result = this.innerEnum.nextElement();
119
120         // if we got here , an exception was not thrown, so at least
121
// one time a good value returned
122
flagIsEnumerationStartedEmpty = false;
123         return result;
124     }
125
126     /**
127      * 1. Retrieves the saved value or calculates it if it does not exist 2.
128      * Changes isGetNextLastResultUpToDate to false. (Because it does not save
129      * the NEXT element now; it saves the current one!)
130      */

131     public E nextElement()
132     {
133         E result = null;
134         if (this.isGetNextLastResultUpToDate) {
135             result = this.getNextLastResult;
136         } else {
137             result = getNextElementFromInnerFunctor();
138         }
139
140         this.isGetNextLastResultUpToDate = false;
141         return result;
142     }
143
144     /**
145      * If (isGetNextLastResultUpToDate==true) returns true else 1. calculates
146      * getNext() and saves it 2. sets isGetNextLastResultUpToDate to true.
147      */

148     public boolean hasMoreElements()
149     {
150         if (endOfEnumerationReached) {
151             return false;
152         }
153
154         if (isGetNextLastResultUpToDate) {
155             return true;
156         } else {
157             try {
158                 this.getNextLastResult = getNextElementFromInnerFunctor();
159                 this.isGetNextLastResultUpToDate = true;
160                 return true;
161             } catch (NoSuchElementException noSuchE) {
162                 endOfEnumerationReached = true;
163                 return false;
164             }
165         } // else
166
} // method
167

168     /**
169      * Tests whether the enumeration started as an empty one. It does not matter
170      * if it hasMoreElements() now, only at initialization time. Efficiency: if
171      * nextElements(), hasMoreElements() were never used, it activates the
172      * hasMoreElements() once. Else it is immediately(O(1))
173      */

174     public boolean isEnumerationStartedEmpty()
175     {
176         if (this.innerFunctorUsageCounter == 0) {
177             if (hasMoreElements()) {
178                 return false;
179             } else {
180                 return true;
181             }
182         } else // it is not the first time , so use the saved value
183
// which was initilaizeed during a call to
184
// getNextElementFromInnerFunctor
185
{
186             return flagIsEnumerationStartedEmpty;
187         }
188     }
189
190     public boolean hasNext()
191     {
192         return this.hasMoreElements();
193     }
194
195     public E next()
196     {
197         return this.nextElement();
198     }
199
200     /**
201      * Always throws UnsupportedOperationException.
202      */

203     public void remove()
204         throws UnsupportedOperationException JavaDoc
205     {
206         throw new UnsupportedOperationException JavaDoc();
207     }
208
209     //~ Inner Interfaces ------------------------------------------------------
210

211     public interface NextElementFunctor<EE>
212     {
213         /**
214          * You must implement that NoSuchElementException is thrown on
215          * nextElement() if it is out of bound.
216          */

217         public EE nextElement()
218             throws NoSuchElementException;
219     }
220 }
221
Popular Tags