/* * Copyright (C) 2000 - 2008 TagServlet Ltd * * This file is part of Open BlueDragon (OpenBD) CFML Server Engine. * * OpenBD is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * Free Software Foundation,version 3. * * OpenBD 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenBD. If not, see http://www.gnu.org/licenses/ * * Additional permission under GNU GPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or combining * it with any of the JARS listed in the README.txt (or a modified version of * (that library), containing parts covered by the terms of that JAR, the * licensors of this Program grant you additional permission to convey the * resulting work. * README.txt @ http://www.openbluedragon.org/license/README.txt * * http://www.openbluedragon.org/ */ package com.naryx.tagfusion.cfm.engine; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.NoSuchElementException; import java.util.Vector; import com.naryx.tagfusion.cfm.tag.tagUtils; public class cfArrayListData extends cfArrayData implements List<Object> { private static final long serialVersionUID = 1; protected cfArrayListData( int _dimensions ){ super( _dimensions ); } protected cfArrayListData( int _dimensions, Vector<? extends cfData> _data ) { super( _dimensions, _data ); } /******************************************************************************* * The following methods implement the java.util.List interface. They're * implemented to support variable sharing between CFML and servlets/JSP * pages. These methods are mostly just wrappers * around the internal "data" attribute that automatically convert between * internal BlueDragon data types and "natural" Java data types. * * TODO: there's a bunch of unsupported methods here that could be supported * quite easily. *******************************************************************************/ /** * * Returns <tt>true</tt> if this list contains the specified element. * More formally, returns <tt>true</tt> if and only if this list contains * at least one element <tt>e</tt> such that * <tt>(o==null ? e==null : o.equals(e))</tt>. * * @param o element whose presence in this list is to be tested. * @return <tt>true</tt> if this list contains the specified element. */ public boolean contains( Object o ) { return data.contains( tagUtils.convertToCfData( o ) ); } /** * Returns an iterator over the elements in this list in proper sequence. * * @return an iterator over the elements in this list in proper sequence. */ public Iterator<Object> iterator() { return new cfArrayDataIterator( data.iterator() ); } /** * Returns a list iterator of the elements in this list (in proper sequence). */ public ListIterator<Object> listIterator() { return new cfArrayDataListIterator( data.listIterator() ); } /** * Returns a list iterator of the elements in this list (in proper sequence), * starting at the specified position in this list. */ public ListIterator<Object> listIterator( int index ) { return new cfArrayDataListIterator( data.listIterator( index ) ); } /** * Returns an array containing all of the elements in this list in proper * sequence. Obeys the general contract of the * <tt>Collection.toArray</tt> method. * * @return an array containing all of the elements in this list in proper * sequence. * @see Arrays#asList(Object[]) */ public Object[] toArray() { Object[] objArray = new Object[ this.size() ]; for ( int i = 0; i < this.size(); i++ ) { objArray[ i ] = this.get( i ); } return objArray; } /** * Returns an array containing all of the elements in this list in proper * sequence; the runtime type of the returned array is that of the * specified array. Obeys the general contract of the * <tt>Collection.toArray(Object[])</tt> method. * * @param a the array into which the elements of this list 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 this list. * * @throws ArrayStoreException if the runtime type of the specified array * is not a supertype of the runtime type of every element in * this list. */ @SuppressWarnings("unchecked") public Object[] toArray( Object a[] ) { throw new UnsupportedOperationException(); } // Modification Operations /** * Appends the specified element to the end of this list (optional * operation). <p> * * Lists that support this operation may place limitations on what * elements may be added to this list. In particular, some * lists will refuse to add null elements, and others will impose * restrictions on the type of elements that may be added. List * classes should clearly specify in their documentation any restrictions * on what elements may be added. * * @param o element to be appended to this list. * @return <tt>true</tt> (as per the general contract of the * <tt>Collection.add</tt> method). * * @throws UnsupportedOperationException if the <tt>add</tt> method is not * supported by this list. * @throws ClassCastException if the class of the specified element * prevents it from being added to this list. * @throws IllegalArgumentException if some aspect of this element * prevents it from being added to this collection. */ public boolean add( Object o ) { return data.add( tagUtils.convertToCfData( o ) ); } /** * Removes the first occurrence in this list of the specified element * (optional operation). If this list does not contain the element, it is * unchanged. More formally, removes the element with the lowest index i * such that <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt> (if * such an element exists). * * @param o element to be removed from this list, if present. * @return <tt>true</tt> if this list contained the specified element. * * @throws UnsupportedOperationException if the <tt>remove</tt> method is * not supported by this list. */ public boolean remove( Object o ) { for ( int i = 0; i < data.size(); i++ ){ if ( tagUtils.getNatural( data.get(i) ).equals( o ) ){ data.remove(i); return true; } } return false; } // Bulk Modification Operations /** * * Returns <tt>true</tt> if this list contains all of the elements of the * specified collection. * * @param c collection to be checked for containment in this list. * @return <tt>true</tt> if this list contains all of the elements of the * specified collection. * * @see #contains(Object) */ public boolean containsAll( Collection<?> c ) { throw new UnsupportedOperationException(); } /** * Appends all of the elements in the specified collection to the end of * this list, in the order that they are returned by the specified * collection's iterator (optional operation). The behavior of this * operation is unspecified if the specified collection is modified while * the operation is in progress. (Note that this will occur if the * specified collection is this list, and it's nonempty.) * * @param c collection whose elements are to be added to this list. * @return <tt>true</tt> if this list changed as a result of the call. * * @throws UnsupportedOperationException if the <tt>addAll</tt> method is * not supported by this list. * * @throws ClassCastException if the class of an element in the specified * collection prevents it from being added to this list. * * @throws IllegalArgumentException if some aspect of an element in the * specified collection prevents it from being added to this * list. * * @see #add(Object) */ public boolean addAll( Collection<?> c ) { synchronized(c){ Iterator<?> it = c.iterator(); while( it.hasNext() ){ add( it.next() ); } } // list will have changed if collection has at least 1 item return c.size() > 0; } /** * Inserts all of the elements in the specified collection into this * list at the specified position (optional operation). Shifts the * element currently at that position (if any) and any subsequent * elements to the right (increases their indices). The new elements * will appear in this list in the order that they are returned by the * specified collection's iterator. The behavior of this operation is * unspecified if the specified collection is modified while the * operation is in progress. (Note that this will occur if the specified * collection is this list, and it's nonempty.) * * @param index index at which to insert first element from the specified * collection. * @param c elements to be inserted into this list. * @return <tt>true</tt> if this list changed as a result of the call. * * @throws UnsupportedOperationException if the <tt>addAll</tt> method is * not supported by this list. * @throws ClassCastException if the class of one of elements of the * specified collection prevents it from being added to this * list. * @throws IllegalArgumentException if some aspect of one of elements of * the specified collection prevents it from being added to * this list. * @throws IndexOutOfBoundsException if the index is out of range (index * < 0 || index > size()). */ public boolean addAll( int index, Collection<?> c ) { synchronized(c){ int offset = index; Iterator<?> it = c.iterator(); while( it.hasNext() ){ add( offset++, it.next() ); } } // list will have changed if collection has at least 1 item return c.size() > 0; } /** * Removes from this list all the elements that are contained in the * specified collection (optional operation). * * @param c collection that defines which elements will be removed from * this list. * @return <tt>true</tt> if this list changed as a result of the call. * * @throws UnsupportedOperationException if the <tt>removeAll</tt> method * is not supported by this list. * * @see #remove(Object) * @see #contains(Object) */ public boolean removeAll( Collection<?> c ) { boolean changed = false; int index = 0; while ( index < data.size() ){ Object natural = tagUtils.getNatural( data.get(index) ); Iterator<?> cIterator = c.iterator(); while ( cIterator.hasNext() ){ if ( natural.equals( cIterator.next() ) ){ data.remove( index ); changed = true; index--; // offset the increment break; } } index++; } return changed; } /** * Retains only the elements in this list that are contained in the * specified collection (optional operation). In other words, removes * from this list all the elements that are not contained in the specified * collection. * * @param c collection that defines which elements this set will retain. * * @return <tt>true</tt> if this list changed as a result of the call. * * @throws UnsupportedOperationException if the <tt>retainAll</tt> method * is not supported by this list. * * @see #remove(Object) * @see #contains(Object) */ public boolean retainAll( Collection<?> c ) { throw new UnsupportedOperationException(); } /** * Removes all of the elements from this list (optional operation). This * list will be empty after this call returns (unless it throws an * exception). * * @throws UnsupportedOperationException if the <tt>clear</tt> method is * not supported by this list. */ public void clear() { data.clear(); } // Positional Access Operations /** * Returns the element at the specified position in this list. * * @param index index of element to return. * @return the element at the specified position in this list. * * @throws IndexOutOfBoundsException if the index is out of range (index * < 0 || index >= size()). */ public Object get( int index ) { return tagUtils.getNatural( data.get( index ) ); } /** * Replaces the element at the specified position in this list with the * specified element (optional operation). * * @param index index of element to replace. * @param element element to be stored at the specified position. * @return the element previously at the specified position. * * @throws UnsupportedOperationException if the <tt>set</tt> method is not * supported by this list. * @throws ClassCastException if the class of the specified element * prevents it from being added to this list. * @throws IllegalArgumentException if some aspect of the specified * element prevents it from being added to this list. * @throws IndexOutOfBoundsException if the index is out of range * (index < 0 || index >= size()). */ public Object set( int index, Object element ) { return tagUtils.getNatural( data.set( index, tagUtils.convertToCfData( element ) ) ); } /** * Inserts the specified element at the specified position in this list * (optional operation). Shifts the element currently at that position * (if any) and any subsequent elements to the right (adds one to their * indices). * * @param index index at which the specified element is to be inserted. * @param element element to be inserted. * * @throws UnsupportedOperationException if the <tt>add</tt> method is not * supported by this list. * @throws ClassCastException if the class of the specified element * prevents it from being added to this list. * @throws IllegalArgumentException if some aspect of the specified * element prevents it from being added to this list. * @throws IndexOutOfBoundsException if the index is out of range * (index < 0 || index > size()). */ public void add( int index, Object element ) { data.add( index, tagUtils.convertToCfData( element ) ); } /** * Removes the element at the specified position in this list (optional * operation). Shifts any subsequent elements to the left (subtracts one * from their indices). Returns the element that was removed from the * list. * * @param index the index of the element to removed. * @return the element previously at the specified position. * * @throws UnsupportedOperationException if the <tt>remove</tt> method is * not supported by this list. * * @throws IndexOutOfBoundsException if the index is out of range (index * < 0 || index >= size()). */ public Object remove( int index ) { return tagUtils.getNatural( data.remove( index ) ); } // Search Operations /** * Returns the index in this list of the first occurrence of the specified * element, or -1 if this list does not contain this element. * More formally, returns the lowest index <tt>i</tt> such that * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, * or -1 if there is no such index. * * @param o element to search for. * @return the index in this list of the first occurrence of the specified * element, or -1 if this list does not contain this element. */ public int indexOf( Object o ) { throw new UnsupportedOperationException(); } /** * Returns the index in this list of the last occurrence of the specified * element, or -1 if this list does not contain this element. * More formally, returns the highest index <tt>i</tt> such that * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, * or -1 if there is no such index. * * @param o element to search for. * @return the index in this list of the last occurrence of the specified * element, or -1 if this list does not contain this element. */ public int lastIndexOf( Object o ) { throw new UnsupportedOperationException(); } // View /** * Returns a view of the portion of this list between the specified * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive. (If * <tt>fromIndex</tt> and <tt>toIndex</tt> are equal, the returned list is * empty.) The returned list is backed by this list, so changes in the * returned list are reflected in this list, and vice-versa. The returned * list supports all of the optional list operations supported by this * list.<p> * * This method eliminates the need for explicit range operations (of * the sort that commonly exist for arrays). Any operation that expects * a list can be used as a range operation by passing a subList view * instead of a whole list. For example, the following idiom * removes a range of elements from a list: * <pre> * list.subList(from, to).clear(); * </pre> * Similar idioms may be constructed for <tt>indexOf</tt> and * <tt>lastIndexOf</tt>, and all of the algorithms in the * <tt>Collections</tt> class can be applied to a subList.<p> * * The semantics of this list returned by this method become undefined if * the backing list (i.e., this list) is <i>structurally modified</i> in * any way other than via the returned list. (Structural modifications are * those that change the size of this list, or otherwise perturb it in such * a fashion that iterations in progress may yield incorrect results.) * * @param fromIndex low endpoint (inclusive) of the subList. * @param toIndex high endpoint (exclusive) of the subList. * @return a view of the specified range within this list. * * @throws IndexOutOfBoundsException for an illegal endpoint index value * (fromIndex < 0 || toIndex > size || fromIndex > toIndex). */ public List<Object> subList( int fromIndex, int toIndex ) { throw new UnsupportedOperationException(); } public class cfArrayDataIterator implements Iterator<Object> { protected Iterator<cfData> iter; public cfArrayDataIterator( Iterator<cfData> _iter ) { iter = _iter; } /** * Returns <tt>true</tt> if this list iterator has more elements when * traversing the list in the forward direction. (In other words, returns * <tt>true</tt> if <tt>next</tt> would return an element rather than * throwing an exception.) * * @return <tt>true</tt> if the list iterator has more elements when * traversing the list in the forward direction. */ public boolean hasNext() { return iter.hasNext(); } /** * Returns the next element in the list. This method may be called * repeatedly to iterate through the list, or intermixed with calls to * <tt>previous</tt> to go back and forth. (Note that alternating calls * to <tt>next</tt> and <tt>previous</tt> will return the same element * repeatedly.) * * @return the next element in the list. * @exception NoSuchElementException if the iteration has no next element. */ public Object next() { return tagUtils.getNatural( iter.next() ); } /** * Removes from the list the last element that was returned by * <tt>next</tt> or <tt>previous</tt> (optional operation). This call can * only be made once per call to <tt>next</tt> or <tt>previous</tt>. It * can be made only if <tt>ListIterator.add</tt> has not been called after * the last call to <tt>next</tt> or <tt>previous</tt>. * * @exception UnsupportedOperationException if the <tt>remove</tt> * operation is not supported by this list iterator. * @exception IllegalStateException neither <tt>next</tt> nor * <tt>previous</tt> have been called, or <tt>remove</tt> or * <tt>add</tt> have been called after the last call to * * <tt>next</tt> or <tt>previous</tt>. */ public void remove() { iter.remove(); } } public class cfArrayDataListIterator extends cfArrayDataIterator implements ListIterator<Object> { public cfArrayDataListIterator( ListIterator<cfData> _iter ) { super( _iter ); } /** * Returns <tt>true</tt> if this list iterator has more elements when * traversing the list in the reverse direction. (In other words, returns * <tt>true</tt> if <tt>previous</tt> would return an element rather than * throwing an exception.) * * @return <tt>true</tt> if the list iterator has more elements when * traversing the list in the reverse direction. */ public boolean hasPrevious() { return ((ListIterator<cfData>)iter).hasPrevious(); } /** * Returns the previous element in the list. This method may be called * repeatedly to iterate through the list backwards, or intermixed with * calls to <tt>next</tt> to go back and forth. (Note that alternating * calls to <tt>next</tt> and <tt>previous</tt> will return the same * element repeatedly.) * * @return the previous element in the list. * * @exception NoSuchElementException if the iteration has no previous * element. */ public Object previous() { return ((ListIterator<cfData>)iter).previous(); } /** * Returns the index of the element that would be returned by a subsequent * call to <tt>next</tt>. (Returns list size if the list iterator is at the * end of the list.) * * @return the index of the element that would be returned by a subsequent * call to <tt>next</tt>, or list size if list iterator is at end * of list. */ public int nextIndex() { return ((ListIterator<cfData>)iter).nextIndex(); } /** * Returns the index of the element that would be returned by a subsequent * call to <tt>previous</tt>. (Returns -1 if the list iterator is at the * beginning of the list.) * * @return the index of the element that would be returned by a subsequent * call to <tt>previous</tt>, or -1 if list iterator is at * beginning of list. */ public int previousIndex() { return ((ListIterator<cfData>)iter).previousIndex(); } // Modification Operations /** * Replaces the last element returned by <tt>next</tt> or * <tt>previous</tt> with the specified element (optional operation). * This call can be made only if neither <tt>ListIterator.remove</tt> nor * <tt>ListIterator.add</tt> have been called after the last call to * <tt>next</tt> or <tt>previous</tt>. * * @param o the element with which to replace the last element returned by * <tt>next</tt> or <tt>previous</tt>. * @exception UnsupportedOperationException if the <tt>set</tt> operation * is not supported by this list iterator. * @exception ClassCastException if the class of the specified element * prevents it from being added to this list. * @exception IllegalArgumentException if some aspect of the specified * element prevents it from being added to this list. * @exception IllegalStateException if neither <tt>next</tt> nor * <tt>previous</tt> have been called, or <tt>remove</tt> or * <tt>add</tt> have been called after the last call to * <tt>next</tt> or <tt>previous</tt>. */ public void set( Object o ) { ((ListIterator<cfData>)iter).set( tagUtils.convertToCfData( o ) ); } /** * Inserts the specified element into the list (optional operation). The * element is inserted immediately before the next element that would be * returned by <tt>next</tt>, if any, and after the next element that * would be returned by <tt>previous</tt>, if any. (If the list contains * no elements, the new element becomes the sole element on the list.) * The new element is inserted before the implicit cursor: a subsequent * call to <tt>next</tt> would be unaffected, and a subsequent call to * <tt>previous</tt> would return the new element. (This call increases * by one the value that would be returned by a call to <tt>nextIndex</tt> * or <tt>previousIndex</tt>.) * * @param o the element to insert. * @exception UnsupportedOperationException if the <tt>add</tt> method is * not supported by this list iterator. * * @exception ClassCastException if the class of the specified element * prevents it from being added to this Set. * * @exception IllegalArgumentException if some aspect of this element * prevents it from being added to this Collection. */ public void add( Object o ) { ((ListIterator<cfData>)iter).add( tagUtils.convertToCfData( o ) ); } } }