org.jgrapht.util.PrefetchIterator.java Source code

Java tutorial

Introduction

Here is the source code for org.jgrapht.util.PrefetchIterator.java

Source

    /* 
     * JGraphT : a free Java graph-theory library
     * 
     *
     * Project Info:  http://jgrapht.sourceforge.net/
     * Project Creator:  Barak Naveh (http://sourceforge.net/users/barak_naveh)
     *
     * (C) Copyright 2003-2007, by Barak Naveh and Contributors.
     *
     * This library is free software; you can redistribute it and/or modify it
     * under the terms of the GNU Lesser General Public License as published by
     * the Free Software Foundation; either version 2.1 of the License, or
     * (at your option) any later version.
     *
     * This library is distributed in the hope that it will be useful, but
     * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
     * License for more details.
     *
     * You should have received a copy of the GNU Lesser General Public License
     * along with this library; if not, write to the Free Software Foundation,
     * Inc.,
     * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
     */
    /* -----------------
     * PrefetchIterator.java
     * -----------------
     * (C) Copyright 2005-2007, by Assaf Lehr and Contributors.
     *
     * Original Author:  Assaf Lehr
     * Contributor(s):   -
     *
     * $Id: PrefetchIterator.java 568 2007-09-30 00:12:18Z perfecthash $
     *
     * Changes
     * -------
     */

