001: /* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com
002:
003: This file is part of the db4o open source object database.
004:
005: db4o is free software; you can redistribute it and/or modify it under
006: the terms of version 2 of the GNU General Public License as published
007: by the Free Software Foundation and as clarified by db4objects' GPL
008: interpretation policy, available at
009: http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
010: Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
011: Suite 350, San Mateo, CA 94403, USA.
012:
013: db4o is distributed in the hope that it will be useful, but WITHOUT ANY
014: WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: for more details.
017:
018: You should have received a copy of the GNU General Public License along
019: with this program; if not, write to the Free Software Foundation, Inc.,
020: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
021: package com.db4o.collections;
022:
023: /**
024: * @exclude
025: */
026: import java.lang.reflect.*;
027: import java.util.*;
028:
029: public abstract class AbstractList4<E> implements Iterable<E>,
030: Collection<E>, List<E> {
031:
032: protected transient int modCount;
033:
034: public AbstractList4() {
035: super ();
036: }
037:
038: public boolean add(E e) {
039: add(size(), e);
040: return true;
041: }
042:
043: public void add(int index, E element) {
044: throw new UnsupportedOperationException();
045: }
046:
047: public boolean addAll(Collection<? extends E> collection) {
048: if (collection.isEmpty()) {
049: return false;
050: }
051: Iterator<? extends E> cIter = collection.iterator();
052: while (cIter.hasNext()) {
053: add(cIter.next());
054: }
055: return true;
056: }
057:
058: public boolean addAll(int index, Collection<? extends E> collection) {
059: if (collection.isEmpty()) {
060: return false;
061: }
062: Iterator<? extends E> cIter = collection.iterator();
063: int pos = index;
064: while (cIter.hasNext()) {
065: add(pos++, cIter.next());
066: }
067: return true;
068: }
069:
070: public void clear() {
071: removeRange(0, size());
072: }
073:
074: public boolean contains(Object o) {
075: return indexOf(o) != -1;
076: }
077:
078: public boolean containsAll(Collection<?> c) {
079: Iterator<?> iter = c.iterator();
080: while (iter.hasNext()) {
081: if (!contains(iter.next())) {
082: return false;
083: }
084: }
085: return true;
086: }
087:
088: public boolean equals(Object other) {
089: if (other == this ) {
090: return true;
091: }
092: if (!(other instanceof List)) {
093: return false;
094: }
095: List<?> otherList = (List<?>) other;
096: if (otherList.size() != size()) {
097: return false;
098: }
099: Iterator<E> iter = iterator();
100: Iterator<?> otherIter = otherList.iterator();
101: while (iter.hasNext()) {
102: E e1 = iter.next();
103: Object e2 = otherIter.next();
104: if (!(e1 == null ? e2 == null : e1.equals(e2))) {
105: return false;
106: }
107: }
108: return true;
109: }
110:
111: public abstract E get(int index);
112:
113: /**
114: * @see List#hashCode()
115: */
116: public int hashCode() {
117: int hashCode = 1;
118: Iterator<E> i = iterator();
119: while (i.hasNext()) {
120: E obj = i.next();
121: hashCode = 31 * hashCode
122: + (obj == null ? 0 : obj.hashCode());
123: }
124: return hashCode;
125: }
126:
127: public boolean isEmpty() {
128: return size() == 0;
129: }
130:
131: public Iterator<E> iterator() {
132: return new ArrayList4Iterator(-1);
133: }
134:
135: public int indexOf(Object o) {
136: ListIterator<E> iter = listIterator();
137: while (iter.hasNext()) {
138: if (equals(o, iter.next())) {
139: return iter.previousIndex();
140: }
141: }
142: return -1;
143: }
144:
145: public int lastIndexOf(Object o) {
146: ListIterator<E> iter = listIterator(size());
147: while (iter.hasPrevious()) {
148: if (equals(o, iter.previous())) {
149: return iter.nextIndex();
150: }
151: }
152: return -1;
153: }
154:
155: private boolean equals(Object e1, E e2) {
156: return (e1 == null ? e2 == null : e1.equals(e2));
157: }
158:
159: public ListIterator<E> listIterator() {
160: return listIterator(0);
161: }
162:
163: public ListIterator<E> listIterator(int index) {
164: checkIndex(index, 0, size());
165: return new ArrayList4IndexIterator(index);
166: }
167:
168: public E remove(int index) {
169: throw new UnsupportedOperationException();
170: }
171:
172: public boolean remove(Object o) {
173: int index = indexOf(o);
174: if (index == -1) {
175: return false;
176: }
177: remove(index);
178: return true;
179: }
180:
181: public boolean removeAll(Collection<?> c) {
182: boolean changed = false;
183: Iterator<?> it = iterator();
184: while (it.hasNext()) {
185: if (c.contains(it.next())) {
186: it.remove();
187: changed = true;
188: }
189: }
190: return changed;
191: }
192:
193: protected void removeRange(int fromIndex, int toIndex) {
194: if ((fromIndex < 0 || fromIndex >= size() || toIndex > size() || toIndex < fromIndex)) {
195: throw new IndexOutOfBoundsException();
196: }
197: if (fromIndex == toIndex) {
198: return;
199: }
200: ListIterator<E> iter = listIterator(fromIndex);
201: for (int i = fromIndex; i < toIndex; ++i) {
202: iter.next();
203: iter.remove();
204: }
205: }
206:
207: public boolean retainAll(Collection<?> c) {
208: boolean changed = false;
209: Iterator<?> it = iterator();
210: while (it.hasNext()) {
211: if (!c.contains(it.next())) {
212: it.remove();
213: changed = true;
214: }
215: }
216: return changed;
217: }
218:
219: public E set(int index, E element) {
220: throw new UnsupportedOperationException();
221: }
222:
223: public abstract int size();
224:
225: public List<E> subList(int fromIndex, int toIndex) {
226: return new SubArrayList4<E>(this , fromIndex, toIndex);
227: }
228:
229: public Object[] toArray() {
230: int size = size();
231: Object[] data = new Object[size];
232: Iterator<E> iter = iterator();
233: int i = 0;
234: while (iter.hasNext()) {
235: data[i++] = iter.next();
236: }
237: return data;
238: }
239:
240: @SuppressWarnings("unchecked")
241: public <T> T[] toArray(T[] a) {
242: int size = size();
243: if (a.length < size) {
244: a = (T[]) Array.newInstance(
245: a.getClass().getComponentType(), size);
246: }
247: Iterator<E> iter = iterator();
248: int i = 0;
249: while (iter.hasNext()) {
250: a[i++] = (T) iter.next();
251: }
252: return a;
253: }
254:
255: /**
256: * @see Collection#toString()
257: */
258: public String toString() {
259: StringBuilder buffer = new StringBuilder();
260: buffer.append('[');
261: Iterator<E> iter = iterator();
262: while (iter.hasNext()) {
263: E element = iter.next();
264: if (element != this ) {
265: buffer.append(element);
266: } else {
267: buffer.append("(this Collection)"); //$NON-NLS-1$
268: }
269: if (iter.hasNext()) {
270: buffer.append(", "); //$NON-NLS-1$
271: }
272: }
273: buffer.append(']');
274: return buffer.toString();
275: }
276:
277: void checkIndex(int index, int from, int to) {
278: if (index < from || index > to) {
279: throw new IndexOutOfBoundsException();
280: }
281: }
282:
283: class ArrayList4Iterator implements Iterator<E> {
284:
285: protected int currentIndex;
286:
287: private int _iteratorModCount;
288:
289: protected boolean canOperate;
290:
291: public ArrayList4Iterator(int pos) {
292: currentIndex = pos;
293: syncModCount();
294: }
295:
296: public boolean hasNext() {
297: return currentIndex + 1 < size();
298: }
299:
300: public E next() {
301: checkConcurrentModification();
302: try {
303: E element = get(currentIndex + 1);
304: ++currentIndex;
305: setCanOperateFlag(true);
306: return element;
307: } catch (IndexOutOfBoundsException e) {
308: checkConcurrentModification();
309: throw new NoSuchElementException();
310: }
311: }
312:
313: public void remove() {
314: checkCanOperate();
315: checkConcurrentModification();
316: AbstractList4.this .remove(currentIndex);
317: --currentIndex;
318: syncModCount();
319: setCanOperateFlag(false);
320: }
321:
322: protected void syncModCount() {
323: _iteratorModCount = modCount;
324: }
325:
326: protected void checkCanOperate() {
327: if (!canOperate) {
328: throw new IllegalStateException();
329: }
330: }
331:
332: protected void setCanOperateFlag(boolean enabled) {
333: canOperate = enabled;
334: }
335:
336: protected void checkConcurrentModification() {
337: if (_iteratorModCount != modCount) {
338: throw new ConcurrentModificationException();
339: }
340: }
341:
342: }
343:
344: class ArrayList4IndexIterator extends ArrayList4Iterator implements
345: ListIterator<E> {
346: public ArrayList4IndexIterator(int index) {
347: super (index - 1);
348: }
349:
350: public void add(E element) {
351: checkCanOperate();
352: checkConcurrentModification();
353: try {
354: AbstractList4.this .add(currentIndex, element);
355: ++currentIndex;
356: syncModCount();
357: setCanOperateFlag(false);
358: } catch (IndexOutOfBoundsException e) {
359: throw new ConcurrentModificationException();
360: }
361: }
362:
363: public boolean hasPrevious() {
364: return currentIndex != -1;
365: }
366:
367: public int nextIndex() {
368: return currentIndex + 1;
369: }
370:
371: public E previous() {
372: checkConcurrentModification();
373: try {
374: E element = get(currentIndex);
375: --currentIndex;
376: setCanOperateFlag(true);
377: return element;
378: } catch (IndexOutOfBoundsException e) {
379: checkConcurrentModification();
380: throw new NoSuchElementException();
381: }
382: }
383:
384: public int previousIndex() {
385: return currentIndex;
386: }
387:
388: public void set(E element) {
389: checkCanOperate();
390: checkConcurrentModification();
391: try {
392: AbstractList4.this .set(currentIndex, element);
393: setCanOperateFlag(false);
394: } catch (IndexOutOfBoundsException e) {
395: throw new ConcurrentModificationException();
396: }
397: }
398: }
399:
400: }
|