001: /*
002: * $Header: /home/cvs/jakarta-commons/primitives/src/java/org/apache/commons/collections/primitives/RandomAccessDoubleList.java,v 1.3 2003/10/16 20:49:36 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 DoubleList}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 1.0
077: * @version $Revision: 1.3 $ $Date: 2003/10/16 20:49:36 $
078: *
079: * @author Rodney Waldhoff
080: */
081: public abstract class RandomAccessDoubleList extends
082: AbstractDoubleCollection implements DoubleList {
083:
084: // constructors
085: //-------------------------------------------------------------------------
086:
087: /** Constructs an empty list. */
088: protected RandomAccessDoubleList() {
089: }
090:
091: // fully abstract methods
092: //-------------------------------------------------------------------------
093:
094: public abstract double 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 double 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 double set(int index, double 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, double element) {
122: throw new UnsupportedOperationException();
123: }
124:
125: //-------------------------------------------------------------------------
126:
127: // javadocs here are inherited
128:
129: public boolean add(double element) {
130: add(size(), element);
131: return true;
132: }
133:
134: public boolean addAll(int index, DoubleCollection collection) {
135: boolean modified = false;
136: for (DoubleIterator iter = collection.iterator(); iter
137: .hasNext();) {
138: add(index++, iter.next());
139: modified = true;
140: }
141: return modified;
142: }
143:
144: public int indexOf(double element) {
145: int i = 0;
146: for (DoubleIterator iter = iterator(); iter.hasNext();) {
147: if (iter.next() == element) {
148: return i;
149: } else {
150: i++;
151: }
152: }
153: return -1;
154: }
155:
156: public int lastIndexOf(double element) {
157: for (DoubleListIterator iter = listIterator(size()); iter
158: .hasPrevious();) {
159: if (iter.previous() == element) {
160: return iter.nextIndex();
161: }
162: }
163: return -1;
164: }
165:
166: public DoubleIterator iterator() {
167: return listIterator();
168: }
169:
170: public DoubleListIterator listIterator() {
171: return listIterator(0);
172: }
173:
174: public DoubleListIterator listIterator(int index) {
175: return new RandomAccessDoubleListIterator(this , index);
176: }
177:
178: public DoubleList subList(int fromIndex, int toIndex) {
179: return new RandomAccessDoubleSubList(this , fromIndex, toIndex);
180: }
181:
182: public boolean equals(Object that) {
183: if (this == that) {
184: return true;
185: } else if (that instanceof DoubleList) {
186: DoubleList thatList = (DoubleList) that;
187: if (size() != thatList.size()) {
188: return false;
189: }
190: for (DoubleIterator thatIter = thatList.iterator(), this Iter = iterator(); this Iter
191: .hasNext();) {
192: if (this Iter.next() != thatIter.next()) {
193: return false;
194: }
195: }
196: return true;
197: } else {
198: return false;
199: }
200: }
201:
202: public int hashCode() {
203: int hash = 1;
204: for (DoubleIterator iter = iterator(); iter.hasNext();) {
205: long bits = Double.doubleToLongBits(iter.next());
206: hash = 31 * hash + ((int) (bits ^ (bits >>> 32)));
207: }
208: return hash;
209: }
210:
211: public String toString() {
212: StringBuffer buf = new StringBuffer();
213: buf.append("[");
214: for (DoubleIterator iter = iterator(); iter.hasNext();) {
215: buf.append(iter.next());
216: if (iter.hasNext()) {
217: buf.append(", ");
218: }
219: }
220: buf.append("]");
221: return buf.toString();
222: }
223:
224: // protected utilities
225: //-------------------------------------------------------------------------
226:
227: /** Get my count of structural modifications. */
228: protected int getModCount() {
229: return _modCount;
230: }
231:
232: /** Increment my count of structural modifications. */
233: protected void incrModCount() {
234: _modCount++;
235: }
236:
237: // attributes
238: //-------------------------------------------------------------------------
239:
240: private int _modCount = 0;
241:
242: // inner classes
243: //-------------------------------------------------------------------------
244:
245: private static class ComodChecker {
246: ComodChecker(RandomAccessDoubleList source) {
247: _source = source;
248: resyncModCount();
249: }
250:
251: protected RandomAccessDoubleList getList() {
252: return _source;
253: }
254:
255: protected void assertNotComodified()
256: throws ConcurrentModificationException {
257: if (_expectedModCount != getList().getModCount()) {
258: throw new ConcurrentModificationException();
259: }
260: }
261:
262: protected void resyncModCount() {
263: _expectedModCount = getList().getModCount();
264: }
265:
266: private RandomAccessDoubleList _source = null;
267: private int _expectedModCount = -1;
268: }
269:
270: protected static class RandomAccessDoubleListIterator extends
271: ComodChecker implements DoubleListIterator {
272: RandomAccessDoubleListIterator(RandomAccessDoubleList list,
273: int index) {
274: super (list);
275: if (index < 0 || index > getList().size()) {
276: throw new IndexOutOfBoundsException("Index " + index
277: + " not in [0," + getList().size() + ")");
278: } else {
279: _nextIndex = index;
280: resyncModCount();
281: }
282: }
283:
284: public boolean hasNext() {
285: assertNotComodified();
286: return _nextIndex < getList().size();
287: }
288:
289: public boolean hasPrevious() {
290: assertNotComodified();
291: return _nextIndex > 0;
292: }
293:
294: public int nextIndex() {
295: assertNotComodified();
296: return _nextIndex;
297: }
298:
299: public int previousIndex() {
300: assertNotComodified();
301: return _nextIndex - 1;
302: }
303:
304: public double next() {
305: assertNotComodified();
306: if (!hasNext()) {
307: throw new NoSuchElementException();
308: } else {
309: double val = getList().get(_nextIndex);
310: _lastReturnedIndex = _nextIndex;
311: _nextIndex++;
312: return val;
313: }
314: }
315:
316: public double previous() {
317: assertNotComodified();
318: if (!hasPrevious()) {
319: throw new NoSuchElementException();
320: } else {
321: double val = getList().get(_nextIndex - 1);
322: _lastReturnedIndex = _nextIndex - 1;
323: _nextIndex--;
324: return val;
325: }
326: }
327:
328: public void add(double value) {
329: assertNotComodified();
330: getList().add(_nextIndex, value);
331: _nextIndex++;
332: _lastReturnedIndex = -1;
333: resyncModCount();
334: }
335:
336: public void remove() {
337: assertNotComodified();
338: if (-1 == _lastReturnedIndex) {
339: throw new IllegalStateException();
340: } else {
341: getList().removeElementAt(_lastReturnedIndex);
342: _lastReturnedIndex = -1;
343: _nextIndex--;
344: resyncModCount();
345: }
346: }
347:
348: public void set(double value) {
349: assertNotComodified();
350: if (-1 == _lastReturnedIndex) {
351: throw new IllegalStateException();
352: } else {
353: getList().set(_lastReturnedIndex, value);
354: resyncModCount();
355: }
356: }
357:
358: private int _nextIndex = 0;
359: private int _lastReturnedIndex = -1;
360: }
361:
362: protected static class RandomAccessDoubleSubList extends
363: RandomAccessDoubleList implements DoubleList {
364: RandomAccessDoubleSubList(RandomAccessDoubleList list,
365: int fromIndex, int toIndex) {
366: if (fromIndex < 0 || toIndex > list.size()) {
367: throw new IndexOutOfBoundsException();
368: } else if (fromIndex > toIndex) {
369: throw new IllegalArgumentException();
370: } else {
371: _list = list;
372: _offset = fromIndex;
373: _limit = toIndex - fromIndex;
374: _comod = new ComodChecker(list);
375: _comod.resyncModCount();
376: }
377: }
378:
379: public double get(int index) {
380: checkRange(index);
381: _comod.assertNotComodified();
382: return _list.get(toUnderlyingIndex(index));
383: }
384:
385: public double removeElementAt(int index) {
386: checkRange(index);
387: _comod.assertNotComodified();
388: double val = _list
389: .removeElementAt(toUnderlyingIndex(index));
390: _limit--;
391: _comod.resyncModCount();
392: incrModCount();
393: return val;
394: }
395:
396: public double set(int index, double element) {
397: checkRange(index);
398: _comod.assertNotComodified();
399: double val = _list.set(toUnderlyingIndex(index), element);
400: incrModCount();
401: _comod.resyncModCount();
402: return val;
403: }
404:
405: public void add(int index, double element) {
406: checkRangeIncludingEndpoint(index);
407: _comod.assertNotComodified();
408: _list.add(toUnderlyingIndex(index), element);
409: _limit++;
410: _comod.resyncModCount();
411: incrModCount();
412: }
413:
414: public int size() {
415: _comod.assertNotComodified();
416: return _limit;
417: }
418:
419: private void checkRange(int index) {
420: if (index < 0 || index >= size()) {
421: throw new IndexOutOfBoundsException("index " + index
422: + " not in [0," + size() + ")");
423: }
424: }
425:
426: private void checkRangeIncludingEndpoint(int index) {
427: if (index < 0 || index > size()) {
428: throw new IndexOutOfBoundsException("index " + index
429: + " not in [0," + size() + "]");
430: }
431: }
432:
433: private int toUnderlyingIndex(int index) {
434: return (index + _offset);
435: }
436:
437: private int _offset = 0;
438: private int _limit = 0;
439: private RandomAccessDoubleList _list = null;
440: private ComodChecker _comod = null;
441:
442: }
443: }
|