DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG 
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://nagoya.apache.org/bugzilla/show_bug.cgi?id=4370>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND 
INSERTED IN THE BUG DATABASE.

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=4370

Add handling of primitive arrays with foreach

           Summary: Add handling of primitive arrays with foreach
           Product: Velocity
           Version: 1.1
          Platform: Other
        OS/Version: Other
            Status: NEW
          Severity: Normal
          Priority: Other
         Component: Build
        AssignedTo: [EMAIL PROTECTED]
        ReportedBy: [EMAIL PROTECTED]


It would be really nice if you added support for primitive arrays with foreach. 
You currently handle arrays of objects by creating an iterator for the array 
when invoking foreach on it. Why not do the same thing with primitive arrays.

I know you will probably tell me that I can always create my own wrapper around 
the array, but that has its problems.

I can create my own Iterator wrapper and add it to the context, but what if I 
need to use that data in multiple foreach statements? I can't use the same 
iterator more than once.

I could create a Collection wrapper for the array, but that is a lot of extra 
work. I don't need the entire collection interface I just want you to iterate 
over the array.

I could create another array creating wrappers for each item (e.g. if I have a 
byte[] create a Byte[]), but that is horribly inefficient for arrays of any 
size.

So the best solution is for Velocity to create an iterator on demand.

It really is not difficult to actually achieve. You already have the 
ArrayIterator class for iterating over arrays of Object. It is easily modified 
to work with any array. Or you can create a separate iterator for primitive 
arrays.

To see how to do that here is the source for the PrimitiveArrayIterator from 
WebMacro which you can compare to your ArrayIterator:

final public class PrimitiveArrayIterator implements Iterator
{
   private final Object a;
   private int _size;
   private int pos;

   public PrimitiveArrayIterator(Object array) 
   {
      if (!array.getClass().isArray()) 
        throw new IllegalArgumentException(array.getClass().getName() 
          + " is not an array.");
      this.a = array;
      _size = java.lang.reflect.Array.getLength(a);
      pos = 0;
   }

   /**
     * Return true if we have not yet reached the end of the enumeration
     */
   final public boolean hasNext() 
   {
      return (pos < _size);
   }

   /**
     * Advance the iterator and return the next value. Return null if we
     * reach the end of the enumeration.
     */
   final public Object next() throws NoSuchElementException
   {
      if (pos < _size) {
         return java.lang.reflect.Array.get(a, pos++);
      } else {
         throw new NoSuchElementException("Advanced beyond end of array");
      }
   }
   final public void remove() throws UnsupportedOperationException
   {
      throw new UnsupportedOperationException();
   }
}

If you changed your ArrayIterator to work with any type of array then all you 
have to change is instead of this in ForEach.java:

    if( listObject instanceof Object[] )

You would have:

    if( listObject.getClass().isArray() )

And you would not have the cast when creating the ArrayIterator further down.

By the way, while looking at this I noticed that Context.java has an unused 
import of ArrayIterator.

Reply via email to