1 56 package org.objectstyle.cayenne.access; 57 58 import java.io.Serializable ; 59 import java.util.ArrayList ; 60 import java.util.Collection ; 61 import java.util.Collections ; 62 import java.util.HashMap ; 63 import java.util.Iterator ; 64 import java.util.List ; 65 import java.util.Map ; 66 67 import org.apache.log4j.Logger; 68 import org.objectstyle.cayenne.CayenneRuntimeException; 69 import org.objectstyle.cayenne.DataObject; 70 import org.objectstyle.cayenne.DataRow; 71 import org.objectstyle.cayenne.Fault; 72 import org.objectstyle.cayenne.ObjectId; 73 import org.objectstyle.cayenne.PersistenceState; 74 import org.objectstyle.cayenne.access.event.SnapshotEvent; 75 import org.objectstyle.cayenne.access.event.SnapshotEventListener; 76 import org.objectstyle.cayenne.event.EventManager; 77 import org.objectstyle.cayenne.map.ObjEntity; 78 import org.objectstyle.cayenne.map.ObjRelationship; 79 import org.objectstyle.cayenne.util.Util; 80 import org.objectstyle.cayenne.validation.ValidationException; 81 import org.objectstyle.cayenne.validation.ValidationResult; 82 83 94 public class ObjectStore implements Serializable , SnapshotEventListener { 95 96 private static Logger logObj = Logger.getLogger(ObjectStore.class); 97 98 protected transient Map newObjectMap = null; 99 100 protected Map objectMap = new HashMap (); 101 protected Map queryResultMap = new HashMap (); 102 103 protected List indirectlyModifiedIds = new ArrayList (); 106 107 protected List flattenedInserts = new ArrayList (); 108 protected List flattenedDeletes = new ArrayList (); 109 110 114 protected Map retainedSnapshotMap = new HashMap (); 115 116 124 protected transient DataRowStore dataRowCache; 125 126 public ObjectStore() { 127 } 128 129 public ObjectStore(DataRowStore dataRowCache) { 130 this(); 131 setDataRowCache(dataRowCache); 132 } 133 134 139 public int registeredObjectsCount() { 140 return objectMap.size(); 141 } 142 143 149 public int cachedQueriesCount() { 150 return queryResultMap.size(); 151 } 152 153 167 public synchronized void retainSnapshot(DataObject object) { 168 ObjectId oid = object.getObjectId(); 169 DataRow snapshot = getCachedSnapshot(oid); 170 171 if (snapshot == null) { 172 snapshot = object.getDataContext().currentSnapshot(object); 173 } 174 else if (snapshot.getVersion() != object.getSnapshotVersion()) { 176 DataContextDelegate delegate = object.getDataContext().nonNullDelegate(); 177 if (delegate.shouldMergeChanges(object, snapshot)) { 178 ObjEntity entity = object 179 .getDataContext() 180 .getEntityResolver() 181 .lookupObjEntity(object); 182 DataRowUtils.forceMergeWithSnapshot(entity, object, snapshot); 183 object.setSnapshotVersion(snapshot.getVersion()); 184 delegate.finishedMergeChanges(object); 185 } 186 } 187 188 retainSnapshot(object, snapshot); 189 } 190 191 198 protected synchronized void retainSnapshot(DataObject object, DataRow snapshot) { 199 this.retainedSnapshotMap.put(object.getObjectId(), snapshot); 200 } 201 202 205 public DataRowStore getDataRowCache() { 206 return dataRowCache; 207 } 208 209 213 public void setDataRowCache(DataRowStore dataRowCache) { 214 if (dataRowCache == this.dataRowCache) { 215 return; 216 } 217 218 221 if (this.dataRowCache != null) { 222 EventManager.getDefaultManager().removeListener( 223 this, 224 this.dataRowCache.getSnapshotEventSubject()); 225 } 226 227 this.dataRowCache = dataRowCache; 228 229 if (dataRowCache != null) { 230 EventManager.getDefaultManager().addNonBlockingListener( 234 this, 235 "snapshotsChanged", 236 SnapshotEvent.class, 237 dataRowCache.getSnapshotEventSubject()); 238 } 239 } 240 241 244 public synchronized void objectsInvalidated(Collection objects) { 245 if (objects.isEmpty()) { 246 return; 247 } 248 249 Collection ids = new ArrayList (objects.size()); 250 Iterator it = objects.iterator(); 251 while (it.hasNext()) { 252 DataObject object = (DataObject) it.next(); 253 254 if (object.getPersistenceState() == PersistenceState.NEW) { 258 continue; 259 } 260 261 object.setPersistenceState(PersistenceState.HOLLOW); 262 263 dataRowCache.forgetSnapshot(object.getObjectId()); 265 266 indirectlyModifiedIds.remove(object.getObjectId()); 268 269 ids.add(object.getObjectId()); 271 } 272 273 getDataRowCache().processSnapshotChanges( 275 this, 276 Collections.EMPTY_MAP, 277 Collections.EMPTY_LIST, 278 ids, 279 Collections.EMPTY_LIST); 280 } 281 282 287 public synchronized void objectsUnregistered(Collection objects) { 288 if (objects.isEmpty()) { 289 return; 290 } 291 292 Iterator it = objects.iterator(); 293 while (it.hasNext()) { 294 DataObject object = (DataObject) it.next(); 295 296 objectMap.remove(object.getObjectId()); 298 indirectlyModifiedIds.remove(object.getObjectId()); 299 dataRowCache.forgetSnapshot(object.getObjectId()); 300 301 object.setDataContext(null); 302 object.setObjectId(null); 303 object.setPersistenceState(PersistenceState.TRANSIENT); 304 } 305 306 } 309 310 315 public synchronized void objectsRolledBack() { 316 Iterator it = getObjectIterator(); 317 318 while (it.hasNext()) { 320 DataObject object = (DataObject) it.next(); 321 int objectState = object.getPersistenceState(); 322 switch (objectState) { 323 case PersistenceState.NEW: 324 it.remove(); 325 326 object.setDataContext(null); 327 object.setObjectId(null); 328 object.setPersistenceState(PersistenceState.TRANSIENT); 329 break; 330 case PersistenceState.DELETED: 331 case PersistenceState.MODIFIED: 334 object.setPersistenceState(PersistenceState.HOLLOW); 337 break; 338 default: 339 break; 341 } 342 } 343 344 this.retainedSnapshotMap.clear(); 347 this.indirectlyModifiedIds.clear(); 348 this.flattenedDeletes.clear(); 349 this.flattenedInserts.clear(); 350 } 351 352 357 public void objectRelationshipUnset( 358 DataObject source, 359 DataObject target, 360 ObjRelationship relationship, 361 boolean processFlattened) { 362 363 objectRelationshipChanged(source, relationship); 364 365 if (processFlattened) { 366 flattenedRelationshipUnset(source, relationship, target); 367 } 368 } 369 370 375 public void objectRelationshipSet( 376 DataObject source, 377 DataObject target, 378 ObjRelationship relationship, 379 boolean processFlattened) { 380 381 objectRelationshipChanged(source, relationship); 382 383 if (processFlattened) { 384 flattenedRelationshipSet(source, relationship, target); 385 } 386 } 387 388 393 void objectRelationshipChanged(DataObject object, ObjRelationship relationship) { 394 if (relationship.isSourceIndependentFromTargetChange()) { 396 int state = object.getPersistenceState(); 397 if (state == PersistenceState.COMMITTED 398 || state == PersistenceState.HOLLOW 399 || state == PersistenceState.MODIFIED) { 400 401 synchronized (this) { 402 indirectlyModifiedIds.add(object.getObjectId()); 403 } 404 } 405 } 406 } 407 408 423 public void snapshotsUpdatedForObjects(List objects, List snapshots, boolean refresh) { 424 425 if (objects.size() != snapshots.size()) { 427 throw new IllegalArgumentException ( 428 "Counts of objects and corresponding snapshots do not match. " 429 + "Objects count: " 430 + objects.size() 431 + ", snapshots count: " 432 + snapshots.size()); 433 } 434 435 Map modified = null; 436 437 synchronized (this) { 438 int size = objects.size(); 439 for (int i = 0; i < size; i++) { 440 DataObject object = (DataObject) objects.get(i); 441 ObjectId oid = object.getObjectId(); 442 443 DataRow cachedSnapshot = getCachedSnapshot(oid); 446 if (refresh || cachedSnapshot == null) { 447 448 DataRow newSnapshot = (DataRow) snapshots.get(i); 449 450 if (cachedSnapshot != null) { 451 if (cachedSnapshot.equals(newSnapshot)) { 453 object.setSnapshotVersion(cachedSnapshot.getVersion()); 454 continue; 455 } 456 else { 457 newSnapshot.setReplacesVersion(cachedSnapshot.getVersion()); 458 } 459 } 460 461 if (modified == null) { 462 modified = new HashMap (); 463 } 464 465 modified.put(oid, newSnapshot); 466 } 467 } 468 469 if (modified != null) { 470 getDataRowCache().processSnapshotChanges( 471 this, 472 modified, 473 Collections.EMPTY_LIST, 474 Collections.EMPTY_LIST, 475 Collections.EMPTY_LIST); 476 } 477 } 478 } 479 480 486 public synchronized void objectsCommitted() { 487 List deletedIds = null; 489 Map modifiedSnapshots = null; 490 491 Iterator entries = objectMap.entrySet().iterator(); 492 List modifiedIds = null; 493 494 while (entries.hasNext()) { 495 Map.Entry entry = (Map.Entry ) entries.next(); 496 497 DataObject object = (DataObject) entry.getValue(); 498 int state = object.getPersistenceState(); 499 ObjectId id = object.getObjectId(); 500 501 if(state == PersistenceState.NEW && !id.isReplacementIdAttached()) { 506 id = fixObjectId((ObjectId) entry.getKey(), object); 507 } 508 509 if (id.isReplacementIdAttached()) { 510 if (modifiedIds == null) { 511 modifiedIds = new ArrayList (); 512 } 513 514 modifiedIds.add(id); 515 516 continue; 518 } 519 else if (id.isTemporary()) { 521 throw new CayenneRuntimeException( 522 "Temporary ID hasn't been replaced on commit: " + object); 523 } 524 525 529 switch (state) { 531 case PersistenceState.DELETED: 532 entries.remove(); 533 dataRowCache.forgetSnapshot(id); 534 object.setDataContext(null); 535 object.setPersistenceState(PersistenceState.TRANSIENT); 536 537 if (deletedIds == null) { 538 deletedIds = new ArrayList (); 539 } 540 541 deletedIds.add(id); 542 break; 543 case PersistenceState.MODIFIED: 545 if (modifiedSnapshots == null) { 546 modifiedSnapshots = new HashMap (); 547 } 548 549 DataRow dataRow = object.getDataContext().currentSnapshot(object); 550 551 modifiedSnapshots.put(id, dataRow); 552 dataRow.setReplacesVersion(object.getSnapshotVersion()); 553 554 object.setPersistenceState(PersistenceState.COMMITTED); 555 object.setSnapshotVersion(dataRow.getVersion()); 556 break; 557 case PersistenceState.NEW: 560 object.setPersistenceState(PersistenceState.COMMITTED); 562 break; 563 } 564 } 565 566 if (modifiedIds != null) { 568 Iterator ids = modifiedIds.iterator(); 569 while (ids.hasNext()) { 570 ObjectId id = (ObjectId) ids.next(); 571 DataObject object = getObject(id); 572 573 if (object == null) { 574 throw new CayenneRuntimeException("No object for id: " + id); 575 } 576 577 if (!id.isTemporary()) { 581 if (deletedIds == null) { 582 deletedIds = new ArrayList (); 583 } 584 585 deletedIds.add(id); 586 } 587 588 if (modifiedSnapshots == null) { 590 modifiedSnapshots = new HashMap (); 591 } 592 593 ObjectId replacementId = id.createReplacementId(); 594 DataRow dataRow = object.getDataContext().currentSnapshot(object); 595 modifiedSnapshots.put(replacementId, dataRow); 596 dataRow.setReplacesVersion(object.getSnapshotVersion()); 597 598 object.setObjectId(replacementId); 600 object.setSnapshotVersion(dataRow.getVersion()); 601 object.setPersistenceState(PersistenceState.COMMITTED); 602 addObject(object); 603 604 objectMap.remove(id); 605 dataRowCache.forgetSnapshot(id); 606 } 607 } 608 609 if (deletedIds != null || modifiedSnapshots != null) { 611 getDataRowCache() 612 .processSnapshotChanges( 613 this, 614 modifiedSnapshots != null 615 ? modifiedSnapshots 616 : Collections.EMPTY_MAP, 617 deletedIds != null ? deletedIds : Collections.EMPTY_LIST, 618 Collections.EMPTY_LIST, 619 !indirectlyModifiedIds.isEmpty() ? new ArrayList ( 620 indirectlyModifiedIds) : Collections.EMPTY_LIST); 621 } 622 623 this.retainedSnapshotMap.clear(); 625 this.indirectlyModifiedIds.clear(); 626 this.flattenedDeletes.clear(); 627 this.flattenedInserts.clear(); 628 } 629 630 631 639 ObjectId fixObjectId(ObjectId registeredId, DataObject object) { 640 if (!registeredId.equals(object.getObjectId()) 641 && !object.getObjectId().isTemporary()) { 642 643 registeredId.getReplacementIdMap().putAll( 644 object.getObjectId().getIdSnapshot()); 645 646 object.setObjectId(registeredId); 647 } 648 649 return registeredId; 650 } 651 652 public synchronized void addObject(DataObject obj) { 653 objectMap.put(obj.getObjectId(), obj); 654 655 if (newObjectMap != null) { 656 newObjectMap.put(obj.getObjectId(), obj); 657 } 658 } 659 660 668 public synchronized void startTrackingNewObjects() { 669 newObjectMap = new HashMap (); 672 } 673 674 682 public synchronized void unregisterNewObjects() { 683 686 if(newObjectMap == null) { 687 return; 688 } 689 690 Iterator it = newObjectMap.values().iterator(); 691 692 while (it.hasNext()) { 693 DataObject dataObj = (DataObject) it.next(); 694 695 ObjectId oid = dataObj.getObjectId(); 696 objectMap.remove(oid); 697 dataRowCache.forgetSnapshot(oid); 698 699 dataObj.setDataContext(null); 700 dataObj.setObjectId(null); 701 dataObj.setPersistenceState(PersistenceState.TRANSIENT); 702 } 703 newObjectMap.clear(); 704 newObjectMap = null; 705 } 706 707 711 public synchronized DataObject getObject(ObjectId id) { 712 return (DataObject) objectMap.get(id); 713 } 714 715 public synchronized DataRow getRetainedSnapshot(ObjectId oid) { 716 return (DataRow) retainedSnapshotMap.get(oid); 717 } 718 719 725 public DataRow getCachedSnapshot(ObjectId oid) { 726 DataRow retained = getRetainedSnapshot(oid); 727 return (retained != null) ? retained : getDataRowCache().getCachedSnapshot(oid); 728 } 729 730 737 public synchronized List getCachedQueryResult(String name) { 738 return (List ) queryResultMap.get(name); 741 } 742 743 748 public synchronized void cacheQueryResult(String name, List results) { 749 queryResultMap.put(name, results); 750 } 751 752 760 public synchronized DataRow getSnapshot(ObjectId oid, QueryEngine engine) { 761 DataRow retained = getRetainedSnapshot(oid); 762 return (retained != null) ? retained : getDataRowCache().getSnapshot(oid, engine); 763 } 764 765 770 public synchronized List getObjects() { 771 return new ArrayList (objectMap.values()); 772 } 773 774 777 public synchronized Iterator getObjectIterator() { 778 return objectMap.values().iterator(); 779 } 780 781 785 public synchronized boolean hasChanges() { 786 787 791 if (!flattenedInserts.isEmpty() || !flattenedDeletes.isEmpty()) { 792 return true; 793 } 794 795 Iterator it = getObjectIterator(); 796 while (it.hasNext()) { 797 DataObject dataObject = (DataObject) it.next(); 798 int state = dataObject.getPersistenceState(); 799 800 if (state == PersistenceState.MODIFIED) { 801 DataContext context = dataObject.getDataContext(); 802 DataRow committedSnapshot = getSnapshot(dataObject.getObjectId(), context); 803 if (committedSnapshot == null) { 804 return true; 805 } 806 807 DataRow currentSnapshot = context.currentSnapshot(dataObject); 808 809 Iterator currentIt = currentSnapshot.entrySet().iterator(); 810 while (currentIt.hasNext()) { 811 Map.Entry entry = (Map.Entry ) currentIt.next(); 812 Object newValue = entry.getValue(); 813 Object oldValue = committedSnapshot.get(entry.getKey()); 814 if (!Util.nullSafeEquals(oldValue, newValue)) { 815 return true; 816 } 817 } 818 819 Iterator committedIt = committedSnapshot.entrySet().iterator(); 822 while (committedIt.hasNext()) { 823 824 Map.Entry entry = (Map.Entry ) committedIt.next(); 825 826 if (entry.getValue() == null) { 828 continue; 829 } 830 831 if (!currentSnapshot.containsKey(entry.getKey())) { 832 return true; 833 } 834 } 835 } 836 else if (state == PersistenceState.NEW || state == PersistenceState.DELETED) { 837 return true; 838 } 839 } 840 return false; 841 } 842 843 847 public synchronized List objectsInState(int state) { 848 List filteredObjects = new ArrayList (); 849 850 Iterator it = objectMap.values().iterator(); 851 while (it.hasNext()) { 852 DataObject nextObj = (DataObject) it.next(); 853 if (nextObj.getPersistenceState() == state) 854 filteredObjects.add(nextObj); 855 } 856 857 return filteredObjects; 858 } 859 860 871 public void snapshotsChanged(SnapshotEvent event) { 872 if (event.getPostedBy() != this.dataRowCache || event.getSource() == this) { 874 return; 875 } 876 877 if (logObj.isDebugEnabled()) { 879 logObj.debug("Received: " + event); 880 } 881 882 synchronized (this) { 883 processUpdatedSnapshots(event.getModifiedDiffs()); 884 processDeletedIDs(event.getDeletedIds()); 885 processInvalidatedIDs(event.getInvalidatedIds()); 886 processIndirectlyModifiedIDs(event.getIndirectlyModifiedIds()); 887 } 888 } 889 890 897 public synchronized void validateUncommittedObjects() throws ValidationException { 898 899 904 Collection deleted = null; 905 Collection inserted = null; 906 Collection updated = null; 907 908 Iterator allIt = getObjectIterator(); 909 while (allIt.hasNext()) { 910 DataObject dataObject = (DataObject) allIt.next(); 911 switch (dataObject.getPersistenceState()) { 912 case PersistenceState.NEW: 913 if (inserted == null) { 914 inserted = new ArrayList (); 915 } 916 inserted.add(dataObject); 917 break; 918 case PersistenceState.MODIFIED: 919 if (updated == null) { 920 updated = new ArrayList (); 921 } 922 updated.add(dataObject); 923 break; 924 case PersistenceState.DELETED: 925 if (deleted == null) { 926 deleted = new ArrayList (); 927 } 928 deleted.add(dataObject); 929 break; 930 } 931 } 932 933 ValidationResult validationResult = new ValidationResult(); 934 935 if (deleted != null) { 936 Iterator it = deleted.iterator(); 937 while (it.hasNext()) { 938 DataObject dataObject = (DataObject) it.next(); 939 dataObject.validateForDelete(validationResult); 940 } 941 } 942 943 if (inserted != null) { 944 Iterator it = inserted.iterator(); 945 while (it.hasNext()) { 946 DataObject dataObject = (DataObject) it.next(); 947 dataObject.validateForInsert(validationResult); 948 } 949 } 950 951 if (updated != null) { 952 Iterator it = updated.iterator(); 953 while (it.hasNext()) { 954 DataObject dataObject = (DataObject) it.next(); 955 dataObject.validateForUpdate(validationResult); 956 } 957 } 958 959 if (validationResult.hasFailures()) { 960 throw new ValidationException(validationResult); 961 } 962 } 963 964 970 public void resolveHollow(DataObject object) { 971 if (object.getPersistenceState() != PersistenceState.HOLLOW) { 972 return; 973 } 974 975 DataContext context = object.getDataContext(); 977 if (context == null) { 978 object.setPersistenceState(PersistenceState.TRANSIENT); 979 return; 980 } 981 982 synchronized (this) { 983 DataRow snapshot = getSnapshot(object.getObjectId(), context); 984 985 if (snapshot == null) { 987 processDeletedIDs(Collections.singletonList(object.getObjectId())); 988 } 989 else { 990 ObjEntity entity = context.getEntityResolver().lookupObjEntity(object); 991 DataRowUtils.refreshObjectWithSnapshot(entity, object, snapshot, true); 992 993 if (object.getPersistenceState() == PersistenceState.HOLLOW) { 994 object.setPersistenceState(PersistenceState.COMMITTED); 995 } 996 } 997 } 998 } 999 1000 1003 void processDeletedIDs(Collection deletedIDs) { 1004 if (deletedIDs != null && !deletedIDs.isEmpty()) { 1005 Iterator it = deletedIDs.iterator(); 1006 while (it.hasNext()) { 1007 ObjectId oid = (ObjectId) it.next(); 1008 DataObject object = getObject(oid); 1009 1010 if (object == null) { 1011 continue; 1012 } 1013 1014 DataContextDelegate delegate; 1015 1016 1018 switch (object.getPersistenceState()) { 1019 case PersistenceState.COMMITTED: 1020 case PersistenceState.HOLLOW: 1021 case PersistenceState.DELETED: 1022 1023 delegate = object.getDataContext().nonNullDelegate(); 1025 1026 if (delegate.shouldProcessDelete(object)) { 1027 objectMap.remove(oid); 1028 retainedSnapshotMap.remove(oid); 1029 1030 object.setDataContext(null); 1033 delegate.finishedProcessDelete(object); 1034 } 1035 1036 break; 1037 1038 case PersistenceState.MODIFIED: 1039 1040 delegate = object.getDataContext().nonNullDelegate(); 1042 if (delegate.shouldProcessDelete(object)) { 1043 object.setPersistenceState(PersistenceState.NEW); 1044 delegate.finishedProcessDelete(object); 1045 } 1046 1047 break; 1048 } 1049 } 1050 } 1051 } 1052 1053 1056 void processInvalidatedIDs(Collection invalidatedIDs) { 1057 if (invalidatedIDs != null && !invalidatedIDs.isEmpty()) { 1058 Iterator it = invalidatedIDs.iterator(); 1059 while (it.hasNext()) { 1060 ObjectId oid = (ObjectId) it.next(); 1061 DataObject object = getObject(oid); 1062 1063 if (object == null) { 1064 continue; 1065 } 1066 1067 1069 switch (object.getPersistenceState()) { 1070 case PersistenceState.COMMITTED: 1071 object.setPersistenceState(PersistenceState.HOLLOW); 1072 break; 1073 case PersistenceState.MODIFIED: 1074 DataContext context = object.getDataContext(); 1075 DataRow diff = getSnapshot(oid, context); 1076 DataContextDelegate delegate = context.nonNullDelegate(); 1078 if (delegate.shouldMergeChanges(object, diff)) { 1079 ObjEntity entity = context 1080 .getEntityResolver() 1081 .lookupObjEntity(object); 1082 DataRowUtils.forceMergeWithSnapshot(entity, object, diff); 1083 delegate.finishedMergeChanges(object); 1084 } 1085 1086 case PersistenceState.HOLLOW: 1087 break; 1089 1090 case PersistenceState.DELETED: 1091 break; 1093 } 1094 } 1095 } 1096 } 1097 1098 1101 void processIndirectlyModifiedIDs(Collection indirectlyModifiedIDs) { 1102 Iterator indirectlyModifiedIt = indirectlyModifiedIDs.iterator(); 1103 while (indirectlyModifiedIt.hasNext()) { 1104 ObjectId oid = (ObjectId) indirectlyModifiedIt.next(); 1105 1106 DataObject object = getObject(oid); 1107 1108 if (object == null 1109 || object.getPersistenceState() != PersistenceState.COMMITTED) { 1110 continue; 1111 } 1112 1113 1117 DataContextDelegate delegate = object.getDataContext().nonNullDelegate(); 1118 1119 if (delegate.shouldMergeChanges(object, null)) { 1120 ObjEntity entity = object 1121 .getDataContext() 1122 .getEntityResolver() 1123 .lookupObjEntity(object); 1124 Iterator relationshipIterator = entity.getRelationships().iterator(); 1125 while (relationshipIterator.hasNext()) { 1126 ObjRelationship relationship = (ObjRelationship) relationshipIterator 1127 .next(); 1128 1129 if (relationship.isSourceIndependentFromTargetChange()) { 1130 Object fault = relationship.isToMany() 1131 ? Fault.getToManyFault() 1132 : Fault.getToOneFault(); 1133 object.writePropertyDirectly(relationship.getName(), fault); 1134 } 1135 } 1136 1137 delegate.finishedProcessDelete(object); 1138 } 1139 } 1140 } 1141 1142 1145 void processUpdatedSnapshots(Map diffs) { 1146 if (diffs != null && !diffs.isEmpty()) { 1147 Iterator oids = diffs.entrySet().iterator(); 1148 1149 while (oids.hasNext()) { 1150 Map.Entry entry = (Map.Entry ) oids.next(); 1151 1152 ObjectId oid = (ObjectId) entry.getKey(); 1153 DataObject object = getObject(oid); 1154 1155 if (object == null 1157 || object.getPersistenceState() == PersistenceState.HOLLOW) { 1158 continue; 1159 } 1160 1161 DataRow diff = (DataRow) entry.getValue(); 1162 1163 if (object.getPersistenceState() == PersistenceState.COMMITTED) { 1165 DataContextDelegate delegate = object 1167 .getDataContext() 1168 .nonNullDelegate(); 1169 if (delegate.shouldMergeChanges(object, diff)) { 1170 ObjEntity entity = object.getDataContext().getEntityResolver().lookupObjEntity(object); 1171 DataRow snapshot = getSnapshot(object.getObjectId(), object.getDataContext()); 1172 DataRowUtils.refreshObjectWithSnapshot(entity, object, snapshot, true); 1173 delegate.finishedMergeChanges(object); 1174 } 1175 continue; 1176 } 1177 1178 if (object.getPersistenceState() == PersistenceState.DELETED 1180 || object.getPersistenceState() == PersistenceState.MODIFIED) { 1181 1182 DataContextDelegate delegate = object 1184 .getDataContext() 1185 .nonNullDelegate(); 1186 if (delegate.shouldMergeChanges(object, diff)) { 1187 ObjEntity entity = object 1188 .getDataContext() 1189 .getEntityResolver() 1190 .lookupObjEntity(object); 1191 DataRowUtils.forceMergeWithSnapshot(entity, object, diff); 1192 delegate.finishedMergeChanges(object); 1193 } 1194 } 1195 } 1196 } 1197 } 1198 1199 1204 void flattenedRelationshipSet( 1205 DataObject source, 1206 ObjRelationship relationship, 1207 DataObject destination) { 1208 1209 if (!relationship.isFlattened()) { 1210 return; 1211 } 1212 1213 if (relationship.isReadOnly()) { 1214 throw new CayenneRuntimeException( 1215 "Cannot set the read-only flattened relationship " 1216 + relationship.getName()); 1217 } 1218 1219 FlattenedRelationshipUpdate info = new FlattenedRelationshipUpdate( 1222 source, 1223 destination, 1224 relationship); 1225 1226 if (!flattenedDeletes.remove(info) && !flattenedInserts.contains(info)) { 1228 flattenedInserts.add(info); 1229 } 1230 } 1231 1232 1237 void flattenedRelationshipUnset( 1238 DataObject source, 1239 ObjRelationship relationship, 1240 DataObject destination) { 1241 1242 if (!relationship.isFlattened()) { 1243 return; 1244 } 1245 1246 if (relationship.isReadOnly()) { 1247 throw new CayenneRuntimeException( 1248 "Cannot unset the read-only flattened relationship " 1249 + relationship.getName()); 1250 } 1251 1252 FlattenedRelationshipUpdate info = new FlattenedRelationshipUpdate( 1255 source, 1256 destination, 1257 relationship); 1258 1259 if (!flattenedInserts.remove(info) && !flattenedDeletes.contains(info)) { 1262 flattenedDeletes.add(info); 1263 } 1264 } 1265 1266 List getFlattenedInserts() { 1267 return flattenedInserts; 1268 } 1269 1270 List getFlattenedDeletes() { 1271 return flattenedDeletes; 1272 } 1273} | Popular Tags |