/*
 * AutoEnum.java
 */

import java.util.Enumeration;

import com.ms.com.Variant;
import com.ms.com.IEnumVariant;
import com.ms.com.ComSuccessException;
import com.ms.com.ComFailException;

import addressbooklib.*;
import addressbooklib.Errors;

/**
 * COM-Style Enumeration<br>
 * Implements the standard IEnumVARIANT interface
 * as well as the DIEnum interface to provide enumeration
 * over an Automation collection class
 * @Author Ken Bandes
 */
public class AutoEnum
    implements IEnumVariant, DIEnum
{
    private Enumerable collection;
    private Enumeration enum;

    /**
     * constructor
     * @param collection an object supporting the Enumerable interface
     */
    public AutoEnum(Enumerable collection)
    {
        this.collection = collection;
        enum = collection.elements();
    }

    /**
     * IEnumVariant method<br>
     * bypass next element(s) in sequence in the enumeration
     * @see com.sm.com.IEnumVariant
     * @param n number of elements to skip
     */
    public void Skip(int n)
    {
        while((n-- > 0) && enum.hasMoreElements())
            enum.nextElement();
        if(n > 0)
            // returns S_FALSE status, indicating
            // end of collection reached
            throw new ComSuccessException();
    }

    /**
     * IEnumVariant method<br>
     * start enumerating from beginning again
     * @see com.sm.com.IEnumVariant
     */
    public void Reset()
    {
        enum = collection.elements();
    }

    /**
     * IEnumVariant method<br>
     * make a copy of this enumerator<br>
     * Not Implemented!
     * @see com.sm.com.IEnumVariant
     * @returns IEnumVariant
     */
    public IEnumVariant Clone()
    {
        throw new ComFailException(
                        StdErrors.E_NOTIMPL, 
                        "Clone method not supported");
    }

    /**
     * IEnumVariant method<br>
     * Retrieve the next n elements into a provided array
     * @param n the number of items to retrieve
     * @param v the vector in which to place the items
     * @param x a single-element array to recieve the actual count
     */
    public void Next(int n, Variant v[], int x[])
    {
        int i;
        for(i = 0; i < n && enum.hasMoreElements(); ++i)
        {
            Variant var = new Variant(enum.nextElement());
            v[i] = var;
        }
        if(x != null)
            x[0] = i;
        if(i < n)
            /* returns S_FALSE status, indicating
             * end of collection reached
             */
            throw new ComSuccessException();
    }


    /**
     * DIEnum method<br>
     * @return indication of whether there are more elements
     */
    public boolean HasMoreElements()
    {
        return enum.hasMoreElements();
    }

    /**
     * DIEnum method<br>
     * @return the next element in the collection
     */
    public Object NextElement()
    {
        if(enum.hasMoreElements())
            return enum.nextElement();
        else
            throw new ComFailException(
                        Errors.E_OUTOFBOUNDS, 
                        "Attempt to Retrieve after last element");
    }
}
