View Javadoc

    1   // ========================================================================
    2   // Copyright 2004-2005 Mort Bay Consulting Pty. Ltd.
    3   // ------------------------------------------------------------------------
    4   // Licensed under the Apache License, Version 2.0 (the "License");
    5   // you may not use this file except in compliance with the License.
    6   // You may obtain a copy of the License at
    7   // http://www.apache.org/licenses/LICENSE-2.0
    8   // Unless required by applicable law or agreed to in writing, software
    9   // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  // ========================================================================
    14
    15  package org.mortbay.util;
    16  import java.io.Serializable;
    17  import java.lang.reflect.Array;
    18  import java.util.ArrayList;
    19  import java.util.Arrays;
    20  import java.util.Collection;
    21  import java.util.Collections;
    22  import java.util.Iterator;
    23  import java.util.List;
    24  import java.util.ListIterator;
    25
    26  /* ------------------------------------------------------------ */
    27  /** Lazy List creation.
    28   * A List helper class that attempts to avoid unneccessary List
    29   * creation.   If a method needs to create a List to return, but it is
    30   * expected that this will either be empty or frequently contain a
    31   * single item, then using LazyList will avoid additional object
    32   * creations by using Collections.EMPTY_LIST or
    33   * Collections.singletonList where possible.
    34   *
    35   * <p><h4>Usage</h4>
    36   * <pre>
    37   *   Object lazylist =null;
    38   *   while(loopCondition)
    39   *   {
    40   *     Object item = getItem();
    41   *     if (item.isToBeAdded())
    42   *         lazylist = LazyList.add(lazylist,item);
    43   *   }
    44   *   return LazyList.getList(lazylist);
    45   * </pre>
    46   *
    47   * An ArrayList of default size is used as the initial LazyList.
    48   *
    49   * @see java.util.List
    50   * @author Greg Wilkins (gregw)
    51   */
    52  public class LazyList
    53      implements Cloneable, Serializable
    54  {
    55      private static final String[] __EMTPY_STRING_ARRAY = new String[0];
    56
    57      /* ------------------------------------------------------------ */
    58      private LazyList()
    59      {}
    60
    61      /* ------------------------------------------------------------ */
    62      /** Add an item to a LazyList
    63       * @param list The list to add to or null if none yet created.
    64       * @param item The item to add.
    65       * @return The lazylist created or added to.
    66       */
    67      public static Object add(Object list, Object item)
    68      {
    69          if (list==null)
    70          {
    71              if (item instanceof List || item==null)
    72              {
    73                  List l = new ArrayList();
    74                  l.add(item);
    75                  return l;
    76              }
    77
    78              return item;
    79          }
    80
    81          if (list instanceof List)
    82          {
    83              ((List)list).add(item);
    84              return list;
    85          }
    86
    87          List l=new ArrayList();
    88          l.add(list);
    89          l.add(item);
    90          return l;
    91      }
    92
    93      /* ------------------------------------------------------------ */
    94      /** Add an item to a LazyList
    95       * @param list The list to add to or null if none yet created.
    96       * @param index The index to add the item at.
    97       * @param item The item to add.
    98       * @return The lazylist created or added to.
    99       */
    100     public static Object add(Object list, int index, Object item)
    101     {
    102         if (list==null)
    103         {
    104             if (index>0 || item instanceof List || item==null)
    105             {
    106                 List l = new ArrayList();
    107                 l.add(index,item);
    108                 return l;
    109             }
    110             return item;
    111         }
    112
    113         if (list instanceof List)
    114         {
    115             ((List)list).add(index,item);
    116             return list;
    117         }
    118
    119         List l=new ArrayList();
    120         l.add(list);
    121         l.add(index,item);
    122         return l;
    123     }
    124
    125     /* ------------------------------------------------------------ */
    126     /** Add the contents of a Collection to a LazyList
    127      * @param list The list to add to or null if none yet created.
    128      * @param collection The Collection whose contents should be added.
    129      * @return The lazylist created or added to.
    130      */
    131     public static Object addCollection(Object list, Collection collection)
    132     {
    133         Iterator i=collection.iterator();
    134         while(i.hasNext())
    135             list=LazyList.add(list,i.next());
    136         return list;
    137     }
    138
    139     /* ------------------------------------------------------------ */
    140     /** Add the contents of an array to a LazyList
    141      * @param list The list to add to or null if none yet created.
    142      * @param collection The Collection whose contents should be added.
    143      * @return The lazylist created or added to.
    144      */
    145     public static Object addArray(Object list, Object[] array)
    146     {
    147         for(int i=0;array!=null && i<array.length;i++)
    148             list=LazyList.add(list,array[i]);
    149         return list;
    150     }
    151
    152     /* ------------------------------------------------------------ */
    153     /** Ensure the capcity of the underlying list.
    154      *
    155      */
    156     public static Object ensureSize(Object list, int initialSize)
    157     {
    158         if (list==null)
    159             return new ArrayList(initialSize);
    160         if (list instanceof ArrayList)
    161         {
    162             ArrayList ol=(ArrayList)list;
    163             if (ol.size()>initialSize)
    164                 return ol;
    165             ArrayList nl = new ArrayList(initialSize);
    166             nl.addAll(ol);
    167             return nl;
    168         }
    169         List l= new ArrayList(initialSize);
    170         l.add(list);
    171         return l;
    172     }
    173
    174     /* ------------------------------------------------------------ */
    175     public static Object remove(Object list, Object o)
    176     {
    177         if (list==null)
    178             return null;
    179
    180         if (list instanceof List)
    181         {
    182             List l = (List)list;
    183             l.remove(o);
    184             if (l.size()==0)
    185                 return null;
    186             return list;
    187         }
    188
    189         if (list.equals(o))
    190             return null;
    191         return list;
    192     }
    193
    194     /* ------------------------------------------------------------ */
    195     public static Object remove(Object list, int i)
    196     {
    197         if (list==null)
    198             return null;
    199
    200         if (list instanceof List)
    201         {
    202             List l = (List)list;
    203             l.remove(i);
    204             if (l.size()==0)
    205                 return null;
    206             return list;
    207         }
    208
    209         if (i==0)
    210             return null;
    211         return list;
    212     }
    213
    214
    215
    216     /* ------------------------------------------------------------ */
    217     /** Get the real List from a LazyList.
    218      *
    219      * @param list A LazyList returned from LazyList.add(Object)
    220      * @return The List of added items, which may be an EMPTY_LIST
    221      * or a SingletonList.
    222      */
    223     public static List getList(Object list)
    224     {
    225         return getList(list,false);
    226     }
    227
    228
    229     /* ------------------------------------------------------------ */
    230     /** Get the real List from a LazyList.
    231      *
    232      * @param list A LazyList returned from LazyList.add(Object) or null
    233      * @param nullForEmpty If true, null is returned instead of an
    234      * empty list.
    235      * @return The List of added items, which may be null, an EMPTY_LIST
    236      * or a SingletonList.
    237      */
    238     public static List getList(Object list, boolean nullForEmpty)
    239     {
    240         if (list==null)
    241             return nullForEmpty?null:Collections.EMPTY_LIST;
    242         if (list instanceof List)
    243             return (List)list;
    244
    245         List l = new ArrayList(1);
    246         l.add(list);
    247         return l;
    248     }
    249
    250
    251     /* ------------------------------------------------------------ */
    252     public static String[] toStringArray(Object list)
    253     {
    254         if (list==null)
    255             return __EMTPY_STRING_ARRAY;
    256
    257         if (list instanceof List)
    258         {
    259             List l = (List)list;
    260             String[] a = new String[l.size()];
    261             for (int i=l.size();i-->0;)
    262             {
    263                 Object o=l.get(i);
    264                 if (o!=null)
    265                     a[i]=o.toString();
    266             }
    267             return a;
    268         }
    269
    270         return new String[] {list.toString()};
    271     }
    272
    273     /* ------------------------------------------------------------ */
    274     public static Object toArray(Object list,Class aClass)
    275     {
    276         if (list==null)
    277             return (Object[])Array.newInstance(aClass,0);
    278
    279         if (list instanceof List)
    280         {
    281             List l = (List)list;
    282             if (aClass.isPrimitive())
    283             {
    284                 Object a = Array.newInstance(aClass,l.size());
    285                 for (int i=0;i<l.size();i++)
    286                     Array.set(a,i,l.get(i));
    287                 return a;
    288             }
    289             return l.toArray((Object[])Array.newInstance(aClass,l.size()));
    290
    291         }
    292
    293         Object a = Array.newInstance(aClass,1);
    294         Array.set(a,0,list);
    295         return a;
    296     }
    297
    298     /* ------------------------------------------------------------ */
    299     /** The size of a lazy List
    300      * @param list  A LazyList returned from LazyList.add(Object) or null
    301      * @return the size of the list.
    302      */
    303     public static int size(Object list)
    304     {
    305         if (list==null)
    306             return 0;
    307         if (list instanceof List)
    308             return ((List)list).size();
    309         return 1;
    310     }
    311
    312     /* ------------------------------------------------------------ */
    313     /** Get item from the list
    314      * @param list  A LazyList returned from LazyList.add(Object) or null
    315      * @param i int index
    316      * @return the item from the list.
    317      */
    318     public static Object get(Object list, int i)
    319     {
    320         if (list==null)
    321             throw new IndexOutOfBoundsException();
    322
    323         if (list instanceof List)
    324             return ((List)list).get(i);
    325
    326         if (i==0)
    327             return list;
    328
    329         throw new IndexOutOfBoundsException();
    330     }
    331
    332     /* ------------------------------------------------------------ */
    333     public static boolean contains(Object list,Object item)
    334     {
    335         if (list==null)
    336             return false;
    337
    338         if (list instanceof List)
    339             return ((List)list).contains(item);
    340
    341         return list.equals(item);
    342     }
    343
    344
    345     /* ------------------------------------------------------------ */
    346     public static Object clone(Object list)
    347     {
    348         if (list==null)
    349             return null;
    350         if (list instanceof List)
    351             return new ArrayList((List)list);
    352         return list;
    353     }
    354
    355     /* ------------------------------------------------------------ */
    356     public static String toString(Object list)
    357     {
    358         if (list==null)
    359             return "[]";
    360         if (list instanceof List)
    361             return ((List)list).toString();
    362         return "["+list+"]";
    363     }
    364
    365     /* ------------------------------------------------------------ */
    366     public static Iterator iterator(Object list)
    367     {
    368         if (list==null)
    369             return Collections.EMPTY_LIST.iterator();
    370         if (list instanceof List)
    371             return ((List)list).iterator();
    372         return getList(list).iterator();
    373     }
    374
    375     /* ------------------------------------------------------------ */
    376     public static ListIterator listIterator(Object list)
    377     {
    378         if (list==null)
    379             return Collections.EMPTY_LIST.listIterator();
    380         if (list instanceof List)
    381             return ((List)list).listIterator();
    382         return getList(list).listIterator();
    383     }
    384
    385     /* ------------------------------------------------------------ */
    386     /**
    387      * @param array Any array of object
    388      * @return A new <i>modifiable</i> list initialised with the elements from <code>array</code>.
    389      */
    390     public static List array2List(Object[] array)
    391     {
    392         if (array==null || array.length==0)
    393             return new ArrayList();
    394         return new ArrayList(Arrays.asList(array));
    395     }
    396
    397     /* ------------------------------------------------------------ */
    398     /** Add element to an array
    399      * @param array The array to add to (or null)
    400      * @param item The item to add
    401      * @param type The type of the array (in case of null array)
    402      * @return new array with contents of array plus item
    403      */
    404     public static Object[] addToArray(Object[] array, Object item, Class type)
    405     {
    406         if (array==null)
    407         {
    408             if (type==null && item!=null)
    409                 type= item.getClass();
    410             Object[] na = (Object[])Array.newInstance(type, 1);
    411             na[0]=item;
    412             return na;
    413         }
    414         else
    415         {
    416             Class c = array.getClass().getComponentType();
    417             Object[] na = (Object[])Array.newInstance(c, Array.getLength(array)+1);
    418             System.arraycopy(array, 0, na, 0, array.length);
    419             na[array.length]=item;
    420             return na;
    421         }
    422     }
    423
    424     /* ------------------------------------------------------------ */
    425     public static Object[] removeFromArray(Object[] array, Object item)
    426     {
    427         if (item==null || array==null)
    428             return array;
    429         for (int i=array.length;i-->0;)
    430         {
    431             if (item.equals(array[i]))
    432             {
    433                 Class c = array==null?item.getClass():array.getClass().getComponentType();
    434                 Object[] na = (Object[])Array.newInstance(c, Array.getLength(array)-1);
    435                 if (i>0)
    436                     System.arraycopy(array, 0, na, 0, i);
    437                 if (i+1<array.length)
    438                     System.arraycopy(array, i+1, na, i, array.length-(i+1));
    439                 return na;
    440             }
    441         }
    442         return array;
    443     }
    444
    445 }
    446