com.tangosol.util.SimpleEnumerator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of coherence Show documentation
Show all versions of coherence Show documentation
Oracle Coherence Community Edition
/*
* 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;
}