/*
 * @(#)StringableFilterSequence.java    1.0  9 February 2001
 *
 * Copyright 2004
 * College of Computer and Information Science
 * Northeastern University
 * Boston, MA  02115
 *
 * The Java Power Tools software may be used for educational
 * purposes as long as this copyright notice is retained intact
 * at the top of all source files.
 *
 * To discuss possible commercial use of this software, 
 * contact Richard Rasala at Northeastern University, 
 * College of Computer and Information Science,
 * 617-373-2462 or rasala@ccs.neu.edu.
 *
 * The Java Power Tools software has been designed and built
 * in collaboration with Viera Proulx and Jeff Raab.
 *
 * Should this software be modified, the words "Modified from 
 * Original" must be included as a comment below this notice.
 *
 * All publication rights are retained.  This software or its 
 * documentation may not be published in any media either
 * in whole or in part without explicit permission.
 *
 * This software was created with support from Northeastern 
 * University and from NSF grant DUE-9950829.
 */

package edu.neu.ccs.filter;

import edu.neu.ccs.*;
import java.io.Serializable;
import java.text.ParseException;
import java.util.*;

/**
 * <P>An ordered collection of filter objects 
 * similar to a <CODE>{@link List List}</CODE> 
 * that is itself a filter
 * representing the ordered application of the list of filters.</P>
 *
 * @author  Jeff Raab
 * @version 2.2
 * @since   1.0
 */
