001: // Jericho HTML Parser - Java based library for analysing and manipulating HTML
002: // Version 2.5
003: // Copyright (C) 2007 Martin Jericho
004: // http://jerichohtml.sourceforge.net/
005: //
006: // This library is free software; you can redistribute it and/or
007: // modify it under the terms of either one of the following licences:
008: //
009: // 1. The Eclipse Public License (EPL) version 1.0,
010: // included in this distribution in the file licence-epl-1.0.html
011: // or available at http://www.eclipse.org/legal/epl-v10.html
012: //
013: // 2. The GNU Lesser General Public License (LGPL) version 2.1 or later,
014: // included in this distribution in the file licence-lgpl-2.1.txt
015: // or available at http://www.gnu.org/licenses/lgpl.txt
016: //
017: // This library is distributed on an "AS IS" basis,
018: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
019: // See the individual licence texts for more details.
020:
021: package au.id.jericho.lib.html.nodoc;
022:
023: import au.id.jericho.lib.html.*;
024: import java.util.*;
025:
026: /**
027: * A base class used internally to simulate multiple inheritance of {@link Segment} and <code>java.util.AbstractSequentialList</code>.
028: * <p>
029: * It allows a {@link Segment} based class to implement <code>java.util.List</code> without having to implement
030: * all of the <code>List</code> methods explicitly, which would clutter the API documentation with mostly irrelevant methods.
031: * By extending this class, most of the list implementation methods are simply listed in the inherited methods list.
032: *
033: * @see Attributes
034: */
035: public abstract class SequentialListSegment extends Segment implements
036: List {
037: public SequentialListSegment(final Source source, final int begin,
038: final int end) {
039: super (source, begin, end);
040: }
041:
042: /**
043: * Returns the number of items in the list.
044: * @return the number of items in the list.
045: */
046: public abstract int getCount();
047:
048: /**
049: * Returns a list iterator of the items in this list (in proper sequence), starting at the specified position in the list.
050: * <p>
051: * The specified index indicates the first item that would be returned by an initial call to the <code>next()</code> method.
052: * An initial call to the <code>previous()</code> method would return the item with the specified index minus one.
053: *
054: * @param index index of the first item to be returned from the list iterator (by a call to the <code>next()</code> method).
055: * @return a list iterator of the items in this list (in proper sequence), starting at the specified position in the list.
056: * @throws IndexOutOfBoundsException if the specified index is out of range (<code>index < 0 || index > size()</code>).
057: */
058: public abstract ListIterator listIterator(int index);
059:
060: /**
061: * Returns the item at the specified position in this list.
062: * <p>
063: * This implementation first gets a list iterator pointing to the indexed item (with <code>listIterator(index)</code>).
064: * Then, it gets the element using <code>ListIterator.next</code> and returns it.
065: *
066: * @param index the index of the item to return.
067: * @return the item at the specified position in this list.
068: * @throws IndexOutOfBoundsException if the specified index is out of range (<code>index < 0 || index >= size()</code>).
069: */
070: public Object get(final int index) {
071: final ListIterator li = listIterator(index);
072: try {
073: return (li.next());
074: } catch (NoSuchElementException ex) {
075: throw (new IndexOutOfBoundsException("index=" + index));
076: }
077: }
078:
079: /**
080: * Returns the number of items in the list.
081: * <p>
082: * This is equivalent to {@link #getCount()},
083: * and is necessary to for the implementation of the <code>java.util.Collection</code> interface.
084: *
085: * @return the number of items in the list.
086: */
087: public int size() {
088: return getCount();
089: }
090:
091: /**
092: * Indicates whether this list is empty.
093: * @return <code>true</code> if there are no items in the list, otherwise <code>false</code>.
094: */
095: public boolean isEmpty() {
096: return getCount() == 0;
097: }
098:
099: /**
100: * Indicates whether this list contains the specified object.
101: *
102: * @param o object to be checked for containment in this list.
103: * @return <code>true</code> if this list contains the specified object, otherwise <code>false</code>.
104: */
105: public boolean contains(final Object o) {
106: return indexOf(o) >= 0;
107: }
108:
109: /**
110: * Returns an array containing all of the items in this list.
111: * @return an array containing all of the items in this list.
112: */
113: public Object[] toArray() {
114: final Object[] array = new Object[getCount()];
115: int x = 0;
116: for (final ListIterator li = listIterator(0); li.hasNext();)
117: array[x++] = li.next();
118: return array;
119: }
120:
121: /**
122: * Returns an array containing all of the items in this list in the correct order;
123: * the runtime type of the returned array is that of the specified array.
124: * If the list fits in the specified array, it is returned therein.
125: * Otherwise, a new array is allocated with the runtime type of the specified array and the size of this list.
126: * <p>
127: * If the list fits in the specified array with room to spare (i.e., the array has more elements than the list),
128: * the item in the array immediately following the end of the collection is set to <code>null</code>.
129: * This is useful in determining the length of the list <i>only</i>
130: * if the caller knows that the list does not contain any <code>null</code> items.
131: *
132: * @param a the array into which the items of the list are to be stored, if it is big enough; otherwise, a new array of the same runtime type is allocated for this purpose.
133: * @return an array containing the items of the list.
134: * @throws NullPointerException if the specified array is <code>null</code>.
135: * @throws ArrayStoreException if the runtime type of the specified array is not a supertype of the runtime type of every item in this list.
136: */
137: public Object[] toArray(Object a[]) {
138: final int count = getCount();
139: if (a.length < count)
140: a = (Object[]) java.lang.reflect.Array.newInstance(a
141: .getClass().getComponentType(), count);
142: int x = 0;
143: for (final ListIterator li = listIterator(0); li.hasNext();)
144: a[x++] = li.next();
145: if (a.length > count)
146: a[count] = null;
147: return a;
148: }
149:
150: /**
151: * This list is unmodifiable, so this method always throws an <code>UnsupportedOperationException</code>.
152: * @throws UnsupportedOperationException
153: */
154: public boolean remove(Object o) {
155: throw new UnsupportedOperationException();
156: }
157:
158: /**
159: * Indicates whether this list contains all of the items in the specified collection.
160: * @param collection the collection to be checked for containment in this list.
161: * @return <code>true</code> if this list contains all of the items in the specified collection, otherwise <code>false</code>.
162: * @throws NullPointerException if the specified collection is null.
163: * @see #contains(Object)
164: */
165: public boolean containsAll(final Collection collection) {
166: for (final Iterator i = collection.iterator(); i.hasNext();)
167: if (!contains(i.next()))
168: return false;
169: return true;
170: }
171:
172: /**
173: * This list is unmodifiable, so this method always throws an <code>UnsupportedOperationException</code>.
174: * @throws UnsupportedOperationException
175: */
176: public boolean addAll(Collection collection) {
177: throw new UnsupportedOperationException();
178: }
179:
180: /**
181: * This list is unmodifiable, so this method always throws an <code>UnsupportedOperationException</code>.
182: * @throws UnsupportedOperationException
183: */
184: public boolean removeAll(Collection collection) {
185: throw new UnsupportedOperationException();
186: }
187:
188: /**
189: * This list is unmodifiable, so this method always throws an <code>UnsupportedOperationException</code>.
190: * @throws UnsupportedOperationException
191: */
192: public boolean retainAll(Collection collection) {
193: throw new UnsupportedOperationException();
194: }
195:
196: /**
197: * This list is unmodifiable, so this method always throws an <code>UnsupportedOperationException</code>.
198: * @throws UnsupportedOperationException
199: */
200: public boolean add(Object o) {
201: throw new UnsupportedOperationException();
202: }
203:
204: /**
205: * This list is unmodifiable, so this method always throws an <code>UnsupportedOperationException</code>.
206: * @throws UnsupportedOperationException
207: */
208: public Object set(int index, Object element) {
209: throw new UnsupportedOperationException();
210: }
211:
212: /**
213: * This list is unmodifiable, so this method always throws an <code>UnsupportedOperationException</code>.
214: * @throws UnsupportedOperationException
215: */
216: public void add(int index, Object element) {
217: throw new UnsupportedOperationException();
218: }
219:
220: /**
221: * This list is unmodifiable, so this method always throws an <code>UnsupportedOperationException</code>.
222: * @throws UnsupportedOperationException
223: */
224: public Object remove(int index) {
225: throw new UnsupportedOperationException();
226: }
227:
228: /**
229: * Returns the index in this list of the first occurence of the specified object, or -1 if the list does not contain this object.
230: *
231: * @param o object to search for.
232: * @return the index in this list of the first occurence of the specified object, or -1 if the list does not contain this object.
233: */
234: public int indexOf(final Object o) {
235: final ListIterator li = listIterator(0);
236: if (o == null) {
237: while (li.hasNext())
238: if (li.next() == null)
239: return li.previousIndex();
240: } else {
241: while (li.hasNext())
242: if (o.equals(li.next()))
243: return li.previousIndex();
244: }
245: return -1;
246: }
247:
248: /**
249: * Returns the index in this list of the last occurence of the specified object, or -1 if the list does not contain this object.
250: *
251: * @param o object to search for.
252: * @return the index in this list of the last occurence of the specified object, or -1 if the list does not contain this object.
253: */
254: public int lastIndexOf(final Object o) {
255: final ListIterator li = listIterator(getCount());
256: if (o == null) {
257: while (li.hasPrevious())
258: if (li.previous() == null)
259: return li.nextIndex();
260: } else {
261: while (li.hasPrevious())
262: if (o.equals(li.previous()))
263: return li.nextIndex();
264: }
265: return -1;
266: }
267:
268: /**
269: * This list is unmodifiable, so this method always throws an <code>UnsupportedOperationException</code>.
270: * @throws UnsupportedOperationException
271: */
272: public void clear() {
273: throw new UnsupportedOperationException();
274: }
275:
276: /**
277: * This list is unmodifiable, so this method always throws an <code>UnsupportedOperationException</code>.
278: * @throws UnsupportedOperationException
279: */
280: public boolean addAll(int index, Collection collection) {
281: throw new UnsupportedOperationException();
282: }
283:
284: /**
285: * Returns an iterator over the items in the list in proper sequence.
286: * @return an iterator over the items in the list in proper sequence.
287: */
288: public Iterator iterator() {
289: return listIterator();
290: }
291:
292: /**
293: * Returns a list iterator of the items in this list (in proper sequence), starting with the first item in the list.
294: * @return a list iterator of the items in this list (in proper sequence), starting with the first item in the list.
295: * @see #listIterator(int)
296: */
297: public ListIterator listIterator() {
298: return listIterator(0);
299: }
300:
301: /**
302: * Returns a view of the portion of this list between <code>fromIndex</code>, inclusive, and <code>toIndex</code>, exclusive.
303: * (If <code>fromIndex</code> and <code>toIndex</code> are equal, the returned list is empty.)
304: * The returned list is backed by this list, so changes in the returned list are reflected in this list, and vice-versa.
305: * The returned list supports all of the optional list operations supported by this list.
306: *
307: * @param fromIndex low endpoint (inclusive) of the subList.
308: * @param toIndex high endpoint (exclusive) of the subList.
309: * @return a view of the specified range within this list.
310: * @throws IndexOutOfBoundsException endpoint index value out of range <code>(fromIndex < 0 || toIndex > size)</code>
311: * @throws IllegalArgumentException endpoint indices out of order <code>(fromIndex > toIndex)</code>
312: * @see java.util.List#subList(int fromIndex, int toIndex)
313: */
314: public List subList(final int fromIndex, final int toIndex) {
315: return (new SubList(this , fromIndex, toIndex));
316: }
317:
318: private static class SubList extends AbstractList {
319: private final List list;
320: private final int offset;
321: private final int size;
322:
323: SubList(final List list, final int fromIndex, final int toIndex) {
324: if (fromIndex < 0)
325: throw new IndexOutOfBoundsException("fromIndex="
326: + fromIndex);
327: if (toIndex > list.size())
328: throw new IndexOutOfBoundsException("toIndex="
329: + toIndex);
330: if (fromIndex > toIndex)
331: throw new IllegalArgumentException("fromIndex("
332: + fromIndex + ") > toIndex(" + toIndex + ")");
333: this .list = list;
334: offset = fromIndex;
335: size = toIndex - fromIndex;
336: }
337:
338: public Object get(final int index) {
339: return list.get(getSuperListIndex(index));
340: }
341:
342: public int size() {
343: return size;
344: }
345:
346: public Iterator iterator() {
347: return listIterator();
348: }
349:
350: public ListIterator listIterator(final int index) {
351: return new ListIterator() {
352: private final ListIterator i = list
353: .listIterator(getSuperListIndex(index));
354:
355: public boolean hasNext() {
356: return nextIndex() < size;
357: }
358:
359: public Object next() {
360: if (!hasNext())
361: throw new NoSuchElementException();
362: return i.next();
363: }
364:
365: public boolean hasPrevious() {
366: return previousIndex() >= 0;
367: }
368:
369: public Object previous() {
370: if (!hasPrevious())
371: throw new NoSuchElementException();
372: return i.previous();
373: }
374:
375: public int nextIndex() {
376: return i.nextIndex() - offset;
377: }
378:
379: public int previousIndex() {
380: return i.previousIndex() - offset;
381: }
382:
383: public void remove() {
384: throw new UnsupportedOperationException();
385: }
386:
387: public void set(Object o) {
388: throw new UnsupportedOperationException();
389: }
390:
391: public void add(Object o) {
392: throw new UnsupportedOperationException();
393: }
394: };
395: }
396:
397: public List subList(final int fromIndex, final int toIndex) {
398: return new SubList(this , fromIndex, toIndex);
399: }
400:
401: private int getSuperListIndex(final int index) {
402: if (index < 0 || index >= size)
403: throw new IndexOutOfBoundsException("index=" + index
404: + ", size=" + size);
405: return index + offset;
406: }
407: }
408: }
|