//
// $Id$
//
// Depot library - a Java relational persistence library
// Copyright (C) 2006-2009 Michael Bayne and Pär Winzell
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

package com.samskivert.depot.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import com.google.common.base.Function;
import com.google.common.collect.Iterators;

/**
 * Provides read-only access to a sequence of elements. Note that these elements will generally be
 * computed via the application of a {@link Function} *every time* you iterate over this sequence.
 * Thus a caller is expected to either simply iterate over the elements once, or use {@link
 * #toList} to convert the sequence to concrete list to avoid repeated application of the
 * conversion function on elements of the sequence.
 */
public abstract class Sequence<T> implements Iterable<T>
{
    /**
     * Applies the supplied mapping function to the elements in the supplied collection, returning
     * a lazily created read-only view of the mapped elements.
     */
    public static <F, T> Sequence<T> map (final Collection<F> source,
                                          final Function<? super F, ? extends T> func)
    {
        return new Sequence<T>() {
            public Iterator<T> iterator () {
                return Iterators.transform(source.iterator(), func);
            }
            public int size () {
                return source.size();
            }
            public boolean isEmpty () {
                return source.isEmpty();
            }
            public ArrayList<T> toList () {
                ArrayList<T> list = new ArrayList<T>(source.size());
                for (F elem : source) {
                    list.add(func.apply(elem));
                }
                return list;
            }
        };
    }

    // from interface Iterable
    public abstract Iterator<T> iterator ();

    /**
     * Returns the number of elements in this sequence.
     */
    public abstract int size ();

    /**
     * Returns true if this sequence is empty, false if it contains at least one element.
     */
    public abstract boolean isEmpty ();

    /**
     * Converts this sequence into an array list.
     */
    public abstract ArrayList<T> toList ();
}

@@ -895,16 +895,49 @@
 .util;%0A%0A
+import java.lang.reflect.Array;%0A%0A
 import j
@@ -956,16 +956,16 @@
 ayList;%0A
-
 import j
@@ -1049,24 +1049,69 @@
 e.Function;%0A
+import com.google.common.base.Preconditions;%0A
 import com.g
@@ -1983,16 +1983,102 @@
 )%0A    %7B%0A
+        Preconditions.checkNotNull(source);%0A        Preconditions.checkNotNull(func);%0A
         
@@ -2666,32 +2666,392 @@
 ;%0A            %7D%0A
+            public T%5B%5D toArray (Class%3CT%3E clazz) %7B%0A                @SuppressWarnings(%22unchecked%22)%0A                T%5B%5D array = (T%5B%5D) Array.newInstance(clazz, source.size());%0A                int index = 0;%0A                for (F elem : source) %7B%0A                    array%5Bindex++%5D = func.apply(elem);%0A                %7D%0A                return array;%0A            %7D%0A
         %7D;%0A    %7D
@@ -3440,32 +3440,32 @@
 y list.%0A     */%0A
-
     public abstr
@@ -3491,11 +3491,189 @@
 List ();
+%0A%0A    /**%0A     * Converts this sequence into an array.%0A     * I wish this were %3CS super T%3E S%5B%5D toArray (Class%3CS? clazz);%0A     */%0A    public abstract T%5B%5D toArray (Class%3CT%3E clazz);
 %0A%7D%0A

Check our preconditions for fast failure, and added toArray().