public class StringableFilterSequence 
    implements StringableFilter, Serializable 
{
    /** The underlying list used for storage of filters. */
    protected List filters = null;
    
    /**
     * Constructs a sequence using the default
     * underlying linear data structure.
     *
     * @see #StringableFilterSequence(List)
     */
    public StringableFilterSequence() {
        this(new ArrayList());
    }
    
    /**
     * Constructs a sequence using the given
     * underlying linear data structure.
     *
     * If the given structure is <CODE>null</CODE>,
     * the default structure is used.
     *
     * @param l the data structure to be used
     * @see #StringableFilterSequence()
     */
    public StringableFilterSequence(List l) {
        if (l == null)
            l = new ArrayList();
            
        filters = l;
    }
    
    //////////////////////
    // StringableFilter //
    //////////////////////

    /**
     * Applies the filters in this sequence in order.
     *
     * @param obj the object to be filtered
     * @see StringableFilter
     */
    public Stringable filterStringable(Stringable obj) 
        throws FilterException 
    {
        // for each of the filters in the list
        Iterator elements = iterator();
        while (elements.hasNext()) {
            Object element = elements.next();

            // apply the filter
            if (element instanceof StringableFilter) {
                StringableFilter f = (StringableFilter)element;
                obj = f.filterStringable(obj);
            }
        }
        
        // return the filtered object
        return obj;
    }    

    ////////////////
    // Public API //
    ////////////////

    /**
     * Inserts the given filter 
     * at the given index in this sequence.
     *
     * @see #add(StringableFilter)
     */
    public void add(int index, StringableFilter f) {
        filters.add(index, f);
    } 

    /**
     * Appends the given filter to the end of this sequence.
     *
     * @return whether or not the filter was successfully added
     * @see #add(int, StringableFilter)
     */
    public boolean add(StringableFilter f) {
        return filters.add(f);
    }
    
    // The following methods have not been implemented
    // since they are not applicable to this class
    //
    // public boolean addAll(Collection c) {
    // public boolean addAll(int index, Collection c) 

    /**
     * Removes all of the filters from this sequence.
     */
    public void clear() {
        filters.clear();
    }

    /**
     * Returns <CODE>true</CODE> if the given filter 
     * is contained in this sequence, 
     * or <CODE>false</CODE> if it is not.
     *
     * @see #containsAll(Collection)
     */
    public boolean contains(StringableFilter f) {
        return filters.contains(f);
    }

    /**
     * Returns <CODE>true</CODE> if this sequence contains 
     * all of the elements of the specified collection.
     *
     * @see #contains(StringableFilter)
     */
    public boolean containsAll(Collection c) {
        return filters.containsAll(c);
    }

    /**
     * Returns <CODE>true</CODE> if the given sequence 
     * is equal to this sequence, 
     * and <CODE>false</CODE> if it is not.
     */
    public boolean equals(StringableFilterSequence sequence) {
        if (filters == null)
            return false;
            
        return filters.equals(sequence.filters);
    }

    /**
     * Returns the filter at the given index in this sequence.
     */
    public StringableFilter get(int index) {
        return (StringableFilter)filters.get(index);
    }

    /**
     * Returns a hash code value for this sequence.
     */
    public int hashCode() {
        return filters.hashCode();
    }

    /**
     * Returns the index in this sequence 
     * of the first occurence of the given filter, 
     * or -1 if this sequence does not contain this filter.
     *
     * @see #lastIndexOf(StringableFilter)
     */
    public int indexOf(StringableFilter f) {
        return filters.indexOf(f);
    }

    /**
     * Returns <CODE>true</CODE> if this sequence is empty,
     * and <CODE>false</CODE> if it is not.
     *
     * @see #size()
     */
    public boolean isEmpty() {
        return filters.isEmpty();
    }

    /**
     * Returns an iterator 
     * over the filters in this sequence in order.
     *
     * @see #listIterator()
     * @see #listIterator(int)
     */
    public Iterator iterator() {
        return filters.iterator();
    }

    /**
     * Returns the index in this sequence
     * of the last occurrence of the given filter,
     * or -1 if this list does not contain this filter.
     *
     * @see #indexOf(StringableFilter)
     */
    public int lastIndexOf(StringableFilter f) {
        return filters.lastIndexOf(f);
    }

    /**
     * Returns a list iterator 
     * over the filters in this sequence in order.
     *
     * @see #listIterator(int)
     * @see #iterator()
     */
    public ListIterator listIterator() {
        return filters.listIterator();
    }

    /**
     * Returns a list iterator 
     * over the filters in this sequence in order, 
     * starting at the given index.
     *
     * @see #listIterator()
     * @see #iterator()
     */
    public ListIterator listIterator(int index) {
        return filters.listIterator(index);
    }

    /**
     * Removes the filter at the given index of the sequence.
     *
     * @return the filter that was removed
     * @see #remove(StringableFilter)
     */
    public StringableFilter remove(int index) {
        return (StringableFilter)filters.remove(index);
    }

    /**
     * Removes the first occurrence 
     * of the given filter in this sequence,
     * and returns <CODE>true</CODE>, 
     * or returns <CODE>false</CODE>
     * if this sequence does not contain the filter.
     *
     * @see #remove(int)
     */
    public boolean remove(StringableFilter f) {
        return filters.remove(f);
    }

    // The following methods have not been implemented
    // since they are not applicable to this class
    //
    // public boolean removeAll(Collection c) 
    // public boolean retainAll(Collection c) 

    /**
     * Replaces the filter 
     * at the given index in this sequence
     * with the given filter. 
     * 
     * @return the filter that was replaced
     */
    public StringableFilter set(int index, StringableFilter f) {
        return (StringableFilter)filters.set(index, f); 
    }
    
    /**
     * Returns the number of filters in this sequence.
     *
     * @see #isEmpty()
     */
    public int size() {
        return filters.size();
    }

    /**
     * Returns a sequence of filters 
     * containing the filters in this sequence 
     * from the given starting index 
     * to the given ending index, exclusive.
     *
     * @see #listIterator(int)
     */
    public StringableFilterSequence subList(int fromIndex, int toIndex) {
        StringableFilterSequence subsequence = new StringableFilterSequence();
        subsequence.filters = filters.subList(fromIndex, toIndex);
        return subsequence;
    }    

    /**
     * Returns an array 
     * containing the filters in this sequence in order.
     *
     * @see #iterator()
     * @see #listIterator()
     */
    public StringableFilter[] toArray() {
        return (StringableFilter[])filters.toArray(new StringableFilter[0]);
    }
    
    // The following methods have not been implemented
    // since they are not applicable to this class
    //
    // public Object[] toArray(Object[]) 
}
