1 package org.hibernate.collection; 3 4 import java.io.Serializable ; 5 import java.util.ArrayList ; 6 import java.util.Collection ; 7 import java.util.HashSet ; 8 import java.util.Iterator ; 9 import java.util.List ; 10 import java.util.ListIterator ; 11 12 import org.hibernate.AssertionFailure; 13 import org.hibernate.HibernateException; 14 import org.hibernate.LazyInitializationException; 15 import org.hibernate.engine.ForeignKeys; 16 import org.hibernate.engine.SessionImplementor; 17 import org.hibernate.engine.TypedValue; 18 import org.hibernate.persister.collection.CollectionPersister; 19 import org.hibernate.type.Type; 20 import org.hibernate.util.EmptyIterator; 21 22 27 public abstract class AbstractPersistentCollection 28 implements Serializable , PersistentCollection { 29 30 private transient SessionImplementor session; 31 private boolean initialized; 32 private transient List additions; 33 private transient boolean directlyAccessible; 34 private transient boolean initializing; 35 private Object owner; 36 37 private String role; 38 private Serializable key; 39 private boolean dirty; 42 private Serializable storedSnapshot; 43 44 public final String getRole() { 45 return role; 46 } 47 48 public final Serializable getKey() { 49 return key; 50 } 51 52 public final boolean isUnreferenced() { 53 return role==null; 54 } 55 56 public final boolean isDirty() { 57 return dirty; 58 } 59 60 public final void clearDirty() { 61 dirty = false; 62 } 63 64 public final void dirty() { 65 dirty = true; 66 } 67 68 public final Serializable getStoredSnapshot() { 69 return storedSnapshot; 70 } 71 72 76 public abstract boolean empty(); 77 80 protected final void read() { 81 initialize(false); 82 } 83 86 private final boolean isConnectedToSession() { 87 return session!=null && session.isOpen(); 88 } 89 90 93 protected final void write() { 94 initialize(true); 95 dirty(); 96 } 97 101 private boolean isQueueAdditionEnabled() { 102 return !initialized && 103 isConnectedToSession() && 104 session.getPersistenceContext().isInverseCollection(this); 105 } 106 109 protected final boolean queueAdd(Object element) { 110 if ( isQueueAdditionEnabled() ) { 111 if (additions==null) additions = new ArrayList (10); 112 additions.add(element); 113 dirty = true; return true; 115 } 116 else { 117 return false; 118 } 119 } 120 123 protected final boolean queueAddAll(Collection coll) { 124 if ( isQueueAdditionEnabled() ) { 125 if (additions==null) additions = new ArrayList (20); 126 additions.addAll(coll); 127 return true; 128 } 129 else { 130 return false; 131 } 132 } 133 134 138 public void delayedAddAll(Collection coll) { 139 throw new AssertionFailure("Collection does not support delayed initialization"); 140 } 141 142 145 public void setSnapshot(Serializable key, String role, Serializable snapshot) { 146 this.key = key; 147 this.role = role; 148 this.storedSnapshot = snapshot; 149 } 150 151 155 public void postAction() { 156 if (additions!=null) additions=null; 157 clearDirty(); 158 } 159 160 164 public AbstractPersistentCollection() {} 165 166 protected AbstractPersistentCollection(SessionImplementor session) { 167 this.session = session; 168 } 169 170 173 public Object getValue() { 174 return this; 175 } 176 177 180 public void beginRead() { 181 initializing = true; 183 } 184 185 188 public boolean endRead() { 189 return afterInitialize(); 191 } 192 193 public boolean afterInitialize() { 194 setInitialized(); 195 if (additions!=null) { 197 delayedAddAll(additions); 198 additions=null; 199 return false; 200 } 201 else { 202 return true; 203 } 204 } 205 206 212 protected final void initialize(boolean writing) { 213 if (!initialized) { 214 if (initializing) { 215 throw new LazyInitializationException("illegal access to loading collection"); 216 } 217 if ( isConnectedToSession() ) { 218 if ( session.isConnected() ) { 219 session.initializeCollection(this, writing); 220 } 221 else { 222 throwLazyInitializationException("session is disconnected"); 223 } 224 } 225 else { 226 throwLazyInitializationException("no session or session was closed"); 227 } 228 } 229 } 230 231 private void throwLazyInitializationException(String msg) { 232 throw new LazyInitializationException( 233 "failed to lazily initialize a collection" + 234 (role==null ? "" : " of role: " + role) + 235 ", " + msg 236 ); 237 } 238 239 protected final void setInitialized() { 240 this.initializing = false; 241 this.initialized = true; 242 } 243 244 protected final void setDirectlyAccessible(boolean directlyAccessible) { 245 this.directlyAccessible = directlyAccessible; 246 } 247 248 252 public boolean isDirectlyAccessible() { 253 return directlyAccessible; 254 } 255 256 260 public final boolean unsetSession(SessionImplementor currentSession) { 261 if (currentSession==this.session) { 262 this.session=null; 263 return true; 264 } 265 else { 266 return false; 267 } 268 } 269 270 276 public final boolean setCurrentSession(SessionImplementor session) throws HibernateException { 277 if (session==this.session) { 278 return false; 279 } 280 else { 281 if ( isConnectedToSession() ) { 282 throw new HibernateException("Illegal attempt to associate a collection with two open sessions"); 283 } 284 else { 285 this.session = session; 286 return true; 287 } 288 } 289 } 290 291 294 public boolean needsRecreate(CollectionPersister persister) { 295 return false; 296 } 297 298 302 public final void forceInitialization() throws HibernateException { 303 if (!initialized) { 304 if (initializing) { 305 throw new AssertionFailure("force initialize loading collection"); 306 } 307 if (session==null) { 308 throw new HibernateException("collection is not associated with any session"); 309 } 310 if ( !session.isConnected() ) { 311 throw new HibernateException("disconnected session"); 312 } 313 session.initializeCollection(this, false); 314 } 315 } 316 317 318 321 protected final Serializable getSnapshot() { 322 return session.getPersistenceContext().getSnapshot(this); 323 } 324 325 328 public final boolean wasInitialized() { 329 return initialized; 330 } 331 332 public boolean isRowUpdatePossible() { 333 return true; 334 } 335 336 339 public final boolean hasQueuedAdditions() { 340 return additions!=null; 341 } 342 345 public final Iterator queuedAdditionIterator() { 346 return hasQueuedAdditions() ? 347 additions.iterator() : 348 EmptyIterator.INSTANCE; 349 } 350 351 355 public void preInsert(CollectionPersister persister) throws HibernateException {} 356 359 public void afterRowInsert(CollectionPersister persister, Object entry, int i) throws HibernateException {} 360 363 public abstract Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException; 364 365 368 protected final SessionImplementor getSession() { 369 return session; 370 } 371 372 final class IteratorProxy implements Iterator { 373 private final Iterator iter; 374 IteratorProxy(Iterator iter) { 375 this.iter=iter; 376 } 377 public boolean hasNext() { 378 return iter.hasNext(); 379 } 380 381 public Object next() { 382 return iter.next(); 383 } 384 385 public void remove() { 386 write(); 387 iter.remove(); 388 } 389 390 } 391 392 final class ListIteratorProxy implements ListIterator { 393 private final ListIterator iter; 394 ListIteratorProxy(ListIterator iter) { 395 this.iter = iter; 396 } 397 public void add(Object o) { 398 write(); 399 iter.add(o); 400 } 401 402 public boolean hasNext() { 403 return iter.hasNext(); 404 } 405 406 public boolean hasPrevious() { 407 return iter.hasPrevious(); 408 } 409 410 public Object next() { 411 return iter.next(); 412 } 413 414 public int nextIndex() { 415 return iter.nextIndex(); 416 } 417 418 public Object previous() { 419 return iter.previous(); 420 } 421 422 public int previousIndex() { 423 return iter.previousIndex(); 424 } 425 426 public void remove() { 427 write(); 428 iter.remove(); 429 } 430 431 public void set(Object o) { 432 write(); 433 iter.set(o); 434 } 435 436 } 437 438 class SetProxy implements java.util.Set { 439 440 final Collection set; 441 442 SetProxy(Collection set) { 443 this.set=set; 444 } 445 public boolean add(Object o) { 446 write(); 447 return set.add(o); 448 } 449 450 public boolean addAll(Collection c) { 451 write(); 452 return set.addAll(c); 453 } 454 455 public void clear() { 456 write(); 457 set.clear(); 458 } 459 460 public boolean contains(Object o) { 461 return set.contains(o); 462 } 463 464 public boolean containsAll(Collection c) { 465 return set.containsAll(c); 466 } 467 468 public boolean isEmpty() { 469 return set.isEmpty(); 470 } 471 472 public Iterator iterator() { 473 return new IteratorProxy( set.iterator() ); 474 } 475 476 public boolean remove(Object o) { 477 write(); 478 return set.remove(o); 479 } 480 481 public boolean removeAll(Collection c) { 482 write(); 483 return set.removeAll(c); 484 } 485 486 public boolean retainAll(Collection c) { 487 write(); 488 return set.retainAll(c); 489 } 490 491 public int size() { 492 return set.size(); 493 } 494 495 public Object [] toArray() { 496 return set.toArray(); 497 } 498 499 public Object [] toArray(Object [] array) { 500 return set.toArray(array); 501 } 502 503 } 504 505 final class ListProxy implements java.util.List { 506 507 private final java.util.List list; 508 509 ListProxy(java.util.List list) { 510 this.list = list; 511 } 512 513 public void add(int index, Object value) { 514 write(); 515 list.add(index, value); 516 } 517 518 521 public boolean add(Object o) { 522 write(); 523 return list.add(o); 524 } 525 526 529 public boolean addAll(Collection c) { 530 write(); 531 return list.addAll(c); 532 } 533 534 537 public boolean addAll(int i, Collection c) { 538 write(); 539 return list.addAll(i, c); 540 } 541 542 545 public void clear() { 546 write(); 547 list.clear(); 548 } 549 550 553 public boolean contains(Object o) { 554 return list.contains(o); 555 } 556 557 560 public boolean containsAll(Collection c) { 561 return list.containsAll(c); 562 } 563 564 567 public Object get(int i) { 568 return list.get(i); 569 } 570 571 574 public int indexOf(Object o) { 575 return list.indexOf(o); 576 } 577 578 581 public boolean isEmpty() { 582 return list.isEmpty(); 583 } 584 585 588 public Iterator iterator() { 589 return new IteratorProxy( list.iterator() ); 590 } 591 592 595 public int lastIndexOf(Object o) { 596 return list.lastIndexOf(o); 597 } 598 599 602 public ListIterator listIterator() { 603 return new ListIteratorProxy( list.listIterator() ); 604 } 605 606 609 public ListIterator listIterator(int i) { 610 return new ListIteratorProxy( list.listIterator(i) ); 611 } 612 613 616 public Object remove(int i) { 617 write(); 618 return list.remove(i); 619 } 620 621 624 public boolean remove(Object o) { 625 write(); 626 return list.remove(o); 627 } 628 629 632 public boolean removeAll(Collection c) { 633 write(); 634 return list.removeAll(c); 635 } 636 637 640 public boolean retainAll(Collection c) { 641 write(); 642 return list.retainAll(c); 643 } 644 645 648 public Object set(int i, Object o) { 649 write(); 650 return list.set(i, o); 651 } 652 653 656 public int size() { 657 return list.size(); 658 } 659 660 663 public List subList(int i, int j) { 664 return list.subList(i, j); 665 } 666 667 670 public Object [] toArray() { 671 return list.toArray(); 672 } 673 674 677 public Object [] toArray(Object [] array) { 678 return list.toArray(array); 679 } 680 681 } 682 683 684 protected static Collection getOrphans( 685 Collection oldElements, 686 Collection currentElements, 687 String entityName, 688 SessionImplementor session) 689 throws HibernateException { 690 691 if ( currentElements.size()==0 ) return oldElements; if ( oldElements.size()==0) return oldElements; 695 Type idType = session.getFactory().getEntityPersister(entityName).getIdentifierType(); 696 697 Collection res = new ArrayList (); 699 700 java.util.Set currentIds = new HashSet (); 702 for ( Iterator it=currentElements.iterator(); it.hasNext(); ) { 703 Object current = it.next(); 704 if ( current!=null && ForeignKeys.isNotTransient(entityName, current, null, session) ) { 705 Serializable currentId = ForeignKeys.getEntityIdentifierIfNotUnsaved(entityName, current, session); 706 currentIds.add( new TypedValue( idType, currentId, session.getEntityMode() ) ); 707 } 708 } 709 710 for ( Iterator it=oldElements.iterator(); it.hasNext(); ) { 712 Object old = it.next(); 713 Serializable oldId = ForeignKeys.getEntityIdentifierIfNotUnsaved(entityName, old, session); 714 if ( !currentIds.contains( new TypedValue( idType, oldId, session.getEntityMode() ) ) ) res.add(old); 715 } 716 717 return res; 718 } 719 720 static void identityRemove( 721 Collection list, 722 Object object, 723 String entityName, 724 SessionImplementor session) 725 throws HibernateException { 726 727 if ( object!=null && ForeignKeys.isNotTransient(entityName, object, null, session) ) { 728 729 Type idType = session.getFactory().getEntityPersister(entityName).getIdentifierType(); 730 731 Serializable idOfCurrent = ForeignKeys.getEntityIdentifierIfNotUnsaved(entityName, object, session); 732 Iterator iter = list.iterator(); 733 while ( iter.hasNext() ) { 734 Serializable idOfOld = ForeignKeys.getEntityIdentifierIfNotUnsaved(entityName, iter.next(), session); 735 if ( idType.isEqual( idOfCurrent, idOfOld, session.getEntityMode(), session.getFactory() ) ) { 736 iter.remove(); 737 break; 738 } 739 } 740 741 } 742 } 743 744 public Object getIdentifier(Object entry, int i) { 745 throw new UnsupportedOperationException (); 746 } 747 748 public Object getOwner() { 749 return owner; 750 } 751 752 public void setOwner(Object owner) { 753 this.owner = owner; 754 } 755 756 } 757 | Popular Tags |