import java.util.*;

    /**
     * Utility class to help implement an iterator/enumerator in which the hasNext()
     * method needs to calculate the next elements ahead of time.
     *
     * <p>Many classes which implement an iterator face a common problem: if there
     * is no easy way to calculate hasNext() other than to call getNext(), then they
     * save the result for fetching in the next call to getNext(). This utility
     * helps in doing just that.
     *
     * <p><b>Usage:</b> The new iterator class will hold this class as a member
     * variable and forward the hasNext() and next() to it. When creating an
     * instance of this class, you supply it with a functor that is doing the real
     * job of calculating the next element.
     *
     * <pre><code>
    //This class supllies enumeration of integer till 100.
    public class IteratorExample implements Enumeration{
    private int counter=0;
    private PrefetchIterator nextSupplier;
    
        IteratorExample()
        {
            nextSupplier = new PrefetchIterator(new PrefetchIterator.NextElementFunctor(){
    
                public Object nextElement() throws NoSuchElementException {
                    counter++;
                    if (counter>=100)
                        throw new NoSuchElementException();
                    else
                        return new Integer(counter);
                }
    
            });
        }
        //forwarding to nextSupplier and return its returned value
        public boolean hasMoreElements() {
            return this.nextSupplier.hasMoreElements();
        }
    //  forwarding to nextSupplier and return its returned value
        public Object nextElement() {
            return this.nextSupplier.nextElement();
        }
      }</pre>
     * </code>
     *
     * @author Assaf_Lehr
     */
    public class PrefetchIterator<E> implements Iterator<E>, Enumeration<E> {
        //~ Instance fields --------------------------------------------------------

        private NextElementFunctor<E> innerEnum;
        private E getNextLastResult;
        private boolean isGetNextLastResultUpToDate = false;
        private boolean endOfEnumerationReached = false;
        private boolean flagIsEnumerationStartedEmpty = true;
        private int innerFunctorUsageCounter = 0;

        //~ Constructors -----------------------------------------------------------

        public PrefetchIterator(NextElementFunctor<E> aEnum) {
            innerEnum = aEnum;
        }

        //~ Methods ----------------------------------------------------------------

        /**
         * Serves as one contact place to the functor; all must use it and not
         * directly the NextElementFunctor.
         */
        private E getNextElementFromInnerFunctor() {
            innerFunctorUsageCounter++;
            E result = this.innerEnum.nextElement();

            // if we got here , an exception was not thrown, so at least
            // one time a good value returned
            flagIsEnumerationStartedEmpty = false;
            return result;
        }

        /**
         * 1. Retrieves the saved value or calculates it if it does not exist 2.
         * Changes isGetNextLastResultUpToDate to false. (Because it does not save
         * the NEXT element now; it saves the current one!)
         */
        public E nextElement() {
            E result = null;
            if (this.isGetNextLastResultUpToDate) {
                result = this.getNextLastResult;
            } else {
                result = getNextElementFromInnerFunctor();
            }

            this.isGetNextLastResultUpToDate = false;
            return result;
        }

        /**
         * If (isGetNextLastResultUpToDate==true) returns true else 1. calculates
         * getNext() and saves it 2. sets isGetNextLastResultUpToDate to true.
         */
        public boolean hasMoreElements() {
            if (endOfEnumerationReached) {
                return false;
            }

            if (isGetNextLastResultUpToDate) {
                return true;
            } else {
                try {
                    this.getNextLastResult = getNextElementFromInnerFunctor();
                    this.isGetNextLastResultUpToDate = true;
                    return true;
                } catch (NoSuchElementException noSuchE) {
                    endOfEnumerationReached = true;
                    return false;
                }
            } // else
        } // method

        /**
         * Tests whether the enumeration started as an empty one. It does not matter
         * if it hasMoreElements() now, only at initialization time. Efficiency: if
         * nextElements(), hasMoreElements() were never used, it activates the
         * hasMoreElements() once. Else it is immediately(O(1))
         */
        public boolean isEnumerationStartedEmpty() {
            if (this.innerFunctorUsageCounter == 0) {
                if (hasMoreElements()) {
                    return false;
                } else {
                    return true;
                }
            } else // it is not the first time , so use the saved value
                   // which was initilaizeed during a call to
                   // getNextElementFromInnerFunctor
            {
                return flagIsEnumerationStartedEmpty;
            }
        }

        public boolean hasNext() {
            return this.hasMoreElements();
        }

        public E next() {
            return this.nextElement();
        }

        /**
         * Always throws UnsupportedOperationException.
         */
        public void remove() throws UnsupportedOperationException {
            throw new UnsupportedOperationException();
        }

        //~ Inner Interfaces -------------------------------------------------------

        public interface NextElementFunctor<EE> {
            /**
             * You must implement that NoSuchElementException is thrown on
             * nextElement() if it is out of bound.
             */
            public EE nextElement() throws NoSuchElementException;
        }
    }

    // End PrefetchIterator.java
    /////////////////////////
    /* 
     * JGraphT : a free Java graph-theory library
     * 
     *
     * Project Info:  http://jgrapht.sourceforge.net/
     * Project Creator:  Barak Naveh (http://sourceforge.net/users/barak_naveh)
     *
     * (C) Copyright 2003-2007, by Barak Naveh and Contributors.
     *
     * This library is free software; you can redistribute it and/or modify it
     * under the terms of the GNU Lesser General Public License as published by
     * the Free Software Foundation; either version 2.1 of the License, or
     * (at your option) any later version.
     *
     * This library is distributed in the hope that it will be useful, but
     * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
     * License for more details.
     *
     * You should have received a copy of the GNU Lesser General Public License
     * along with this library; if not, write to the Free Software Foundation,
     * Inc.,
     * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
     */
    /* -----------------
     * PrefetchIteratorTest.java
     * -----------------
     * (C) Copyright 2005-2007, by Assaf Lehr and Contributors.
     *
     * Original Author:  Assaf Lehr
     * Contributor(s):   -
     *
     * $Id: PrefetchIteratorTest.java 568 2007-09-30 00:12:18Z perfecthash $
     *
     * Changes
     * -------
     */
    package org.jgrapht.util;

    import java.util.*;

    import junit.framework.*;

    public class PrefetchIteratorTest extends TestCase {
        //~ Methods ----------------------------------------------------------------

        public void testIteratorInterface() {
            Iterator iterator = new IterateFrom1To99();
            for (int i = 1; i < 100; i++) {
                assertEquals(true, iterator.hasNext());
                assertEquals(i, iterator.next());
            }
            assertEquals(false, iterator.hasNext());
            Exception exceptionThrown = null;
            try {
                iterator.next();
            } catch (Exception e) {
                exceptionThrown = e;
            }
            assertTrue(exceptionThrown instanceof NoSuchElementException);
        }

        public void testEnumInterface() {
            Enumeration enumuration = new IterateFrom1To99();
            for (int i = 1; i < 100; i++) {
                assertEquals(true, enumuration.hasMoreElements());
                assertEquals(i, enumuration.nextElement());
            }
            assertEquals(false, enumuration.hasMoreElements());
            Exception exceptionThrown = null;
            try {
                enumuration.nextElement();
            } catch (Exception e) {
                exceptionThrown = e;
            }
            assertTrue(exceptionThrown instanceof NoSuchElementException);
        }

        //~ Inner Classes ----------------------------------------------------------

        // This test class supplies enumeration of integer from 1 till 100.
        public static class IterateFrom1To99 implements Enumeration, Iterator {
            private int counter = 0;
            private PrefetchIterator nextSupplier;

            public IterateFrom1To99() {
                nextSupplier = new PrefetchIterator<Integer>(new PrefetchIterator.NextElementFunctor<Integer>() {
                    public Integer nextElement() throws NoSuchElementException {
                        counter++;
                        if (counter >= 100) {
                            throw new NoSuchElementException();
                        } else {
                            return new Integer(counter);
                        }
                    }
                });
            }

            // forwarding to nextSupplier and return its returned value
            public boolean hasMoreElements() {
                return this.nextSupplier.hasMoreElements();
            }

            // forwarding to nextSupplier and return its returned value
            public Object nextElement() {
                return this.nextSupplier.nextElement();
            }

            public Object next() {
                return this.nextSupplier.next();
            }

            public boolean hasNext() {
                return this.nextSupplier.hasNext();
            }

            public void remove() {
                this.nextSupplier.remove();
            }
        }
    }

    // End PrefetchIteratorTest.java