// Copyright (c) 1996-2002 Brian D. Carlstrom

package bdc.util;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public final class ListUtil
{
        //protected method used in MapUtil and ListUtil
    static Object copyValue (Object value)
    {
        if (value instanceof Map) {
            return MapUtil.copyMap((Map)value);
        }
        else if (value instanceof List) {
            return copyList((List)value);
        }
        else {
            return value;
        }
    }
    
    /**
       Copy a List.  This method will copy the source List and
       output a destination List.  For each List or hastable
       within the source List they will also be copied, all other
       types will be shared.  So for a List of Lists or
       Maps, this will recurse.

       @param source the source List to copy.
       @return the destination List.
    */
    public static List copyList (List source)
    {
        List destination = new ArrayList(source.size());
        for (int i=0, s=source.size(); i<s; i++) {
            Object value = source.get(i);
            destination.add(copyValue(value));
        }
        return destination;
    }
    
    /**
        Helper function to create a new empty List.

        @return a new empty List
    */
    public static List List ()
    {
        return new ArrayList(0);
    }

    /**
        Helper function to create a new ArrayList containing one Object.

        @param object the Object to add to the List

        @return a new ArrayList containing the specified <b>object</b>
    */
    public static List List (Object object)
    {
        List list = new ArrayList(1);
        list.add(object);
        return list;
    }

    /**
        Helper function to create a new ArrayList containing two Objects.

        @param a the first Object to add to the List
        @param b the second Object to add to the List

        @return a new ArrayList containing the specified objects
    */
    public static List List (Object a, Object b)
    {
        List list = new ArrayList(2);
        list.add(a);
        list.add(b);
        return list;
    }

    /**
        Helper function to create a new ArrayList containing three
        Objects.

        @param a the first Object to add to the List
        @param b the second Object to add to the List
        @param c the third Object to add to the List

        @return a new ArrayList containing the specified objects
    */
    public static List List (Object a, Object b, Object c)
    {
        List list = new ArrayList(3);
        list.add(a);
        list.add(b);
        list.add(c);
        return list;
    }

    /**
        Helper function to create a new ArrayList containing four
        Objects.

        @param a the first Object to add to the List
        @param b the second Object to add to the List
        @param c the third Object to add to the List
        @param d the fourth Object to add to the List

        @return a new ArrayList containing the specified objects
    */
    public static List List (Object a, Object b, Object c, Object d)
    {
        List list = new ArrayList(4);
        list.add(a);
        list.add(b);
        list.add(c);
        list.add(d);
        return list;
    }
    /**
        Helper function to create a new ArrayList containing five
        Objects.

        @param a the first Object to add to the List
        @param b the second Object to add to the List
        @param c the third Object to add to the List
        @param d the fourth Object to add to the List
        @param e the fifth Object to add to the List

        @return a new ArrayList containing the specified objects
    */
    public static List List (Object a, Object b, Object c, Object d,
                                 Object e)
    {
        List list = new ArrayList(5);
        list.add(a);
        list.add(b);
        list.add(c);
        list.add(d);
        list.add(e);
        return list;
    }

    /**
        Helper function to create a new ArrayList containing six Objects.

        @param a the first Object to add to the List
        @param b the second Object to add to the List
        @param c the third Object to add to the List
        @param d the fourth Object to add to the List
        @param e the fifth Object to add to the List
        @param f the sixth Object to add to the List

        @return a new ArrayList containing the specified objects
    */
    public static List List (Object a, Object b, Object c, Object d,
                                 Object e, Object f)
    {
        List list = new ArrayList(6);
        list.add(a);
        list.add(b);
        list.add(c);
        list.add(d);
        list.add(e);
        list.add(f);
        return list;
    }

    /**
        Helper function to create a new ArrayList containing seven
        Objects.

        @param a the first Object to add to the List
        @param b the second Object to add to the List
        @param c the third Object to add to the List
        @param d the fourth Object to add to the List
        @param e the fifth Object to add to the List
        @param f the sixth Object to add to the List
        @param g the seventh Object to add to the List

        @return a new ArrayList containing the specified objects
    */
    public static List List (Object a, Object b, Object c, Object d,
                                 Object e, Object f, Object g)
    {
        List list = new ArrayList(7);
        list.add(a);
        list.add(b);
        list.add(c);
        list.add(d);
        list.add(e);
        list.add(f);
        list.add(g);
        return list;
    }

    /**
        Helper function to create a new ArrayList containing eight
        Objects.

        @param a the first Object to add to the List
        @param b the second Object to add to the List
        @param c the third Object to add to the List
        @param d the fourth Object to add to the List
        @param e the fifth Object to add to the List
        @param f the sixth Object to add to the List
        @param g the seventh Object to add to the List
        @param h the eighth Object to add to the List

        @return a new ArrayList containing the specified objects
    */
    public static List List (Object a, Object b, Object c, Object d,
                                 Object e, Object f, Object g, Object h)
    {
        List list = new ArrayList(8);
        list.add(a);
        list.add(b);
        list.add(c);
        list.add(d);
        list.add(e);
        list.add(f);
        list.add(g);
        list.add(h);
        return list;
    }

    /**
        Helper function to create a new ArrayList containing nine
        Objects.

        @param a the first Object to add to the List
        @param b the second Object to add to the List
        @param c the third Object to add to the List
        @param d the fourth Object to add to the List
        @param e the fifth Object to add to the List
        @param f the sixth Object to add to the List
        @param g the seventh Object to add to the List
        @param h the eighth Object to add to the List
        @param i the ninth Object to add to the List

        @return a new ArrayList containing the specified objects
    */
    public static List List (Object a, Object b, Object c, Object d,
                                 Object e, Object f, Object g, Object h,
                                 Object i)
    {
        List list = new ArrayList(9);
        list.add(a);
        list.add(b);
        list.add(c);
        list.add(d);
        list.add(e);
        list.add(f);
        list.add(g);
        list.add(h);
        list.add(i);
        return list;
    }

    /**
        Helper function to create a new ArrayList containing ten Objects.

        @param a the first Object to add to the List
        @param b the second Object to add to the List
        @param c the third Object to add to the List
        @param d the fourth Object to add to the List
        @param e the fifth Object to add to the List
        @param f the sixth Object to add to the List
        @param g the seventh Object to add to the List
        @param h the eighth Object to add to the List
        @param i the ninth Object to add to the List
        @param j the tenth Object to add to the List

        @return a new ArrayList containing the specified objects
    */
    public static List List (Object a, Object b, Object c, Object d,
                                 Object e, Object f, Object g, Object h,
                                 Object i, Object j)
    {
        List list = new ArrayList(10);
        list.add(a);
        list.add(b);
        list.add(c);
        list.add(d);
        list.add(e);
        list.add(f);
        list.add(g);
        list.add(h);
        list.add(i);
        list.add(j);
        return list;
    }

    /**
        Helper function to create a new ArrayList containing eleven
        Objects.

        @param a the first Object to add to the List
        @param b the second Object to add to the List
        @param c the third Object to add to the List
        @param d the fourth Object to add to the List
        @param e the fifth Object to add to the List
        @param f the sixth Object to add to the List
        @param g the seventh Object to add to the List
        @param h the eighth Object to add to the List
        @param i the ninth Object to add to the List
        @param j the tenth Object to add to the List
        @param k the eleventh Object to add to the List

        @return a new ArrayList containing the specified objects
    */
    public static List List (Object a, Object b, Object c, Object d,
                                 Object e, Object f, Object g, Object h,
                                 Object i, Object j, Object k)
    {
        List list = new ArrayList(11);
        list.add(a);
        list.add(b);
        list.add(c);
        list.add(d);
        list.add(e);
        list.add(f);
        list.add(g);
        list.add(h);
        list.add(i);
        list.add(j);
        list.add(k);
        return list;
    }

    /**
        Helper function to create a new ArrayList containing twelve
        Objects.

        @param a the first Object to add to the List
        @param b the second Object to add to the List
        @param c the third Object to add to the List
        @param d the fourth Object to add to the List
        @param e the fifth Object to add to the List
        @param f the sixth Object to add to the List
        @param g the seventh Object to add to the List
        @param h the eighth Object to add to the List
        @param i the ninth Object to add to the List
        @param j the tenth Object to add to the List
        @param k the eleventh Object to add to the List
        @param l the twelfth Object to add to the List

        @return a new ArrayList containing the specified objects
    */
    public static List List (Object a, Object b, Object c, Object d,
                             Object e, Object f, Object g, Object h,
                             Object i, Object j, Object k, Object l)
    {
        List list = new ArrayList(12);
        list.add(a);
        list.add(b);
        list.add(c);
        list.add(d);
        list.add(e);
        list.add(f);
        list.add(g);
        list.add(h);
        list.add(i);
        list.add(j);
        list.add(k);
        list.add(l);
        return list;
    }

    /**
        Null safe method to check the length of a List.

        @param List a List to check the size of. <b>null</b> is an
        acceptable value for this argument.

        @return the length of the <B>List</B>, or zero if it is
        null.
    */
    public static int getListSize (List List)
    {
        if (List != null) {
            return List.size();
        }
        return 0;
    }

    /**
        Determine if a List is null or empty.

        @param List a List object to check

        @return <b>true</b> if <B>List</B> is null or empty,
        <b>false</b> otherwise
    */
    public static boolean nullOrEmptyList (List List)
    {
        return (List == null) || List.isEmpty();
    }

    /**
        Removes all elements from the two Lists <B>l1</B> and <B>l2</B>
        which are contained in both. If a particular element appears N times
        in <B>l1</B> and M times in <B>l2</B>, it will be deleted min(N, M)
        times from both Lists.

        @param l1 the first List
        @param l2 the second List
    */
    public static void removeEqualElements (List l1, List l2)
    {
        List dups = equalElements(l1, l2);
        for (int i=0; i<dups.size(); i++) {
            Object o = dups.get(i);
            if (l1.contains(o) && l2.contains(o)) {
                l1.remove(o);
                l2.remove(o);
            }
        }
    }

    /**
        Determine all elements common between two Lists.

        @param l1 the first List
        @param l2 the second List

        @return a list of all elements common to <b>l1</b> and
        <b>l2</b>.The comparison is made using List.contains().
    */
    public static List equalElements (List l1, List l2)
    {
        List common = new ArrayList();
        for (int i=0, s=l1.size(); i<s; i++) {
            Object o = l1.get(i);
            if (l2.contains(o)) {
                common.add(o);
            }
        }
        return common;
    }

    /**
        Generate a comma separated list of strings from a List.

        @param v a List of objects to put into the string
        @return a comma separated list of the strings in <b>v</b>
    */
    public static String listToCSVString (List l)
    {
        return listToString(l, ",");
    }

   
    /**
        Generate a string from a List, separating the elements with
        the specified string.  Include a space on the separator if you
        want spaces after the separator literal.

        @param v a List of objects to put into the string
        @param separator a String that should separate each element of v
        @return a String containing elements of v separated by separator
    */
    public static String listToString (List l, String separator)
    {
        FastStringBuffer sb = new FastStringBuffer();
        for (int i=0, s=l.size(); i<s; i++) {
            if (i != 0) {
                sb.append(separator);
            }
            Object o = l.get(i);
            sb.append(o.toString());
        }
        return sb.toString();
    }  

    /**
        Determine if the two Lists are equal.

        @param l1 the first List
        @param l2 the second List

        @return <b>true</b> if the two Lists are equal, <b>false</b>
        otherwise
    */
    public static boolean listEquals (List l1, List l2)
    {
        if (l1 == l2) {
            return true;
        }
        if (l1 == null || l2 == null || l1.size() != l2.size()) {
            return false;
        }
        for (int i = 0; i < l1.size(); i++) {
            Object o1 = l1.get(i);
            Object o2 = l2.get(i);
            if (!o1.equals(o2)) {
                return false;
            }
        }
        return true;
    }

    /**
        Adds <b>element</b> as the last element of the List, if not
        already present within the List.

        @param list the list to append to
        @param element the element to add
    */
    public static void addIfAbsent (List list, Object element)
    {
        if (!list.contains(element)) {
            list.add(element);
        }
    }

    /**
        keep people from creating this class
    */
    private ListUtil ()
    {
    }
}
