1 8 9 package com.sleepycat.collections; 10 11 import java.util.Collection ; 12 import java.util.Iterator ; 13 import java.util.List ; 14 import java.util.ListIterator ; 15 16 import com.sleepycat.bind.EntityBinding; 17 import com.sleepycat.bind.EntryBinding; 18 import com.sleepycat.bind.RecordNumberBinding; 19 import com.sleepycat.je.Database; 20 import com.sleepycat.je.DatabaseEntry; 21 import com.sleepycat.je.DatabaseException; 22 import com.sleepycat.je.OperationStatus; 23 import com.sleepycat.util.keyrange.KeyRangeException; 24 25 46 public class StoredList extends StoredCollection implements List { 47 48 private static final EntryBinding DEFAULT_KEY_BINDING = 49 new IndexKeyBinding(1); 50 51 private int baseIndex = 1; 52 private boolean isSubList; 53 54 71 public StoredList(Database database, EntryBinding valueBinding, 72 boolean writeAllowed) { 73 74 super(new DataView(database, DEFAULT_KEY_BINDING, valueBinding, null, 75 writeAllowed, null)); 76 } 77 78 95 public StoredList(Database database, EntityBinding valueEntityBinding, 96 boolean writeAllowed) { 97 98 super(new DataView(database, DEFAULT_KEY_BINDING, null, 99 valueEntityBinding, writeAllowed, null)); 100 } 101 102 120 public StoredList(Database database, EntryBinding valueBinding, 121 PrimaryKeyAssigner keyAssigner) { 122 123 super(new DataView(database, DEFAULT_KEY_BINDING, valueBinding, 124 null, true, keyAssigner)); 125 } 126 127 145 public StoredList(Database database, EntityBinding valueEntityBinding, 146 PrimaryKeyAssigner keyAssigner) { 147 148 super(new DataView(database, DEFAULT_KEY_BINDING, null, 149 valueEntityBinding, true, keyAssigner)); 150 } 151 152 private StoredList(DataView view, int baseIndex) { 153 154 super(view); 155 this.baseIndex = baseIndex; 156 this.isSubList = true; 157 } 158 159 171 public void add(int index, Object value) { 172 173 checkIterAddAllowed(); 174 DataCursor cursor = null; 175 boolean doAutoCommit = beginAutoCommit(); 176 try { 177 cursor = new DataCursor(view, true); 178 OperationStatus status = 179 cursor.getSearchKey(new Long (index), null, false); 180 if (status == OperationStatus.SUCCESS) { 181 cursor.putBefore(value); 182 closeCursor(cursor); 183 } else { 184 closeCursor(cursor); 185 cursor = null; 186 view.append(value, null, null); 187 } 188 commitAutoCommit(doAutoCommit); 189 } catch (Exception e) { 190 closeCursor(cursor); 191 throw handleException(e, doAutoCommit); 192 } 193 } 194 195 207 public boolean add(Object value) { 208 209 checkIterAddAllowed(); 210 boolean doAutoCommit = beginAutoCommit(); 211 try { 212 view.append(value, null, null); 213 commitAutoCommit(doAutoCommit); 214 return true; 215 } catch (Exception e) { 216 throw handleException(e, doAutoCommit); 217 } 218 } 219 220 240 public int append(Object value) { 241 242 boolean doAutoCommit = beginAutoCommit(); 243 try { 244 Object [] key = new Object [1]; 245 view.append(value, key, null); 246 commitAutoCommit(doAutoCommit); 247 return ((Number ) key[0]).intValue(); 248 } catch (Exception e) { 249 throw handleException(e, doAutoCommit); 250 } 251 } 252 253 void checkIterAddAllowed() 254 throws UnsupportedOperationException { 255 256 if (isSubList) { 257 throw new UnsupportedOperationException ("cannot add to subList"); 258 } 259 if (!view.keysRenumbered) { throw new UnsupportedOperationException ( 261 "requires renumbered keys"); 262 } 263 } 264 265 278 public boolean addAll(int index, Collection coll) { 279 280 checkIterAddAllowed(); 281 DataCursor cursor = null; 282 Iterator i = null; 283 boolean doAutoCommit = beginAutoCommit(); 284 try { 285 i = storedOrExternalIterator(coll); 286 if (!i.hasNext()) { 287 return false; 288 } 289 cursor = new DataCursor(view, true); 290 OperationStatus status = 291 cursor.getSearchKey(new Long (index), null, false); 292 if (status == OperationStatus.SUCCESS) { 293 while (i.hasNext()) { 294 cursor.putBefore(i.next()); 295 } 296 closeCursor(cursor); 297 } else { 298 closeCursor(cursor); 299 cursor = null; 300 while (i.hasNext()) { 301 view.append(i.next(), null, null); 302 } 303 } 304 StoredIterator.close(i); 305 commitAutoCommit(doAutoCommit); 306 return true; 307 } catch (Exception e) { 308 closeCursor(cursor); 309 StoredIterator.close(i); 310 throw handleException(e, doAutoCommit); 311 } 312 } 313 314 321 public boolean contains(Object value) { 322 323 return containsValue(value); 324 } 325 326 333 public Object get(int index) { 334 335 return super.get(new Long (index)); 336 } 337 338 346 public int indexOf(Object value) { 347 348 return indexOf(value, true); 349 } 350 351 359 public int lastIndexOf(Object value) { 360 361 return indexOf(value, false); 362 } 363 364 private int indexOf(Object value, boolean findFirst) { 365 366 DataCursor cursor = null; 367 try { 368 cursor = new DataCursor(view, false); 369 OperationStatus status = cursor.findValue(value, findFirst); 370 return (status == OperationStatus.SUCCESS) 371 ? (cursor.getCurrentRecordNumber() - baseIndex) 372 : (-1); 373 } catch (Exception e) { 374 throw StoredContainer.convertException(e); 375 } finally { 376 closeCursor(cursor); 377 } 378 } 379 380 int getIndexOffset() { 381 382 return baseIndex; 383 } 384 385 401 public ListIterator listIterator() { 402 403 return blockIterator(); 404 } 405 406 422 public ListIterator listIterator(int index) { 423 424 BlockIterator i = blockIterator(); 425 if (i.moveToIndex(index)) { 426 return i; 427 } else { 428 throw new IndexOutOfBoundsException (String.valueOf(index)); 429 } 430 } 431 432 443 public Object remove(int index) { 444 445 try { 446 Object [] oldVal = new Object [1]; 447 removeKey(new Long (index), oldVal); 448 return oldVal[0]; 449 } catch (IllegalArgumentException e) { 450 throw new IndexOutOfBoundsException (e.getMessage()); 451 } 452 } 453 454 465 public boolean remove(Object value) { 466 467 return removeValue(value); 468 } 469 470 485 public Object set(int index, Object value) { 486 487 try { 488 return put(new Long (index), value); 489 } catch (IllegalArgumentException e) { 490 throw new IndexOutOfBoundsException (e.getMessage()); 491 } 492 } 493 494 503 public List subList(int fromIndex, int toIndex) { 504 505 if (fromIndex < 0 || fromIndex > toIndex) { 506 throw new IndexOutOfBoundsException (String.valueOf(fromIndex)); 507 } 508 try { 509 int newBaseIndex = baseIndex + fromIndex; 510 return new StoredList( 511 view.subView(new Long (fromIndex), true, 512 new Long (toIndex), false, 513 new IndexKeyBinding(newBaseIndex)), 514 newBaseIndex); 515 } catch (KeyRangeException e) { 516 throw new IndexOutOfBoundsException (e.getMessage()); 517 } catch (Exception e) { 518 throw StoredContainer.convertException(e); 519 } 520 } 521 522 531 public boolean equals(Object other) { 532 533 if (!(other instanceof List )) return false; 534 List otherList = (List ) other; 535 StoredIterator i1 = null; 536 ListIterator i2 = null; 537 try { 538 i1 = storedIterator(); 539 i2 = storedOrExternalListIterator(otherList); 540 while (i1.hasNext()) { 541 if (!i2.hasNext()) return false; 542 if (i1.nextIndex() != i2.nextIndex()) return false; 543 Object o1 = i1.next(); 544 Object o2 = i2.next(); 545 if (o1 == null) { 546 if (o2 != null) return false; 547 } else { 548 if (!o1.equals(o2)) return false; 549 } 550 } 551 if (i2.hasNext()) return false; 552 return true; 553 } finally { 554 if (i1 != null) { 555 i1.close(); 556 } 557 StoredIterator.close(i2); 558 } 559 } 560 561 566 final ListIterator storedOrExternalListIterator(List list) { 567 568 if (list instanceof StoredCollection) { 569 return ((StoredCollection) list).storedIterator(); 570 } else { 571 return list.listIterator(); 572 } 573 } 574 575 579 public int hashCode() { 580 return super.hashCode(); 581 } 582 583 Object makeIteratorData(BaseIterator iterator, 584 DatabaseEntry keyEntry, 585 DatabaseEntry priKeyEntry, 586 DatabaseEntry valueEntry) { 587 588 return view.makeValue(priKeyEntry, valueEntry); 589 } 590 591 boolean hasValues() { 592 593 return true; 594 } 595 596 private static class IndexKeyBinding extends RecordNumberBinding { 597 598 private int baseIndex; 599 600 private IndexKeyBinding(int baseIndex) { 601 602 this.baseIndex = baseIndex; 603 } 604 605 public Object entryToObject(DatabaseEntry data) { 606 607 return new Long (entryToRecordNumber(data) - baseIndex); 608 } 609 610 public void objectToEntry(Object object, DatabaseEntry data) { 611 612 recordNumberToEntry(((Number ) object).intValue() + baseIndex, 613 data); 614 } 615 } 616 } 617 | Popular Tags |