001: /* SubList
002: *
003: * $Id: SubList.java 4648 2006-09-25 16:25:53Z paul_jack $
004: * Created on September 23, 2006
005: *
006: * Copyright (C) 2006 Internet Archive.
007: *
008: * This file is part of the Heritrix web crawler (crawler.archive.org).
009: *
010: * Heritrix is free software; you can redistribute it and/or modify
011: * it under the terms of the GNU Lesser Public License as published by
012: * the Free Software Foundation; either version 2.1 of the License, or
013: * any later version.
014: *
015: * Heritrix is distributed in the hope that it will be useful,
016: * but WITHOUT ANY WARRANTY; without even the implied warranty of
017: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
018: * GNU Lesser Public License for more details.
019: *
020: * You should have received a copy of the GNU Lesser Public License
021: * along with Heritrix; if not, write to the Free Software
022: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
023: */
024: package org.archive.util;
025:
026: import java.io.Serializable;
027: import java.util.AbstractList;
028: import java.util.List;
029:
030: /**
031: * Universal sublist implementation. Instances of this class are
032: * appropriate to return from {@link List#subList(int, int)}
033: * implementations.
034: *
035: * <p>This implementation is efficient if the super list is random-access.
036: * LinkedList-style super lists should subclass this and provide a custom
037: * iterator.
038: *
039: * @author pjack
040: * @param <E> the element type of the list
041: */
042: public class SubList<E> extends AbstractList<E> implements Serializable {
043:
044: private static final long serialVersionUID = 1L;
045:
046: /**
047: * The list that created this SubList.
048: */
049: final private List<E> delegate;
050:
051: /**
052: * The starting index of the SubList, inclusive.
053: */
054: private int start;
055:
056: /**
057: * The ending index of the SubList, exclusive.
058: */
059: private int end;
060:
061: /**
062: * Constructor.
063: *
064: * @param delegate the list that create this SubList
065: * @param start the starting index of the sublist, inclusive
066: * @param end the ending index of the sublist, exclusive
067: * @throws IndexOutOfBoundsException if start or end are outside the
068: * bounds of the list
069: * @throws IllegalArgumentException if end is less than start
070: */
071: public SubList(List<E> delegate, int start, int end) {
072: if ((start < 0) || (start > delegate.size())) {
073: throw new IndexOutOfBoundsException();
074: }
075: if ((end < 0) || (end > delegate.size())) {
076: throw new IndexOutOfBoundsException();
077: }
078: if (end < start) {
079: throw new IllegalArgumentException();
080: }
081: this .delegate = delegate;
082: this .start = start;
083: this .end = end;
084: }
085:
086: /**
087: * Ensures that the given index is strictly within the bounds of this
088: * SubList.
089: *
090: * @param index the index to check
091: * @throws IndexOutOfBoundsException if the index is out of bounds
092: */
093: private void ensureInside(int index) {
094: if ((index < 0) || (index >= end - start)) {
095: throw new IndexOutOfBoundsException();
096: }
097: }
098:
099: /**
100: * Ensures that the given index is either within bounds or on the border
101: * of this SubList. In other words, this method allows the given index
102: * to be equal to {@link #size()}.
103: *
104: * @param index the index to check
105: * @throws IndexOutOfBoundsException if the index is out of bounds
106: */
107: private void ensureBorder(int index) {
108: if ((index < 0) || (index > end - start)) {
109: throw new IndexOutOfBoundsException();
110: }
111: }
112:
113: @Override
114: public E get(int index) {
115: ensureInside(index);
116: return delegate.get(start + index);
117: }
118:
119: @Override
120: public int size() {
121: return end - start;
122: }
123:
124: @Override
125: public E set(int index, E value) {
126: ensureInside(index);
127: return delegate.set(start + index, value);
128: }
129:
130: @Override
131: public void add(int index, E value) {
132: ensureBorder(index);
133: delegate.add(start + index, value);
134: end++;
135: }
136:
137: @Override
138: public E remove(int index) {
139: ensureInside(index);
140: return delegate.remove(start + index);
141: }
142: }
|