KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > versant > core > jdo > sco > SCOList


1
2 /*
3  * Copyright (c) 1998 - 2005 Versant Corporation
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  * Versant Corporation - initial API and implementation
11  */

12 package com.versant.core.jdo.sco;
13
14 import com.versant.core.jdo.VersantPersistenceManagerImp;
15 import com.versant.core.jdo.VersantStateManager;
16
17 import javax.jdo.spi.PersistenceCapable;
18 import java.io.Serializable JavaDoc;
19 import java.util.AbstractList JavaDoc;
20 import java.util.Collection JavaDoc;
21 import java.util.Iterator JavaDoc;
22
23 import com.versant.core.common.*;
24 import com.versant.core.metadata.FieldMetaData;
25
26 /**
27  * SCO for List. This is faster than SCOArrayList.
28  *
29  * @keep-all
30  */

31 public final class SCOList extends AbstractList JavaDoc
32         implements VersantManagedSCOCollection, Serializable JavaDoc,
33         VersantAdvancedSCO {
34
35     // Same as ArrayList
36
private static final long serialVersionUID = 8683452581122892189L;
37
38     private transient Object JavaDoc[] data;
39     private int size;
40
41     private transient PersistenceCapable owner;
42     private final transient int managed;
43     private final transient int inverseFieldNo;
44     private final transient VersantFieldMetaData fmd;
45     private transient VersantStateManager stateManager;
46     private transient Object JavaDoc[] originalData;
47     private transient boolean beenReset;
48
49     public SCOList(PersistenceCapable owner, VersantStateManager stateManager,
50             VersantFieldMetaData fmd, Object JavaDoc[] originalData) {
51         this.owner = owner;
52         if (fmd.isManaged()) {
53             if (fmd.isMaster()) {
54                 managed = MANAGED_ONE_TO_MANY;
55             } else if (fmd.isManyToMany()) {
56                 managed = MANAGED_MANY_TO_MANY;
57             } else {
58                 managed = MANAGED_NONE;
59             }
60         } else {
61             managed = MANAGED_NONE;
62         }
63         this.inverseFieldNo = fmd.getInverseFieldNo();
64         this.stateManager = stateManager;
65         this.fmd = fmd;
66         this.originalData = originalData;
67         int n = originalData == null ? 0 : originalData.length;
68         if (n == 0) {
69             data = new Object JavaDoc[10];
70         } else {
71             data = new Object JavaDoc[n];
72             if (owner.jdoIsNew()) {
73                 size = n;
74                 switch (managed) {
75                     case MANAGED_ONE_TO_MANY:
76                         for (int i = 0; i < n; i++) {
77                             Object JavaDoc o = originalData[i];
78                             if (Debug.DEBUG) {
79                                 checkNull(o);
80                             }
81                             SCOInverseUtil.addMasterOnDetail(o, owner,
82                                     inverseFieldNo);
83                             data[i] = o;
84                         }
85                         break;
86                     case MANAGED_MANY_TO_MANY:
87                         for (int i = 0; i < n; i++) {
88                             Object JavaDoc o = originalData[i];
89                             if (Debug.DEBUG) {
90                                 checkNull(o);
91                             }
92                             SCOInverseUtil.addToOtherSideOfManyToMany(o,
93                                     inverseFieldNo, owner);
94                             data[i] = o;
95                         }
96                         break;
97                     default:
98                         for (int i = 0; i < n; i++) {
99                             Object JavaDoc o = originalData[i];
100                             if (Debug.DEBUG) {
101                                 checkNull(o);
102                             }
103                             data[i] = o;
104                         }
105                 }
106                 ;
107             } else {
108                 int i;
109                 for (i = 0; i < n; i++) {
110                     Object JavaDoc o = originalData[i];
111                     if (Debug.DEBUG) {
112                         checkNull(o);
113                     }
114                     data[i] = o;
115                 }
116                 size = i;
117             }
118         }
119     }
120
121     public Object JavaDoc get(int index) {
122         checkIndex(index);
123         return data[index];
124     }
125
126     public int size() {
127         return size;
128     }
129
130     private RuntimeException JavaDoc createNPE() {
131         return BindingSupportImpl.getInstance().nullElement(
132                 "Null element not allowed: " + fmd.getQName());
133     }
134
135     public boolean add(Object JavaDoc o) {
136         if (Debug.DEBUG) {
137             checkNull(o);
138         }
139
140         if (size == data.length) expand();
141         data[size++] = o;
142         makeDirty();
143         switch (managed) {
144             case MANAGED_ONE_TO_MANY:
145                 SCOInverseUtil.addMasterOnDetail(o, owner, inverseFieldNo);
146                 break;
147             case MANAGED_MANY_TO_MANY:
148                 SCOInverseUtil.addToOtherSideOfManyToMany(o, inverseFieldNo,
149                         owner);
150                 break;
151         }
152         return true;
153     }
154
155     private void checkNull(Object JavaDoc o) {
156         if (!((FieldMetaData)fmd).ordered && o == null) {
157             throw createNPE();
158         }
159     }
160
161     private void expand() {
162         modCount++;
163         Object JavaDoc[] a = new Object JavaDoc[(size * 3) / 2 + 1];
164         System.arraycopy(data, 0, a, 0, size);
165         data = a;
166     }
167
168     private void ensureCapacity(int minSize) {
169         modCount++;
170         int n = (size * 3) / 2 + 1;
171         if (n < minSize) n = minSize;
172         Object JavaDoc[] a = new Object JavaDoc[n];
173         System.arraycopy(data, 0, a, 0, size);
174         data = a;
175     }
176
177     public void add(int index, Object JavaDoc element) {
178         if (Debug.DEBUG) {
179             checkNull(element);
180         }
181         if (index > size || index < 0) {
182             throw BindingSupportImpl.getInstance().indexOutOfBounds(
183                     "Index: " + index + ", Size: " + size);
184         }
185         if (size == data.length) expand();
186         if (index < size) {
187             System.arraycopy(data, index, data, index + 1, size - index);
188         }
189         data[index] = element;
190         size++;
191         makeDirty();
192         switch (managed) {
193             case MANAGED_ONE_TO_MANY:
194                 SCOInverseUtil.addMasterOnDetail(element, owner,
195                         inverseFieldNo);
196                 break;
197             case MANAGED_MANY_TO_MANY:
198                 SCOInverseUtil.addToOtherSideOfManyToMany(element,
199                         inverseFieldNo, owner);
200                 break;
201         }
202     }
203
204     private void checkIndex(int index) {
205         if (index >= size || index < 0) {
206             throw BindingSupportImpl.getInstance().indexOutOfBounds(
207                     "Index: " + index + ", Size: " + size);
208         }
209     }
210
211     public Object JavaDoc set(int index, Object JavaDoc element) {
212         if (Debug.DEBUG) {
213             checkNull(element);
214         }
215         checkIndex(index);
216         Object JavaDoc result = data[index];
217         data[index] = element;
218         makeDirty();
219         switch (managed) {
220             case MANAGED_ONE_TO_MANY:
221                 if (result != null) {
222                     SCOInverseUtil.removeMasterOnDetail(result, owner,
223                             inverseFieldNo);
224                 }
225                 SCOInverseUtil.addMasterOnDetail(element, owner,
226                         inverseFieldNo);
227                 break;
228             case MANAGED_MANY_TO_MANY:
229                 if (result != null) {
230                     SCOInverseUtil.removeFromOtherSideOfManyToMany(result,
231                             inverseFieldNo, owner);
232                 }
233                 SCOInverseUtil.addToOtherSideOfManyToMany(element,
234                         inverseFieldNo, owner);
235                 break;
236         }
237         return result;
238     }
239
240     public Object JavaDoc remove(int index) {
241         checkIndex(index);
242         modCount++;
243         makeDirty();
244         return removeImp(index);
245     }
246
247     private Object JavaDoc removeImp(int index) {
248         Object JavaDoc result = data[index];
249         int n = size - index - 1;
250         if (n > 0) System.arraycopy(data, index + 1, data, index, n);
251         data[--size] = null;
252         if (result == null) return null; // ok as we do not allow nulls in list
253
switch (managed) {
254             case MANAGED_ONE_TO_MANY:
255                 SCOInverseUtil.removeMasterOnDetail(result, owner,
256                         inverseFieldNo);
257                 break;
258             case MANAGED_MANY_TO_MANY:
259                 SCOInverseUtil.removeFromOtherSideOfManyToMany(result,
260                         inverseFieldNo, owner);
261                 break;
262         }
263         return result;
264     }
265
266     public int indexOf(Object JavaDoc o) {
267         if (o == null) {
268             for (int i = 0; i < size; i++) {
269                 if (data[i] == o) return i;
270             }
271         } else {
272             for (int i = 0; i < size; i++) {
273                 if (o.equals(data[i])) return i;
274             }
275         }
276         return -1;
277     }
278
279     public int lastIndexOf(Object JavaDoc o) {
280         if (o == null) {
281             for (int i = size - 1; i >= 0; i--) {
282                 if (data[i] == o) return i;
283             }
284         } else {
285             for (int i = size - 1; i >= 0; i--) {
286                 if (o.equals(data[i])) return i;
287             }
288         }
289         return -1;
290     }
291
292     public void clear() {
293         modCount++;
294         switch (managed) {
295             case MANAGED_ONE_TO_MANY:
296                 for (int i = 0; i < size; i++) {
297                     SCOInverseUtil.removeMasterOnDetail(data[i], owner,
298                             inverseFieldNo);
299                     data[i] = null;
300                 }
301                 break;
302             case MANAGED_MANY_TO_MANY:
303                 for (int i = 0; i < size; i++) {
304                     SCOInverseUtil.removeFromOtherSideOfManyToMany(data[i],
305                             inverseFieldNo, owner);
306                     data[i] = null;
307                 }
308                 break;
309             default:
310                 for (int i = 0; i < size; i++) data[i] = null;
311         }
312         size = 0;
313         makeDirty();
314     }
315
316     public boolean addAll(int index, Collection JavaDoc c) {
317         if (index > size || index < 0) {
318             throw BindingSupportImpl.getInstance().indexOutOfBounds(
319                     "Index: " + index + ", Size: " + size);
320         }
321         int numNew = c.size();
322         if (numNew == 0) return false;
323         int newSize = size + numNew;
324         if (newSize > data.length) ensureCapacity(newSize);
325
326         int n = size - index;
327         if (n > 0) System.arraycopy(data, index, data, index + numNew, n);
328
329         Iterator JavaDoc e = c.iterator();
330         switch (managed) {
331             case MANAGED_ONE_TO_MANY:
332                 for (int i = 0; i < numNew; i++) {
333                     Object JavaDoc o = e.next();
334                     if (Debug.DEBUG) {
335                         checkNull(o);
336                     }
337                     SCOInverseUtil.addMasterOnDetail(o, owner, inverseFieldNo);
338                     data[index++] = o;
339                 }
340                 break;
341             case MANAGED_MANY_TO_MANY:
342                 for (int i = 0; i < numNew; i++) {
343                     Object JavaDoc o = e.next();
344                     if (Debug.DEBUG) {
345                         checkNull(o);
346                     }
347                     SCOInverseUtil.addToOtherSideOfManyToMany(o,
348                             inverseFieldNo, owner);
349                     data[index++] = o;
350                 }
351                 break;
352             default:
353                 for (int i = 0; i < numNew; i++) {
354                     Object JavaDoc o = e.next();
355                     if (Debug.DEBUG) {
356                         checkNull(o);
357                     }
358                     data[index++] = o;
359                 }
360         }
361
362         size += numNew;
363         makeDirty();
364         return true;
365     }
366
367     public boolean addAll(Collection JavaDoc c) {
368         int numNew = c.size();
369         if (numNew == 0) return false;
370         int newSize = size + numNew;
371         if (newSize > data.length) ensureCapacity(newSize);
372
373         Iterator JavaDoc e = c.iterator();
374         switch (managed) {
375             case MANAGED_ONE_TO_MANY:
376                 for (int i = 0; i < numNew; i++) {
377                     Object JavaDoc o = e.next();
378                     if (Debug.DEBUG) {
379                         checkNull(o);
380                     }
381                     SCOInverseUtil.addMasterOnDetail(o, owner, inverseFieldNo);
382                     data[size++] = o;
383                 }
384                 break;
385             case MANAGED_MANY_TO_MANY:
386                 for (int i = 0; i < numNew; i++) {
387                     Object JavaDoc o = e.next();
388                     if (Debug.DEBUG) {
389                         checkNull(o);
390                     }
391                     SCOInverseUtil.addToOtherSideOfManyToMany(o,
392                             inverseFieldNo, owner);
393                     data[size++] = o;
394                 }
395                 break;
396             default:
397                 for (int i = 0; i < numNew; i++) {
398                     Object JavaDoc o = e.next();
399                     if (Debug.DEBUG) {
400                         checkNull(o);
401                     }
402                     data[size++] = o;
403                 }
404         }
405
406         makeDirty();
407         return true;
408     }
409
410     protected void removeRange(int fromIndex, int toIndex) {
411         modCount++;
412
413         switch (managed) {
414             case MANAGED_ONE_TO_MANY:
415                 for (int i = fromIndex; i < toIndex; i++) {
416                     SCOInverseUtil.removeMasterOnDetail(data[i], owner,
417                             inverseFieldNo);
418                 }
419                 break;
420             case MANAGED_MANY_TO_MANY:
421                 for (int i = fromIndex; i < toIndex; i++) {
422                     SCOInverseUtil.removeFromOtherSideOfManyToMany(data[i],
423                             inverseFieldNo, owner);
424                 }
425                 break;
426         }
427
428         int numMoved = size - toIndex;
429         if (numMoved > 0) {
430             System.arraycopy(data, toIndex, data, fromIndex,
431                     numMoved);
432         }
433
434         int newSize = size - (toIndex - fromIndex);
435         while (size != newSize) data[--size] = null;
436
437         makeDirty();
438     }
439
440     public boolean isEmpty() {
441         return size == 0;
442     }
443
444     public boolean contains(Object JavaDoc o) {
445         if (o == null) {
446             for (int i = 0; i < size; i++) {
447                 if (data[i] == o) return true;
448             }
449         } else {
450             for (int i = 0; i < size; i++) {
451                 if (o.equals(data[i])) return true;
452             }
453         }
454         return false;
455     }
456
457     public Object JavaDoc[] toArray() {
458         Object JavaDoc[] a = new Object JavaDoc[size];
459         System.arraycopy(data, 0, a, 0, size);
460         return a;
461     }
462
463     public Object JavaDoc[] toArray(Object JavaDoc a[]) {
464         if (a.length < size) {
465             a = (Object JavaDoc[])java.lang.reflect.Array.newInstance(
466                     a.getClass().getComponentType(), size);
467         }
468         System.arraycopy(data, 0, a, 0, size);
469         if (a.length > size) a[size] = null;
470         return a;
471     }
472
473     public boolean remove(Object JavaDoc o) {
474         int i = indexOf(o);
475         if (i >= 0) {
476             remove(i);
477             return true;
478         }
479         return false;
480     }
481
482     public Object JavaDoc clone() {
483         try {
484             SCOList v = (SCOList)super.clone();
485             v.data = new Object JavaDoc[size];
486             System.arraycopy(data, 0, v.data, 0, size);
487             v.modCount = 0;
488             return v;
489         } catch (CloneNotSupportedException JavaDoc e) {
490             // this shouldn't happen, since we are Cloneable
491
throw new InternalError JavaDoc();
492         }
493     }
494
495     /**
496      * Same format as ArrayList.
497      */

498     private synchronized void writeObject(java.io.ObjectOutputStream JavaDoc s)
499             throws java.io.IOException JavaDoc {
500         s.defaultWriteObject();
501         s.writeInt(data.length);
502         for (int i = 0; i < size; i++) s.writeObject(data[i]);
503     }
504
505     /**
506      * Same format as ArrayList.
507      */

508     private synchronized void readObject(java.io.ObjectInputStream JavaDoc s)
509             throws java.io.IOException JavaDoc, ClassNotFoundException JavaDoc {
510         s.defaultReadObject();
511         int arrayLength = s.readInt();
512         data = new Object JavaDoc[arrayLength];
513         for (int i = 0; i < size; i++) data[i] = s.readObject();
514     }
515
516     public CollectionDiff getCollectionDiff(PersistenceContext pm) {
517         if (fmd.isOrdered()) {
518             return CollectionDiffUtil.getOrderedCollectionDiff(fmd, pm,
519                     data, size,
520                     (owner.jdoIsNew() && !beenReset) ? null : originalData);
521         } else {
522             return CollectionDiffUtil.getUnorderedCollectionDiff(fmd, pm,
523                     data, size,
524                     (owner.jdoIsNew() && !beenReset) ? null : originalData);
525         }
526     }
527
528     public Object JavaDoc getOwner() {
529         return owner;
530     }
531
532     public void makeTransient() {
533         owner = null;
534         stateManager = null;
535     }
536
537     public void makeDirty() {
538         if (stateManager != null) {
539             stateManager.makeDirty(owner, fmd.getManagedFieldNo());
540         }
541     }
542
543     public void reset() {
544         beenReset = true;
545         originalData = toArray();
546     }
547
548     public void manyToManyAdd(Object JavaDoc o) {
549         if (size == data.length) expand();
550         data[size++] = o;
551         makeDirty();
552     }
553
554     public void manyToManyRemove(Object JavaDoc o) {
555         int i = indexOf(o);
556         if (i < 0) return;
557         modCount++;
558         int n = size - i - 1;
559         if (n > 0) System.arraycopy(data, i + 1, data, i, n);
560         data[--size] = null;
561         makeDirty();
562     }
563
564     public boolean containsAll(Collection JavaDoc c) {
565         for (Iterator JavaDoc i = c.iterator(); i.hasNext();) {
566             if (indexOf(i.next()) < 0) return false;
567         }
568         return true;
569     }
570
571     public boolean removeAll(Collection JavaDoc c) {
572         int mc = modCount;
573         for (Iterator JavaDoc i = c.iterator(); i.hasNext();) {
574             int index = indexOf(i.next());
575             if (index >= 0) {
576                 removeImp(index);
577                 modCount++;
578             }
579         }
580         if (mc != modCount) {
581             makeDirty();
582             return true;
583         } else {
584             return false;
585         }
586     }
587
588     public boolean retainAll(Collection JavaDoc c) {
589         int mc = modCount;
590         for (int i = 0; i < size;) {
591             if (c.contains(data[i])) {
592                 i++;
593             } else {
594                 removeImp(i);
595                 modCount++;
596             }
597         }
598         if (mc != modCount) {
599             makeDirty();
600             return true;
601         } else {
602             return false;
603         }
604     }
605
606     /**
607      * Is the collection ordered.
608      */

609     public boolean isOrdered() {
610         return fmd.isOrdered();
611     }
612
613     /**
614      * Put references to all the values into collectionData. If the
615      * values are PC instances then the instances themselves or their
616      * OIDs may be stored in collectionData.
617      */

618     public CollectionData fillCollectionData(CollectionData collectionData) {
619         int size = size();
620         collectionData.valueCount = size;
621         Object JavaDoc[] newData;
622         Object JavaDoc[] values = collectionData.values;
623         if (values == null || values.length < size) {
624             newData = new Object JavaDoc[size];
625         } else {
626             newData = values;
627         }
628         System.arraycopy(data, 0, newData, 0, size);
629         collectionData.values = newData;
630         return collectionData;
631     }
632 }
633
Popular Tags