1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.wotonomy.datastore;
20
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Iterator;
24 import java.util.LinkedList;
25 import java.util.List;
26 import java.util.ListIterator;
27 import java.util.Observable;
28
29 public class DefaultDataView extends Observable
30 implements DataView
31 {
32 protected DataSoup backingSoup;
33 protected List objectList;
34 protected List keyList;
35 protected List addedObjectList;
36 protected List removedObjectList;
37 protected List addedKeyList;
38 protected List removedKeyList;
39 protected Collection updatedObjects;
40 protected boolean fullyLoaded;
41
42 DefaultDataView( DataSoup aSoup, Collection aKeyList )
43 {
44 backingSoup = aSoup;
45 objectList = new ArrayList();
46 keyList = new ArrayList();
47 addedObjectList = new ArrayList();
48 removedObjectList = new ArrayList();
49 addedKeyList = new ArrayList();
50 removedKeyList = new ArrayList();
51 updatedObjects = new LinkedList();
52 fullyLoaded = false;
53
54 setKeyList( aKeyList );
55 }
56
57 void setKeyList( Collection aCollection )
58 {
59 fullyLoaded = false;
60 addedObjectList.clear();
61 removedObjectList.clear();
62 addedKeyList.clear();
63 removedKeyList.clear();
64 updatedObjects.clear();
65 keyList.clear();
66 objectList.clear();
67 if ( ( aCollection == null ) || ( aCollection.size() == 0 ) )
68 {
69 return;
70 }
71 keyList.addAll( aCollection );
72 for ( int i = 0; i < keyList.size(); i++ )
73 {
74 objectList.add( null );
75 }
76 }
77
78 public Object get( int i )
79 {
80 if ( i > keyList.size() ) return null;
81
82 Object o = objectList.get( i );
83 if ( o == null )
84 {
85 Object key = keyList.get( i );
86 if ( key == null ) return null;
87
88
89 o = backingSoup.getObjectByKey( (DataKey) key );
90
91 objectList.set( i, o );
92 }
93 return o;
94 }
95
96 public int indexOf( Object o )
97 {
98 if ( o == null ) return -1;
99 for ( int i = 0; i < size(); i++ )
100 {
101 if ( o.equals( get( i ) ) )
102 {
103 return i;
104 }
105 }
106 return -1;
107 }
108
109 private int indexOfIdenticalObject( Object o )
110 {
111 if ( o == null ) return -1;
112 for ( int i = 0; i < size(); i++ )
113 {
114 if ( o == get( i ) )
115 {
116 return i;
117 }
118 }
119 return -1;
120 }
121
122 public int lastIndexOf( Object o )
123 {
124 if ( o == null ) return -1;
125 int lastIndex = -1;
126 for ( int i = 0; i < size(); i++ )
127 {
128 if ( o.equals( get( i ) ) )
129 {
130 lastIndex = i;
131 }
132 }
133 return lastIndex;
134 }
135
136 protected void loadAllObjects()
137 {
138 if ( fullyLoaded ) return;
139 for ( int i = 0; i < keyList.size(); i++ )
140 {
141 get( i );
142 }
143 fullyLoaded = true;
144 }
145
146
147 public Object getObject()
148 {
149 return get( 0 );
150 }
151
152
153 public void update( Object anObject )
154 {
155 if ( contains( anObject ) )
156 {
157 if ( ! addedObjectList.contains( anObject ) )
158 {
159 updatedObjects.add( anObject );
160 }
161 }
162
163
164 setChanged();
165 notifyObservers( anObject );
166 }
167
168
169
170 public DataView query(
171 String aProperty, Object beginKey, Object endKey ) { return this; }
172
173 public boolean commit()
174 {
175 int index;
176 Object o;
177 DataKey key;
178 for ( int i = 0; i < addedObjectList.size(); i++ )
179 {
180 o = addedObjectList.get(i);
181 key = backingSoup.addObject( o );
182 index = indexOfIdenticalObject( o );
183 keyList.set( index, key );
184 }
185 addedObjectList.clear();
186 addedKeyList.clear();
187 for ( int i = 0; i < removedObjectList.size(); i++ )
188 {
189 backingSoup.removeObject( (DataKey) removedKeyList.get(i) );
190 }
191 removedObjectList.clear();
192 removedKeyList.clear();
193
194 int i;
195 Iterator it = updatedObjects.iterator();
196 while ( it.hasNext() )
197 {
198 i = objectList.indexOf( it.next() );
199 backingSoup.updateObject(
200 (DataKey) keyList.get(i), objectList.get(i) );
201 }
202 updatedObjects.clear();
203
204
205 setChanged();
206 notifyObservers( this );
207
208 return true;
209 }
210
211 public DataKey getKeyForObject( Object anObject )
212 {
213 int index = indexOfIdenticalObject( anObject );
214 if ( index == -1 ) return null;
215 return (DataKey) keyList.get( index );
216 }
217
218 public Object getObjectForKey( DataKey aKey )
219 {
220 int index = keyList.indexOf( aKey );
221 if ( index == -1 ) return null;
222 return get( index );
223 }
224
225
226
227 public int size () { return keyList.size(); }
228 public boolean isEmpty () { return keyList.isEmpty(); }
229 public void clear () { setKeyList( null ); };
230 public int hashCode() { return keyList.hashCode(); };
231
232 public boolean equals (Object o)
233 {
234 if ( ! ( o instanceof DefaultDataView ) ) return false;
235 return keyList.equals( ((DefaultDataView)o).keyList );
236 }
237
238 public boolean contains (Object o)
239 {
240 loadAllObjects();
241 return objectList.contains(o);
242 }
243
244 public boolean containsAll (Collection c)
245 {
246 loadAllObjects();
247 return objectList.containsAll( c );
248 }
249
250 public boolean add (Object o)
251 {
252
253 if ( removedObjectList.contains( o ) )
254 {
255 int index = removedObjectList.indexOf( o );
256 removedObjectList.remove( index );
257 Object key = removedKeyList.remove( index );
258 objectList.add( o );
259 keyList.add( key );
260
261
262 setChanged();
263 notifyObservers( o );
264 return true;
265 }
266
267
268 Object key = backingSoup.registerTemporaryObject( o );
269 addedObjectList.add( o );
270 addedKeyList.add( key );
271 objectList.add( o );
272 keyList.add( key );
273
274
275 setChanged();
276 notifyObservers( o );
277 return true;
278 }
279
280 public Object remove( int index )
281 {
282 Object result = get( index );
283 if ( remove( result ) )
284 {
285 return result;
286 }
287 return null;
288 }
289
290 public boolean remove (Object o)
291 {
292 loadAllObjects();
293
294 int index = objectList.indexOf( o );
295 if ( index == -1 ) return false;
296
297 objectList.remove( index );
298 Object key = keyList.remove( index );
299
300 if ( updatedObjects.contains( o ) )
301 {
302 updatedObjects.remove( o );
303 }
304
305
306 if ( ! ( removedObjectList.contains( o ) ) )
307 {
308 removedObjectList.add( o );
309 removedKeyList.add( key );
310 }
311
312
313 setChanged();
314 notifyObservers( o );
315
316 return true;
317 }
318
319 /***
320 * Set completely replaces the object at the specified
321 * index with the specified object. The new object is not
322 * marked as inserted, and the old object is not marked
323 * as deleted: the new object will be stored in the soup
324 * with the same key. The old object is returned.
325 */
326 public Object set( int index, Object element )
327 {
328 Object result = objectList.set( index, element );
329 update( element );
330 return result;
331 }
332
333 public void add( int index, Object o )
334 {
335
336 if ( removedObjectList.contains( o ) )
337 {
338 int i = removedObjectList.indexOf( o );
339 removedObjectList.remove( i );
340 Object key = removedKeyList.remove( i );
341 objectList.add( index, o );
342 keyList.add( index, key );
343
344
345 setChanged();
346 notifyObservers( o );
347 return;
348 }
349
350
351 Object key = backingSoup.registerTemporaryObject( o );
352 addedObjectList.add( o );
353 addedKeyList.add( key );
354 objectList.add( index, o );
355 keyList.add( index, key );
356
357
358 setChanged();
359 notifyObservers( o );
360 }
361
362 public boolean addAll (Collection c)
363 {
364 boolean result = true;
365 Iterator it = c.iterator();
366 while ( it.hasNext() )
367 {
368 result = result && add( it.next() );
369 }
370 return result;
371 }
372
373 public boolean addAll (int index, Collection c)
374 {
375 int originalSize = size();
376 boolean result = true;
377 Iterator it = c.iterator();
378 while ( it.hasNext() )
379 {
380 add( index, it.next() );
381 }
382 return ( originalSize + c.size() == size() );
383 }
384
385 public boolean removeAll (Collection c)
386 {
387 boolean result = true;
388 Iterator it = c.iterator();
389 while ( it.hasNext() )
390 {
391 result = result && remove( it.next() );
392 }
393 return result;
394 }
395
396 public boolean retainAll (Collection c)
397 {
398 removeAll( new ArrayList( objectList ) );
399 return addAll( c );
400 }
401
402 public List subList( int fromIndex, int toIndex )
403 {
404 List result = new LinkedList();
405 for ( int i = fromIndex; i < toIndex; i++ )
406 {
407 result.add( get( i ) );
408 }
409 return result;
410 }
411
412 public Iterator iterator()
413 {
414 loadAllObjects();
415 return objectList.iterator();
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431 }
432
433 public ListIterator listIterator()
434 {
435 return new DataViewIterator( this );
436 }
437
438 public ListIterator listIterator( int index )
439 {
440 return new DataViewIterator( this, index );
441 }
442
443 public Object[] toArray ()
444 {
445 loadAllObjects();
446 return objectList.toArray();
447 }
448 public java.lang.Object[] toArray (Object[] array)
449 {
450 loadAllObjects();
451 return objectList.toArray( array );
452 }
453
454 protected class DataViewIterator implements ListIterator
455 {
456 DataView theView;
457 int currentIndex;
458
459
460
461 Object currentObject;
462
463 public DataViewIterator( DataView aView )
464 {
465 this( aView, 0 );
466 }
467
468 public DataViewIterator( DataView aView, int index )
469 {
470 theView = aView;
471 if ( theView.size() > index )
472 {
473 currentIndex = index;
474 currentObject = theView.get( currentIndex );
475 }
476 else
477 {
478 index = -1;
479 currentObject = null;
480 }
481 }
482
483 public void add( Object o )
484 {
485 currentIndex++;
486 theView.add( currentIndex, o );
487 }
488
489 public boolean hasNext()
490 {
491 return ( theView.size() > currentIndex + 1 );
492 }
493
494 public boolean hasPrevious()
495 {
496 return ( currentIndex > -1 );
497 }
498
499 public Object next()
500 {
501 return theView.get( ++currentIndex );
502 }
503
504 public int nextIndex()
505 {
506 return currentIndex + 1;
507 }
508
509 public Object previous()
510 {
511 return theView.get( currentIndex-- );
512 }
513
514 public int previousIndex()
515 {
516 return currentIndex;
517 }
518
519 public void remove()
520 {
521 theView.remove( currentIndex-- );
522 }
523
524 public void set( Object o )
525 {
526 theView.set( currentIndex, o );
527 }
528
529 }
530 }
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557