001: /*
002: * $Header: /home/cvs/jakarta-commons/primitives/src/java/org/apache/commons/collections/primitives/RandomAccessLongList.java,v 1.2 2003/10/14 20:04:26 scolebourne Exp $
003: * ====================================================================
004: * The Apache Software License, Version 1.1
005: *
006: * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
007: * reserved.
008: *
009: * Redistribution and use in source and binary forms, with or without
010: * modification, are permitted provided that the following conditions
011: * are met:
012: *
013: * 1. Redistributions of source code must retain the above copyright
014: * notice, this list of conditions and the following disclaimer.
015: *
016: * 2. Redistributions in binary form must reproduce the above copyright
017: * notice, this list of conditions and the following disclaimer in
018: * the documentation and/or other materials provided with the
019: * distribution.
020: *
021: * 3. The end-user documentation included with the redistribution, if
022: * any, must include the following acknowledgement:
023: * "This product includes software developed by the
024: * Apache Software Foundation (http://www.apache.org/)."
025: * Alternately, this acknowledgement may appear in the software itself,
026: * if and wherever such third-party acknowledgements normally appear.
027: *
028: * 4. The names "The Jakarta Project", "Commons", and "Apache Software
029: * Foundation" must not be used to endorse or promote products derived
030: * from this software without prior written permission. For written
031: * permission, please contact apache@apache.org.
032: *
033: * 5. Products derived from this software may not be called "Apache"
034: * nor may "Apache" appear in their names without prior written
035: * permission of the Apache Software Foundation.
036: *
037: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
038: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
039: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
040: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
041: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
042: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
043: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
044: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
045: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
046: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
047: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
048: * SUCH DAMAGE.
049: * ====================================================================
050: *
051: * This software consists of voluntary contributions made by many
052: * individuals on behalf of the Apache Software Foundation. For more
053: * information on the Apache Software Foundation, please see
054: * <http://www.apache.org/>.
055: *
056: */
057:
058: package org.apache.commons.collections.primitives;
059:
060: import java.util.ConcurrentModificationException;
061: import java.util.NoSuchElementException;
062:
063: /**
064: * Abstract base class for {@link LongList}s backed
065: * by random access structures like arrays.
066: * <p />
067: * Read-only subclasses must override {@link #get}
068: * and {@link #size}. Mutable subclasses
069: * should also override {@link #set}. Variably-sized
070: * subclasses should also override {@link #add}
071: * and {@link #removeElementAt}. All other methods
072: * have at least some base implementation derived from
073: * these. Subclasses may choose to override these methods
074: * to provide a more efficient implementation.
075: *
076: * @since Commons Primitives 0.1
077: * @version $Revision: 1.2 $ $Date: 2003/10/14 20:04:26 $
078: *
079: * @author Rodney Waldhoff
080: */
081: public abstract class RandomAccessLongList extends
082: AbstractLongCollection implements LongList {
083:
084: // constructors
085: //-------------------------------------------------------------------------
086:
087: /** Constructs an empty list. */
088: protected RandomAccessLongList() {
089: }
090:
091: // fully abstract methods
092: //-------------------------------------------------------------------------
093:
094: public abstract long get(int index);
095:
096: public abstract int size();
097:
098: // unsupported in base
099: //-------------------------------------------------------------------------
100:
101: /**
102: * Unsupported in this implementation.
103: * @throws UnsupportedOperationException since this method is not supported
104: */
105: public long removeElementAt(int index) {
106: throw new UnsupportedOperationException();
107: }
108:
109: /**
110: * Unsupported in this implementation.
111: * @throws UnsupportedOperationException since this method is not supported
112: */
113: public long set(int index, long element) {
114: throw new UnsupportedOperationException();
115: }
116:
117: /**
118: * Unsupported in this implementation.
119: * @throws UnsupportedOperationException since this method is not supported
120: */
121: public void add(int index, long element) {
122: throw new UnsupportedOperationException();
123: }
124:
125: //-------------------------------------------------------------------------
126:
127: // javadocs here are inherited
128:
129: public boolean add(long element) {
130: add(size(), element);
131: return true;
132: }
133:
134: public boolean addAll(int index, LongCollection collection) {
135: boolean modified = false;
136: for (LongIterator iter = collection.iterator(); iter.hasNext();) {
137: add(index++, iter.next());
138: modified = true;
139: }
140: return modified;
141: }
142:
143: public int indexOf(long element) {
144: int i = 0;
145: for (LongIterator iter = iterator(); iter.hasNext();) {
146: if (iter.next() == element) {
147: return i;
148: } else {
149: i++;
150: }
151: }
152: return -1;
153: }
154:
155: public int lastIndexOf(long element) {
156: for (LongListIterator iter = listIterator(size()); iter
157: .hasPrevious();) {
158: if (iter.previous() == element) {
159: return iter.nextIndex();
160: }
161: }
162: return -1;
163: }
164:
165: public LongIterator iterator() {
166: return listIterator();
167: }
168:
169: public LongListIterator listIterator() {
170: return listIterator(0);
171: }
172:
173: public LongListIterator listIterator(int index) {
174: return new RandomAccessLongListIterator(this , index);
175: }
176:
177: public LongList subList(int fromIndex, int toIndex) {
178: return new RandomAccessLongSubList(this , fromIndex, toIndex);
179: }
180:
181: public boolean equals(Object that) {
182: if (this == that) {
183: return true;
184: } else if (that instanceof LongList) {
185: LongList thatList = (LongList) that;
186: if (size() != thatList.size()) {
187: return false;
188: }
189: for (LongIterator thatIter = thatList.iterator(), this Iter = iterator(); this Iter
190: .hasNext();) {
191: if (this Iter.next() != thatIter.next()) {
192: return false;
193: }
194: }
195: return true;
196: } else {
197: return false;
198: }
199: }
200:
201: public int hashCode() {
202: int hash = 1;
203: for (LongIterator iter = iterator(); iter.hasNext();) {
204: long val = iter.next();
205: hash = 31 * hash + ((int) (val ^ (val >>> 32)));
206: }
207: return hash;
208: }
209:
210: public String toString() {
211: StringBuffer buf = new StringBuffer();
212: buf.append("[");
213: for (LongIterator iter = iterator(); iter.hasNext();) {
214: buf.append(iter.next());
215: if (iter.hasNext()) {
216: buf.append(", ");
217: }
218: }
219: buf.append("]");
220: return buf.toString();
221: }
222:
223: // protected utilities
224: //-------------------------------------------------------------------------
225:
226: /** Get my count of structural modifications. */
227: protected int getModCount() {
228: return _modCount;
229: }
230:
231: /** Increment my count of structural modifications. */
232: protected void incrModCount() {
233: _modCount++;
234: }
235:
236: // attributes
237: //-------------------------------------------------------------------------
238:
239: private int _modCount = 0;
240:
241: // inner classes
242: //-------------------------------------------------------------------------
243:
244: private static class ComodChecker {
245: ComodChecker(RandomAccessLongList source) {
246: _source = source;
247: resyncModCount();
248: }
249:
250: protected RandomAccessLongList getList() {
251: return _source;
252: }
253:
254: protected void assertNotComodified()
255: throws ConcurrentModificationException {
256: if (_expectedModCount != getList().getModCount()) {
257: throw new ConcurrentModificationException();
258: }
259: }
260:
261: protected void resyncModCount() {
262: _expectedModCount = getList().getModCount();
263: }
264:
265: private RandomAccessLongList _source = null;
266: private int _expectedModCount = -1;
267: }
268:
269: protected static class RandomAccessLongListIterator extends
270: ComodChecker implements LongListIterator {
271: RandomAccessLongListIterator(RandomAccessLongList list,
272: int index) {
273: super (list);
274: if (index < 0 || index > getList().size()) {
275: throw new IndexOutOfBoundsException("Index " + index
276: + " not in [0," + getList().size() + ")");
277: } else {
278: _nextIndex = index;
279: resyncModCount();
280: }
281: }
282:
283: public boolean hasNext() {
284: assertNotComodified();
285: return _nextIndex < getList().size();
286: }
287:
288: public boolean hasPrevious() {
289: assertNotComodified();
290: return _nextIndex > 0;
291: }
292:
293: public int nextIndex() {
294: assertNotComodified();
295: return _nextIndex;
296: }
297:
298: public int previousIndex() {
299: assertNotComodified();
300: return _nextIndex - 1;
301: }
302:
303: public long next() {
304: assertNotComodified();
305: if (!hasNext()) {
306: throw new NoSuchElementException();
307: } else {
308: long val = getList().get(_nextIndex);
309: _lastReturnedIndex = _nextIndex;
310: _nextIndex++;
311: return val;
312: }
313: }
314:
315: public long previous() {
316: assertNotComodified();
317: if (!hasPrevious()) {
318: throw new NoSuchElementException();
319: } else {
320: long val = getList().get(_nextIndex - 1);
321: _lastReturnedIndex = _nextIndex - 1;
322: _nextIndex--;
323: return val;
324: }
325: }
326:
327: public void add(long value) {
328: assertNotComodified();
329: getList().add(_nextIndex, value);
330: _nextIndex++;
331: _lastReturnedIndex = -1;
332: resyncModCount();
333: }
334:
335: public void remove() {
336: assertNotComodified();
337: if (-1 == _lastReturnedIndex) {
338: throw new IllegalStateException();
339: } else {
340: getList().removeElementAt(_lastReturnedIndex);
341: _lastReturnedIndex = -1;
342: _nextIndex--;
343: resyncModCount();
344: }
345: }
346:
347: public void set(long value) {
348: assertNotComodified();
349: if (-1 == _lastReturnedIndex) {
350: throw new IllegalStateException();
351: } else {
352: getList().set(_lastReturnedIndex, value);
353: resyncModCount();
354: }
355: }
356:
357: private int _nextIndex = 0;
358: private int _lastReturnedIndex = -1;
359: }
360:
361: protected static class RandomAccessLongSubList extends
362: RandomAccessLongList implements LongList {
363: RandomAccessLongSubList(RandomAccessLongList list,
364: int fromIndex, int toIndex) {
365: if (fromIndex < 0 || toIndex > list.size()) {
366: throw new IndexOutOfBoundsException();
367: } else if (fromIndex > toIndex) {
368: throw new IllegalArgumentException();
369: } else {
370: _list = list;
371: _offset = fromIndex;
372: _limit = toIndex - fromIndex;
373: _comod = new ComodChecker(list);
374: _comod.resyncModCount();
375: }
376: }
377:
378: public long get(int index) {
379: checkRange(index);
380: _comod.assertNotComodified();
381: return _list.get(toUnderlyingIndex(index));
382: }
383:
384: public long removeElementAt(int index) {
385: checkRange(index);
386: _comod.assertNotComodified();
387: long val = _list.removeElementAt(toUnderlyingIndex(index));
388: _limit--;
389: _comod.resyncModCount();
390: incrModCount();
391: return val;
392: }
393:
394: public long set(int index, long element) {
395: checkRange(index);
396: _comod.assertNotComodified();
397: long val = _list.set(toUnderlyingIndex(index), element);
398: incrModCount();
399: _comod.resyncModCount();
400: return val;
401: }
402:
403: public void add(int index, long element) {
404: checkRangeIncludingEndpoint(index);
405: _comod.assertNotComodified();
406: _list.add(toUnderlyingIndex(index), element);
407: _limit++;
408: _comod.resyncModCount();
409: incrModCount();
410: }
411:
412: public int size() {
413: _comod.assertNotComodified();
414: return _limit;
415: }
416:
417: private void checkRange(int index) {
418: if (index < 0 || index >= size()) {
419: throw new IndexOutOfBoundsException("index " + index
420: + " not in [0," + size() + ")");
421: }
422: }
423:
424: private void checkRangeIncludingEndpoint(int index) {
425: if (index < 0 || index > size()) {
426: throw new IndexOutOfBoundsException("index " + index
427: + " not in [0," + size() + "]");
428: }
429: }
430:
431: private int toUnderlyingIndex(int index) {
432: return (index + _offset);
433: }
434:
435: private int _offset = 0;
436: private int _limit = 0;
437: private RandomAccessLongList _list = null;
438: private ComodChecker _comod = null;
439:
440: }
441: }
|