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;
022:
023: import java.util.*;
024:
025: import com.db4o.internal.*;
026: import com.db4o.reflect.*;
027: import com.db4o.types.*;
028:
029: /**
030: * database aware linked list implementation
031: * @exclude
032: * @persistent
033: */
034: public class P2LinkedList extends P1Collection implements Db4oList {
035:
036: public P1ListElement i_first;
037: public P1ListElement i_last;
038:
039: public void add(int index, Object element) {
040: synchronized (streamLock()) {
041: checkActive();
042: if (index == 0) {
043: i_first = new P1ListElement(getTrans(), i_first,
044: element);
045: store(i_first);
046: checkLastAndUpdate(null, i_first);
047: } else {
048: P2ListElementIterator i = iterator4();
049: P1ListElement previous = i.move(index - 1);
050: if (previous == null) {
051: throw new IndexOutOfBoundsException();
052: }
053: P1ListElement newElement = new P1ListElement(
054: getTrans(), previous.i_next, element);
055: store(newElement);
056: previous.i_next = newElement;
057: previous.update();
058: checkLastAndUpdate(previous, newElement);
059: }
060: }
061: }
062:
063: public boolean add(Object o) {
064: synchronized (streamLock()) {
065: checkActive();
066: if (o == null) {
067: throw new NullPointerException();
068: }
069: add4(o);
070: update();
071: return true;
072: }
073: }
074:
075: private boolean add4(Object o) {
076: if (o != null) {
077: P1ListElement newElement = new P1ListElement(getTrans(),
078: null, o);
079: store(newElement);
080: if (i_first == null) {
081: i_first = newElement;
082: } else {
083: i_last.checkActive();
084: i_last.i_next = newElement;
085: i_last.update();
086: }
087: i_last = newElement;
088: return true;
089: }
090: return false;
091: }
092:
093: public boolean addAll(Collection c) {
094: synchronized (streamLock()) {
095: checkActive();
096: boolean modified = false;
097: Iterator i = c.iterator();
098: while (i.hasNext()) {
099: if (add4(i.next())) {
100: modified = true;
101: }
102: }
103: if (modified) {
104: update();
105: }
106: return modified;
107: }
108: }
109:
110: public boolean addAll(int index, Collection c) {
111: synchronized (streamLock()) {
112: checkActive();
113: Object first = null;
114: Iterator it = c.iterator();
115: while (it.hasNext() && (first == null)) {
116: first = it.next();
117: }
118: if (first != null) {
119: P1ListElement newElement = null;
120: P1ListElement nextElement = null;
121: if (index == 0) {
122: nextElement = i_first;
123: newElement = new P1ListElement(getTrans(), i_first,
124: first);
125: i_first = newElement;
126: } else {
127: P2ListElementIterator i = iterator4();
128: P1ListElement previous = i.move(index - 1);
129: if (previous == null) {
130: throw new IndexOutOfBoundsException();
131: }
132: nextElement = previous.i_next;
133: newElement = new P1ListElement(getTrans(),
134: previous.i_next, first);
135: previous.i_next = newElement;
136: previous.update();
137: }
138: while (it.hasNext()) {
139: Object obj = it.next();
140: if (obj != null) {
141: newElement.i_next = new P1ListElement(
142: getTrans(), nextElement, obj);
143: store(newElement);
144: newElement = newElement.i_next;
145: }
146: }
147: store(newElement);
148: if (nextElement == null) {
149: i_last = newElement;
150: }
151: update();
152: return true;
153: }
154: return false;
155: }
156: }
157:
158: public int adjustReadDepth(int a_depth) {
159: return 1;
160: }
161:
162: private void checkLastAndUpdate(P1ListElement a_oldLast,
163: P1ListElement a_added) {
164: if (i_last == a_oldLast) {
165: i_last = a_added;
166: }
167: update();
168: }
169:
170: void checkRemoved(P1ListElement a_previous, P1ListElement a_removed) {
171: boolean needsUpdate = false;
172: if (a_removed == i_first) {
173: i_first = a_removed.i_next;
174: needsUpdate = true;
175: }
176: if (a_removed == i_last) {
177: i_last = a_previous;
178: needsUpdate = true;
179: }
180: if (needsUpdate) {
181: update();
182: }
183: }
184:
185: public void clear() {
186: synchronized (streamLock()) {
187: checkActive();
188: P2ListElementIterator i = iterator4();
189: while (i.hasNext()) {
190: P1ListElement elem = i.nextElement();
191: elem.delete(i_deleteRemoved);
192: }
193: i_first = null;
194: i_last = null;
195: update();
196: }
197: }
198:
199: public boolean contains(Object o) {
200: return indexOf(o) >= 0;
201: }
202:
203: private boolean contains4(Object o) {
204: return indexOf4(o) >= 0;
205: }
206:
207: public boolean containsAll(Collection c) {
208: synchronized (streamLock()) {
209: checkActive();
210: Iterator i = c.iterator();
211: while (i.hasNext()) {
212: if (!contains4(i.next())) {
213: return false;
214: }
215: }
216: return true;
217: }
218: }
219:
220: public Object createDefault(Transaction a_trans) {
221: checkActive();
222: P2LinkedList l4 = new P2LinkedList();
223: l4.setTrans(a_trans);
224: P2ListElementIterator i = iterator4();
225: while (i.hasNext()) {
226: l4.add4(i.next());
227: }
228: return l4;
229: }
230:
231: public Object get(int index) {
232: synchronized (streamLock()) {
233: checkActive();
234: P2ListElementIterator i = iterator4();
235: P1ListElement elem = i.move(index);
236: if (elem != null) {
237: return elem.activatedObject(elementActivationDepth());
238: }
239: return null;
240: }
241: }
242:
243: public boolean hasClassIndex() {
244: return true;
245: }
246:
247: public int indexOf(Object o) {
248: synchronized (streamLock()) {
249: checkActive();
250: return indexOf4(o);
251: }
252: }
253:
254: private int indexOf4(Object o) {
255: int idx = 0;
256: // TODO: may need to check for primitive wrappers to use
257: // equals also.
258: if (getTrans() != null
259: && (!getTrans().container().handlers().isSecondClass(o))) {
260: long id = getIDOf(o);
261: if (id > 0) {
262: P2ListElementIterator i = iterator4();
263: while (i.hasNext()) {
264: P1ListElement elem = i.nextElement();
265: if (getIDOf(elem.i_object) == id) {
266: return idx;
267: }
268: idx++;
269: }
270: }
271: } else {
272: P2ListElementIterator i = iterator4();
273: while (i.hasNext()) {
274: P1ListElement elem = i.nextElement();
275: if (elem.i_object.equals(o)) {
276: return idx;
277: }
278: idx++;
279: }
280: }
281: return -1;
282: }
283:
284: public boolean isEmpty() {
285: synchronized (streamLock()) {
286: checkActive();
287: return i_first == null;
288: }
289: }
290:
291: public Iterator iterator() {
292: synchronized (streamLock()) {
293: checkActive();
294: return iterator4();
295: }
296: }
297:
298: private P2ListElementIterator iterator4() {
299: return new P2ListElementIterator(this , i_first);
300: }
301:
302: public int lastIndexOf(Object o) {
303: synchronized (streamLock()) {
304: checkActive();
305: int ret = -1;
306: int idx = 0;
307: if (getTrans() != null) {
308: long id = getIDOf(o);
309: if (id > 0) {
310: P2ListElementIterator i = iterator4();
311: while (i.hasNext()) {
312: P1ListElement elem = i.nextElement();
313: if (getIDOf(elem.i_object) == id) {
314: ret = idx;
315: }
316: idx++;
317: }
318: }
319: } else {
320: P2ListElementIterator i = iterator4();
321: while (i.hasNext()) {
322: P1ListElement elem = i.nextElement();
323: if (elem.i_object.equals(o)) {
324: ret = idx;
325: }
326: idx++;
327: }
328: }
329: return ret;
330: }
331: }
332:
333: public ListIterator listIterator() {
334: throw new UnsupportedOperationException();
335: }
336:
337: public ListIterator listIterator(int index) {
338: throw new UnsupportedOperationException();
339: }
340:
341: public Object remove(int index) {
342: synchronized (streamLock()) {
343: checkActive();
344: return remove4(index);
345: }
346: }
347:
348: public boolean remove(Object o) {
349: synchronized (streamLock()) {
350: checkActive();
351: return remove4(o);
352: }
353: }
354:
355: private Object remove4(int index) {
356: Object ret = null;
357: P1ListElement elem = null;
358: P1ListElement previous = null;
359: if (index == 0) {
360: elem = i_first;
361: } else {
362: previous = iterator4().move(index - 1);
363: if (previous != null) {
364: elem = previous.i_next;
365: }
366: }
367: if (elem != null) {
368: elem.checkActive();
369: if (previous != null) {
370: previous.i_next = elem.i_next;
371: previous.update();
372: }
373: checkRemoved(previous, elem);
374: ret = elem.activatedObject(elementActivationDepth());
375: elem.delete(i_deleteRemoved);
376: return ret;
377: }
378: throw new IndexOutOfBoundsException();
379: }
380:
381: private boolean remove4(Object o) {
382: int idx = indexOf4(o);
383: if (idx >= 0) {
384: remove4(idx);
385: return true;
386: }
387: return false;
388: }
389:
390: public boolean removeAll(Collection c) {
391: synchronized (streamLock()) {
392: checkActive();
393: boolean modified = false;
394: Iterator i = c.iterator();
395: while (i.hasNext()) {
396: if (remove(i.next())) {
397: modified = true;
398: }
399: }
400: return modified;
401: }
402: }
403:
404: public void replicateFrom(Object obj) {
405: checkActive();
406: P2ListElementIterator i = iterator4();
407: while (i.hasNext()) {
408: P1ListElement elem = i.nextElement();
409: elem.delete(false);
410: }
411: i_first = null;
412: i_last = null;
413: P2LinkedList l4 = (P2LinkedList) obj;
414: i = l4.iterator4();
415: while (i.hasNext()) {
416: add4(i.next());
417: }
418: updateInternal();
419: }
420:
421: public boolean retainAll(Collection c) {
422: throw new UnsupportedOperationException();
423: }
424:
425: public Object set(int index, Object element) {
426: synchronized (streamLock()) {
427: checkActive();
428: boolean needUpdate = false;
429: Object ret = null;
430: P1ListElement elem = null;
431: P1ListElement previous = null;
432: P1ListElement newElement = new P1ListElement(getTrans(),
433: null, element);
434: if (index == 0) {
435: elem = i_first;
436: i_first = newElement;
437: needUpdate = true;
438: } else {
439: P2ListElementIterator i = iterator4();
440: previous = i.move(index - 1);
441: if (previous != null) {
442: elem = previous.i_next;
443: } else {
444: throw new IndexOutOfBoundsException();
445: }
446: }
447:
448: if (elem != null) {
449: elem.checkActive();
450: newElement.i_next = elem.i_next;
451: if (previous != null) {
452: previous.i_next = newElement;
453: previous.update();
454: }
455: ret = elem.activatedObject(elementActivationDepth());
456: elem.delete(i_deleteRemoved);
457: } else {
458: i_last = newElement;
459: needUpdate = true;
460: }
461: if (needUpdate) {
462: update();
463: }
464: return ret;
465: }
466: }
467:
468: public synchronized int size() {
469: synchronized (streamLock()) {
470: checkActive();
471: return size4();
472: }
473: }
474:
475: private int size4() {
476: int size = 0;
477: P2ListElementIterator i = iterator4();
478: while (i.hasNext()) {
479: size++;
480: i.nextElement();
481: }
482: return size;
483: }
484:
485: public Object storedTo(Transaction a_trans) {
486: if (getTrans() == null) {
487: setTrans(a_trans);
488: } else {
489: if (a_trans != getTrans()) {
490: return replicate(getTrans(), a_trans);
491: }
492: }
493: return this ;
494: }
495:
496: public List subList(int fromIndex, int toIndex) {
497: throw new UnsupportedOperationException();
498: }
499:
500: public Object[] toArray() {
501: synchronized (streamLock()) {
502: checkActive();
503: Object[] arr = new Object[size4()];
504: int i = 0;
505: P2ListElementIterator j = iterator4();
506: while (j.hasNext()) {
507: P1ListElement elem = j.nextElement();
508: arr[i++] = elem
509: .activatedObject(elementActivationDepth());
510: }
511: return arr;
512: }
513: }
514:
515: public Object[] toArray(Object[] a) {
516: synchronized (streamLock()) {
517: checkActive();
518: int size = size();
519: if (a.length < size) {
520: Transaction trans = getTrans();
521: if (trans == null) {
522: Exceptions4.throwRuntimeException(29);
523: }
524: Reflector reflector = trans.reflector();
525: a = (Object[]) reflector.array()
526: .newInstance(
527: reflector.forObject(a)
528: .getComponentType(), size);
529: }
530: int i = 0;
531: P2ListElementIterator j = iterator4();
532: while (j.hasNext()) {
533: P1ListElement elem = j.nextElement();
534: a[i++] = elem.activatedObject(elementActivationDepth());
535: }
536: if (a.length > size) {
537: a[size] = null;
538: }
539: return a;
540: }
541: }
542:
543: }
|