All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tangosol.util.SimpleEnumerator Maven / Gradle / Ivy

/*
 * Copyright (c) 2000, 2020, Oracle and/or its affiliates.
 *
 * Licensed under the Universal Permissive License v 1.0 as shown at
 * http://oss.oracle.com/licenses/upl.
 */

package com.tangosol.util;


import java.lang.reflect.Array;

import java.util.Collection;
import java.util.Iterator;
import java.util.Enumeration;
import java.util.NoSuchElementException;
import java.util.ArrayList;


/**
* Provide a generic implementation of an array enumerator.
*
* @author Cameron Purdy
* @version 0.50, 09/05/97
* @version 1.00, 08/07/98
*/
@SuppressWarnings("unchecked")
public class SimpleEnumerator
        extends Base
        implements Enumeration, Iterator
    {
    // ----- constructors ---------------------------------------------------

    /**
    * Construct the simple enumerator based on an array of objects.
    *
    * @param aoItem  array of objects to enumerate
    */
    public SimpleEnumerator(E[] aoItem)
        {
        // iterate forwards, don't copy the array
        this(aoItem, 0, aoItem.length, true, false);
        }

    /**
    * Construct the simple enumerator based on an array of objects.
    *
    * @param aoItem   array of objects to enumerate
    * @param ofStart  the first object position
    * @param cItems   the number of objects to enumerate
    */
    public SimpleEnumerator(E[] aoItem, int ofStart, int cItems)
        {
        // iterate forwards, don't copy the array
        this(aoItem, ofStart, cItems, true, false);
        }

    /**
    * Construct the simple enumerator based on an array of objects, making
    * a copy of the array if specified.
    *
    * @param aoItem    array of objects to enumerate
    * @param ofStart   the first object position
    * @param cItems    the number of objects to enumerate
    * @param fForward  true to iterate forwards, false to iterate from the
    *                  end backwards to the beginning
    * @param fCopy     pass true to make a copy of the array or false if the
    *                  array's contents will not change
    */
    public SimpleEnumerator(E[] aoItem, int ofStart, int cItems,
                            boolean fForward, boolean fCopy)
        {
        if (cItems < 0)
            {
            throw new IllegalArgumentException("Negative count");
            }
        if (fForward
                ? ofStart < 0 || ofStart + cItems > aoItem.length
                : ofStart >= aoItem.length || ofStart - cItems < 0)
            {
            throw new IllegalArgumentException("Off limits");
            }

        // only copy if there are at least two items in the iterator
        if (fCopy && cItems > 1)
            {
            aoItem = aoItem.clone();
            }

        m_aoItem   = aoItem;
        m_fForward = fForward;
        m_iItem    = ofStart;
        m_ofLimit  = fForward ? ofStart + cItems : ofStart - cItems;
        }

    /**
    * Construct a simple enumerator based on another Enumeration.  This forces
    * an initial pass through the elements of the passed enumerator, making
    * a copy of that data, thus capturing a "point in time" view of an
    * Enumeration which may be backed by mutable data.  In other words, this
    * constructs a "safe enumerator" based on a "not-safe enumerator".
    *
    * @param enmr  the java.util.Enumeration to enumerate
    */
    public SimpleEnumerator(Enumeration enmr)
        {
        this(toArray(enmr));
        }

    /**
    * Construct a simple enumerator based on another Iterator.  This forces
    * an initial pass through the elements of the passed enumerator, making
    * a copy of that data, thus capturing a "point in time" view of an
    * Iterator which may be backed by mutable data.  In other words, this
    * constructs a "safe enumerator" based on a "not-safe enumerator".
    *
    * @param iter  the java.util.Iterator to enumerate
    */
    public SimpleEnumerator(Iterator iter)
        {
        this(toArray(iter));
        }

    /**
    * Construct a simple enumerator based on a collection.
    *
    * @param col  the java.util.Collection to enumerate
    */
    public SimpleEnumerator(Collection col)
        {
        this((E[]) col.toArray());
        }


    // ----- Enumeration interface ------------------------------------------

    /**
    * Tests if this enumeration contains more elements.
    *
    * @return true if the enumeration contains more elements, false otherwise
    */
    public boolean hasMoreElements()
        {
        return hasNext();
        }

    /**
    * Returns the next element of this enumeration.
    *
    * @return the next element in the enumeration
    */
    public E nextElement()
        {
        return next();
        }


    // ----- Iterator interface ---------------------------------------------

    /**
    * Tests if this Iterator contains more elements.
    *
    * @return true if the Iterator contains more elements, false otherwise
    */
    public boolean hasNext()
        {
        return m_fForward ? m_iItem < m_ofLimit : m_iItem > m_ofLimit;
        }

    /**
    * Returns the next element of this Iterator.
    *
    * @return the next element in the Iterator
    */
    public E next()
        {
        if (!hasNext())
            {
            throw new NoSuchElementException();
            }

        try
            {
            E o = m_aoItem[m_iItem];

            if (m_fForward)
                {
                m_iItem++;
                }
            else
                {
                m_iItem--;
                }
            return o;
            }
        catch (ArrayIndexOutOfBoundsException e)
            {
            throw new NoSuchElementException();
            }
        }

    /**
    * Remove the last-returned element that was returned by the Iterator.
    * This method always throws UnsupportedOperationException because the
    * Iterator is immutable.
    */
    public void remove()
        {
        throw new UnsupportedOperationException("iterator is immutable");
        }


    // ----- Enumeration helpers --------------------------------------------

    /**
    * Turns an enumeration into an array.
    *
    * @param enmr  the enumerator
    *
    * @return an array of the objects from the enumerator
    */
    public static  T[] toArray(Enumeration enmr)
        {
        if (!enmr.hasMoreElements())
            {
            return (T[]) NO_OBJECTS;
            }

        if (enmr instanceof SimpleEnumerator)
            {
            return (T[]) ((SimpleEnumerator) enmr).toArray();
            }

        ArrayList list = new ArrayList<>();
        do
            {
            list.add(enmr.nextElement());
            }
        while (enmr.hasMoreElements());
        return (T[]) list.toArray();
        }

    /**
    * Turns an enumeration into an array. The behavior of this method differs
    * from the simple {@link #toArray(Enumeration)} method in the same way
    * that the {@link Collection#toArray(Object[])} method differs from the
    * {@link Collection#toArray()} method.
    *
    * @param enmr  the enumerator
    * @param ao    the array into which the elements of the Enumeration are
    *              to be stored, if it is big enough; otherwise, a new array
    *              of the same runtime type is allocated for this purpose
    *
    * @return an array of the objects from the enumerator
    */
    public static  T[] toArray(Enumeration enmr, T[] ao)
        {
        if (!enmr.hasMoreElements())
            {
            if (ao.length > 0)
                {
                ao[0] = null;
                }
            return ao;
            }

        if (enmr instanceof SimpleEnumerator)
            {
            return (T[]) ((SimpleEnumerator) enmr).toArray(ao);
            }

        ArrayList list = new ArrayList<>();
        do
            {
            list.add(enmr.nextElement());
            }
        while (enmr.hasMoreElements());
        return ao == null ? (T[]) list.toArray() : list.toArray(ao);
        }

    /**
    * Turns an Iterator into an array.
    *
    * @param iter  the Iterator
    *
    * @return an array of the objects
    */
    public static  T[] toArray(Iterator iter)
        {
        if (!iter.hasNext())
            {
            return (T[]) NO_OBJECTS;
            }

        if (iter instanceof SimpleEnumerator)
            {
            return (T[]) ((SimpleEnumerator) iter).toArray();
            }

        ArrayList list = new ArrayList();
        do
            {
            list.add(iter.next());
            }
        while (iter.hasNext());
        return (T[]) list.toArray();
        }

    /**
    * Turns an Iterator into an array. The behavior of this method differs
    * from the simple {@link #toArray(Iterator)} method in the same way that
    * the {@link Collection#toArray(Object[])} method differs from the
    * {@link Collection#toArray()} method.
    *
    * @param iter  the Iterator
    * @param ao    the array into which the elements of the Iterator are
    *              to be stored, if it is big enough; otherwise, a new array
    *              of the same runtime type is allocated for this purpose
    *
    * @return an array of the objects from the Iterator
    */
    public static  T[] toArray(Iterator iter, T[] ao)
        {
        if (!iter.hasNext())
            {
            if (ao == null)
                {
                ao = (T[]) NO_OBJECTS;
                }
            else if (ao.length > 0)
                {
                ao[0] = null;
                }
            return ao;
            }

        if (iter instanceof SimpleEnumerator)
            {
            return (T[]) ((SimpleEnumerator) iter).toArray(ao);
            }

        ArrayList list = new ArrayList<>();
        do
            {
            list.add(iter.next());
            }
        while (iter.hasNext());
        return ao == null ? (T[]) list.toArray() : list.toArray(ao);
        }


    // ----- Collection-like helpers ----------------------------------------

    /**
    * Return the remaining contents of this SimpleEnumerator as an array.
    *
    * @return an array containing all of the elements in this enumerator
    */
    public Object[] toArray()
        {
        return toArray((Object[]) null);
        }

    /**
    * Return the remaining contents of this SimpleEnumerator as an array of
    * the type specified by the passed array, and use that passed array to
    * store the values if it is big enough, putting a null in the first
    * unused element if the size of the passed array is bigger than the
    * number of remaining elements in this enumerator, as per the contract
    * of the {@link Collection#toArray(Object[])} method.
    *
    * @param ao    the array into which the elements of the Enumeration are
    *              to be stored, if it is big enough; otherwise, a new array
    *              of the same runtime type is allocated for this purpose
    *
    * @return an array containing the elements of the collection
    * 
    * @throws ArrayStoreException if the runtime type of the specified array
    *         is not a supertype of the runtime type of every element in this
    *         collection
    */
    public  T[] toArray(T[] ao)
        {
        E[]      aoItem   = m_aoItem;
        int      iNext    = m_iItem;
        int      iLast    = m_ofLimit;
        boolean  fForward = m_fForward;

        // create the array to store the map contents
        int co = fForward ? iLast - iNext : iNext - iLast;
        if (ao == null)
            {
            // implied Object[] type, see toArray()
            ao = (T[]) new Object[co];
            }
        else if (ao.length < co)
            {
            // if it is not big enough, a new array of the same runtime
            // type is allocated
            ao = (T[]) Array.newInstance(ao.getClass().getComponentType(), co);
            }
        else if (ao.length > co)
            {
            // if the collection fits in the specified array with room to
            // spare, the element in the array immediately following the
            // end of the collection is set to null
            ao[co] = null;
            }

        if (fForward)
            {
            System.arraycopy(aoItem, iNext, ao, 0, co);
            }
        else
            {
            int i = 0;
            while (iNext > iLast)
                {
                ao[i++] = (T) aoItem[iNext--];
                }
            }

        // set the enumerator to "finished"
        m_iItem = iLast;

        return ao;
        }


    // ----- constants ------------------------------------------------------

    /**
    * An array of no items.
    */
    private static final Object[] NO_OBJECTS = new Object[0];


    // ----- data members ---------------------------------------------------

    /**
    * Array of items to enumerate.
    */
    protected E[] m_aoItem;

    /**
    * Iterator position:  next item to return.
    */
    protected int m_iItem;

    /**
    * Iterator end position (beyond last).
    */
    protected int m_ofLimit;

    /**
    * Iterator direction.
    */
    protected boolean m_fForward;
    }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy