    1   /* ListType
    2    *
    3    * $Id: ListType.java 4648 2006-09-25 16:25:53Z paul_jack $
    4    *
    5    * Created on Jan 7, 2004
    6    *
    7    * Copyright (C) 2004 Internet Archive.
    8    *
    9    * This file is part of the Heritrix web crawler (crawler.archive.org).
    10   *
    11   * Heritrix is free software; you can redistribute it and/or modify
    12   * it under the terms of the GNU Lesser Public License as published by
    13   * the Free Software Foundation; either version 2.1 of the License, or
    14   * any later version.
    15   *
    16   * Heritrix is distributed in the hope that it will be useful,
    17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    19   * GNU Lesser Public License for more details.
    20   *
    21   * You should have received a copy of the GNU Lesser Public License
    22   * along with Heritrix; if not, write to the Free Software
    23   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    24   */
    25  package org.archive.crawler.settings;
    26
    27  import java.util.ArrayList;
    28  import java.util.Collection;
    29  import java.util.Iterator;
    30  import java.util.List;
    31  import java.util.ListIterator;
    32
    33  import org.archive.util.SubList;
    34
    35  /*** Super type for all lists.
    36   *
    37   * @author John Erik Halse
    38   */
    39  public abstract class ListType<T> extends Type implements List<Object> {
    40
    41      private final List<T> listData = new ArrayList<T>();
    42      private final String description;
    43
    44      /*** Constructs a new ListType.
    45       *
    46       * @param name the name of the list
    47       * @param description the description of the list
    48       */
    49      public ListType(String name, String description) {
    50          super(name, null);
    51          this.description = description;
    52      }
    53
    54      /*** Appends the specified element to the end of this list.
    55       *
    56       * @param element element to be appended to this list.
    57       * @throws ClassCastException is thrown if the element was of wrong type
    58       *         and could not be converted.
    59       * @return true if this collection changed as a result of the call (as
    60       * per the Collections.add contract).
    61       */
    62      public boolean add(Object element) {
    63          T checked = checkType(element);
    64          return this.listData.add(checked);
    65      }
    66
    67      /*** Inserts the specified element at the specified position in this list.
    68       *
    69       * Shifts the element currently at that position (if any) and any
    70       * subsequent elements to the right (adds one to their indices).
    71       *
    72       * @param index index at which the specified element is to be inserted.
    73       * @param element element to be inserted.
    74       * @throws ClassCastException is thrown if the element was of wrong type
    75       *         and could not be converted.
    76       */
    77      public void add(int index, Object element) {
    78          T checked = checkType(element);
    79          this.listData.add(index, checked);
    80      }
    81
    82      /*** Appends all of the elements in the specified list to the end of this
    83       * list, in the order that they are returned by the specified lists's
    84       * iterator.
    85       *
    86       * The behavior of this operation is unspecified if the specified
    87       * collection is modified while the operation is in progress.
    88       *
    89       * This method is a helper method for subclasses.
    90       *
    91       * @param l list whose elements are to be added to this list.
    92       */
    93      protected void addAll(ListType<T> l) {
    94          this.listData.addAll(l.listData);
    95      }
    96
    97      /*** Replaces the element at the specified position in this list with the
    98       *  specified element.
    99       *
    100      * @param index index at which the specified element is to be inserted.
    101      * @param element element to be inserted.
    102      * @return the element previously at the specified position.
    103      * @throws ClassCastException is thrown if the element was of wrong type
    104      *         and could not be converted.
    105      */
    106     public Object set(int index, Object element) {
    107         T checked = checkType(element);
    108         return this.listData.set(index, checked);
    109     }
    110
    111     /*** Returns an iterator over the elements in this list in proper sequence.
    112      *
    113      * @return an iterator over the elements in this list.
    114      */
    115     public Iterator<Object> iterator() {
    116         return new ListIter();
    117     }
    118
    119     /*** Get the number of elements in this list.
    120      *
    121      * @return number of elements.
    122      */
    123     public int size() {
    124         return this.listData.size();
    125     }
    126
    127     /*** Returns true if this list contains no elements.
    128      *
    129      * @return true if this list contains no elements.
    130      */
    131     public boolean isEmpty() {
    132         return this.listData.isEmpty();
    133     }
    134
    135     /*** Check if element is of right type for this list.
    136      *
    137      * If this method gets a String, it should try to convert it to
    138      * the right element type before throwing an exception.
    139      *
    140      * @param element element to check.
    141      * @return element of the right type.
    142      * @throws ClassCastException is thrown if the element was of wrong type
    143      *         and could not be converted.
    144      */
    145     public abstract T checkType(Object element) throws ClassCastException;
    146
    147     /* (non-Javadoc)
    148      * @see org.archive.crawler.settings.Type#getDefaultValue()
    149      */
    150     public Object getDefaultValue() {
    151         return this;
    152     }
    153
    154     /* (non-Javadoc)
    155      * @see org.archive.crawler.settings.Type#getDescription()
    156      */
    157     public String getDescription() {
    158         return this.description;
    159     }
    160
    161     /*** Removes all elements from this list.
    162      */
    163     public void clear() {
    164         this.listData.clear();
    165     }
    166
    167     /***
    168      * Returns the object stored at the index specified
    169      * @param index The location of the object to get within the list.
    170      * @return the object stored at the index specified
    171      */
    172     public Object get(int index){
    173         return this.listData.get(index);
    174     }
    175
    176     /*** The getLegalValues is not applicable for list so this method will
    177      * always return null.
    178      *
    179      * @return null
    180      * @see org.archive.crawler.settings.Type#getLegalValues()
    181      */
    182     public Object[] getLegalValues() {
    183         return null;
    184     }
    185
    186     /*** Returns this object.
    187      *
    188      * This method is implemented to be able to treat the ListType as an
    189      * subclass of {@link javax.management.Attribute}.
    190      *
    191      * @return this object.
    192      * @see javax.management.Attribute#getValue()
    193      */
    194     public Object getValue() {
    195         return this;
    196     }
    197
    198     public boolean addAll(Collection<? extends Object> c)
    199     {
    200     	for (Object o : c) {
    201             T checked = checkType(o);
    202             listData.add(checked);
    203         }
    204         return true;
    205     }
    206
    207     public boolean addAll(int index, Collection<? extends Object> c)
    208     {
    209     	for (Object o : c) {
    210             T checked = checkType(o);
    211             listData.add(index, checked);
    212             index++;
    213         }
    214         return true;
    215     }
    216
    217     public boolean contains(Object o)
    218     {
    219         return this.listData.contains(o);
    220     }
    221
    222     public boolean containsAll(Collection c)
    223     {
    224         return this.listData.containsAll(c);
    225     }
    226
    227     public int indexOf(Object o)
    228     {
    229         return this.listData.indexOf(o);
    230     }
    231
    232     public int lastIndexOf(Object o)
    233     {
    234         return this.listData.lastIndexOf(o);
    235     }
    236
    237     public ListIterator<Object> listIterator()
    238     {
    239         return new ListIter();
    240     }
    241
    242     public ListIterator<Object> listIterator(int index)
    243     {
    244     	return new ListIter(index);
    245     }
    246
    247     public List<Object> subList(int fromIndex, int toIndex)
    248     {
    249         return new SubList<Object>(this, fromIndex, toIndex);
    250     }
    251
    252     public Object[] toArray()
    253     {
    254         return this.listData.toArray();
    255     }
    256
    257     public <X> X[] toArray(X[] a)
    258     {
    259         return this.listData.toArray(a);
    260     }
    261
    262     public Object remove(int index)
    263     {
    264         return this.listData.remove(index);
    265     }
    266
    267     public boolean remove(Object o)
    268     {
    269         return this.listData.remove(o);
    270     }
    271
    272     public boolean removeAll(Collection c)
    273     {
    274         return this.listData.removeAll(c);
    275     }
    276
    277     public boolean retainAll(Collection c)
    278     {
    279         return this.listData.retainAll(c);
    280     }
    281
    282     /***
    283      * Returns a compile-time typesafe version of this list.  Unlike this
    284      * List, the returned list will not accept String values as elements.
    285      *
    286      * @return  a typesafe version of this list
    287      */
    288     public List<T> typesafe() {
    289         return listData;
    290     }
    291
    292     private class ListIter implements ListIterator<Object> {
    293
    294         final private ListIterator<T> delegate;
    295
    296         public ListIter() {
    297             this.delegate = listData.listIterator();
    298         }
    299
    300         public ListIter(int index) {
    301             this.delegate = listData.listIterator(index);
    302         }
    303
    304         public void add(Object o) {
    305             T checked = checkType(o);
    306             delegate.add(checked);
    307         }
    308
    309         public boolean hasNext() {
    310             return delegate.hasNext();
    311         }
    312
    313         public boolean hasPrevious() {
    314             return delegate.hasPrevious();
    315         }
    316
    317         public Object next() {
    318             return delegate.next();
    319         }
    320
    321         public int nextIndex() {
    322             return delegate.nextIndex();
    323         }
    324
    325         public Object previous() {
    326             return delegate.previous();
    327         }
    328
    329         public int previousIndex() {
    330             return delegate.previousIndex();
    331         }
    332
    333         public void remove() {
    334             delegate.remove();
    335         }
    336
    337         public void set(Object o) {
    338             T checked = checkType(o);
    339             delegate.set(checked);
    340         }
    341
    342     }
    343 }