View Javadoc

1   /* SubList
2    *
3    * $Id: SubList.java 4648 2006-09-25 16:25:53Z paul_jack $
4    * Created on September 23, 2006
5    *
6    * Copyright (C) 2006 Internet Archive.
7    *
8    * This file is part of the Heritrix web crawler (crawler.archive.org).
9    *
10   * Heritrix is free software; you can redistribute it and/or modify
11   * it under the terms of the GNU Lesser Public License as published by
12   * the Free Software Foundation; either version 2.1 of the License, or
13   * any later version.
14   *
15   * Heritrix is distributed in the hope that it will be useful,
16   * but WITHOUT ANY WARRANTY; without even the implied warranty of
17   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   * GNU Lesser Public License for more details.
19   *
20   * You should have received a copy of the GNU Lesser Public License
21   * along with Heritrix; if not, write to the Free Software
22   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23   */
24  package org.archive.util;
25  
26  
27  import java.io.Serializable;
28  import java.util.AbstractList;
29  import java.util.List;
30  
31  
32  /***
33   * Universal sublist implementation.  Instances of this class are 
34   * appropriate to return from {@link List#subList(int, int)} 
35   * implementations.
36   * 
37   * <p>This implementation is efficient if the super list is random-access.
38   * LinkedList-style super lists should subclass this and provide a custom
39   * iterator.
40   * 
41   * @author pjack
42   * @param <E>  the element type of the list
43   */
44  public class SubList<E> extends AbstractList<E> implements Serializable {
45  
46      private static final long serialVersionUID = 1L;
47  
48      /***
49       * The list that created this SubList.
50       */
51      final private List<E> delegate;
52  
53      /***
54       * The starting index of the SubList, inclusive.
55       */
56      private int start;
57  
58      /***
59       * The ending index of the SubList, exclusive.
60       */
61      private int end;
62  
63      
64      /***
65       * Constructor.
66       * 
67       * @param delegate  the list that create this SubList
68       * @param start   the starting index of the sublist, inclusive
69       * @param end  the ending index of the sublist, exclusive
70       * @throws IndexOutOfBoundsException   if start or end are outside the
71       *   bounds of the list
72       * @throws IllegalArgumentException  if end is less than start
73       */
74      public SubList(List<E> delegate, int start, int end) {
75          if ((start < 0) || (start > delegate.size())) {
76              throw new IndexOutOfBoundsException();
77          }
78          if ((end < 0) || (end > delegate.size())) {
79              throw new IndexOutOfBoundsException();
80          }
81          if (end < start) {
82              throw new IllegalArgumentException();
83          }
84          this.delegate = delegate;
85          this.start = start;
86          this.end = end;
87      }
88      
89      /***
90       * Ensures that the given index is strictly within the bounds of this
91       * SubList.  
92       * 
93       * @param index  the index to check
94       * @throws  IndexOutOfBoundsException  if the index is out of bounds
95       */
96      private void ensureInside(int index) {
97          if ((index < 0) || (index >= end - start)) {
98              throw new IndexOutOfBoundsException();
99          }
100     }
101 
102     /***
103      * Ensures that the given index is either within bounds or on the border
104      * of this SubList.  In other words, this method allows the given index
105      * to be equal to {@link #size()}.
106      * 
107      * @param index  the index to check
108      * @throws  IndexOutOfBoundsException  if the index is out of bounds
109      */
110     private void ensureBorder(int index) {
111         if ((index < 0) || (index > end - start)) {
112             throw new IndexOutOfBoundsException();
113         }
114     }
115 
116 
117     @Override
118     public E get(int index) {
119         ensureInside(index);
120         return delegate.get(start + index);
121     }
122 
123 
124     @Override
125     public int size() {
126         return end - start;
127     }
128 
129 
130     @Override
131     public E set(int index, E value) {
132         ensureInside(index);
133         return delegate.set(start + index, value);
134     }
135 
136 
137     @Override
138     public void add(int index, E value) {
139         ensureBorder(index);
140         delegate.add(start + index, value);
141         end++;
142     }
143 
144     
145     @Override
146     public E remove(int index) {
147         ensureInside(index);
148         return delegate.remove(start + index);
149     }
150 }