1 56 57 package org.objectstyle.cayenne.access; 58 59 import java.io.IOException ; 60 import java.io.ObjectInputStream ; 61 import java.io.ObjectOutputStream ; 62 import java.io.Serializable ; 63 import java.util.ArrayList ; 64 import java.util.Collection ; 65 import java.util.Collections ; 66 import java.util.HashMap ; 67 import java.util.Iterator ; 68 import java.util.List ; 69 import java.util.Map ; 70 71 import org.apache.log4j.Level; 72 import org.objectstyle.cayenne.CayenneException; 73 import org.objectstyle.cayenne.CayenneRuntimeException; 74 import org.objectstyle.cayenne.DataObject; 75 import org.objectstyle.cayenne.DataRow; 76 import org.objectstyle.cayenne.Fault; 77 import org.objectstyle.cayenne.ObjectId; 78 import org.objectstyle.cayenne.PersistenceState; 79 import org.objectstyle.cayenne.TempObjectId; 80 import org.objectstyle.cayenne.access.event.DataContextEvent; 81 import org.objectstyle.cayenne.access.util.IteratedSelectObserver; 82 import org.objectstyle.cayenne.access.util.PrefetchHelper; 83 import org.objectstyle.cayenne.access.util.QueryUtils; 84 import org.objectstyle.cayenne.conf.Configuration; 85 import org.objectstyle.cayenne.event.EventManager; 86 import org.objectstyle.cayenne.event.EventSubject; 87 import org.objectstyle.cayenne.map.DataMap; 88 import org.objectstyle.cayenne.map.DbJoin; 89 import org.objectstyle.cayenne.map.DbRelationship; 90 import org.objectstyle.cayenne.map.Entity; 91 import org.objectstyle.cayenne.map.EntityResolver; 92 import org.objectstyle.cayenne.map.ObjAttribute; 93 import org.objectstyle.cayenne.map.ObjEntity; 94 import org.objectstyle.cayenne.map.ObjRelationship; 95 import org.objectstyle.cayenne.query.GenericSelectQuery; 96 import org.objectstyle.cayenne.query.ParameterizedQuery; 97 import org.objectstyle.cayenne.query.Query; 98 import org.objectstyle.cayenne.query.SelectQuery; 99 import org.objectstyle.cayenne.util.Util; 100 101 128 public class DataContext implements QueryEngine, Serializable { 129 130 private static final DataContextDelegate defaultDelegate = new DataContextDelegate() { 132 133 public GenericSelectQuery willPerformSelect( 134 DataContext context, 135 GenericSelectQuery query) { 136 return query; 137 } 138 139 public boolean shouldMergeChanges(DataObject object, DataRow snapshotInStore) { 140 return true; 141 } 142 143 public boolean shouldProcessDelete(DataObject object) { 144 return true; 145 } 146 147 public void finishedMergeChanges(DataObject object) { 148 149 } 150 151 public void finishedProcessDelete(DataObject object) { 152 153 } 154 }; 155 156 public static final EventSubject WILL_COMMIT = EventSubject.getSubject( 158 DataContext.class, 159 "DataContextWillCommit"); 160 public static final EventSubject DID_COMMIT = EventSubject.getSubject( 161 DataContext.class, 162 "DataContextDidCommit"); 163 public static final EventSubject DID_ROLLBACK = EventSubject.getSubject( 164 DataContext.class, 165 "DataContextDidRollback"); 166 167 168 169 174 protected static final ThreadLocal threadDataContext = new ThreadLocal (); 175 176 private static boolean transactionEventsEnabledDefault; 178 179 private boolean transactionEventsEnabled; 181 182 private DataContextDelegate delegate; 184 185 protected boolean usingSharedSnaphsotCache; 186 protected boolean validatingObjectsOnCommit; 187 protected ObjectStore objectStore; 188 189 protected transient QueryEngine parent; 190 191 196 protected Map userProperties; 197 198 204 protected transient String lazyInitParentDomainName; 205 206 210 private static final DataObject newDataObject(String className) throws Exception { 211 return (DataObject) Configuration 212 .getResourceLoader() 213 .loadClass(className) 214 .newInstance(); 215 } 216 217 226 public static DataContext getThreadDataContext() throws IllegalStateException { 227 DataContext dc = (DataContext) threadDataContext.get(); 228 if (dc == null) { 229 throw new IllegalStateException ("Current thread has no bound DataContext."); 230 } 231 232 return dc; 233 } 234 235 242 public static void bindThreadDataContext(DataContext context) { 243 threadDataContext.set(context); 244 } 245 246 252 public static DataContext createDataContext() { 253 return Configuration.getSharedConfiguration().getDomain().createDataContext(); 254 } 255 256 265 public static DataContext createDataContext(boolean useSharedCache) { 266 return Configuration.getSharedConfiguration().getDomain().createDataContext( 267 useSharedCache); 268 } 269 270 275 public static DataContext createDataContext(String domainName) { 276 DataDomain domain = Configuration.getSharedConfiguration().getDomain(domainName); 277 if (domain == null) { 278 throw new IllegalArgumentException ("Non-existent domain: " + domainName); 279 } 280 return domain.createDataContext(); 281 } 282 283 291 public static DataContext createDataContext(String domainName, boolean useSharedCache) { 292 293 DataDomain domain = Configuration.getSharedConfiguration().getDomain(domainName); 294 if (domain == null) { 295 throw new IllegalArgumentException ("Non-existent domain: " + domainName); 296 } 297 return domain.createDataContext(useSharedCache); 298 } 299 300 304 public DataContext() { 305 this(null, null); 306 } 307 308 316 public DataContext(QueryEngine parent, ObjectStore objectStore) { 317 setParent(parent); 318 319 this.objectStore = objectStore; 320 this.setTransactionEventsEnabled(transactionEventsEnabledDefault); 321 this.usingSharedSnaphsotCache = getParentDataDomain() != null 322 && objectStore.getDataRowCache() == getParentDataDomain() 323 .getSharedSnapshotCache(); 324 } 325 326 329 private final void awakeFromDeserialization() { 330 if (parent == null && lazyInitParentDomainName != null) { 331 332 DataDomain domain = Configuration.getSharedConfiguration().getDomain( 333 lazyInitParentDomainName); 334 335 this.parent = domain; 336 337 if (isUsingSharedSnapshotCache() && domain != null) { 338 this.objectStore.setDataRowCache(domain.getSharedSnapshotCache()); 339 } 340 } 341 } 342 343 348 protected Map getUserProperties() { 349 if (userProperties == null) { 353 userProperties = new HashMap (); 354 } 355 356 return userProperties; 357 } 358 359 365 public Object getUserProperty(String key) { 366 return getUserProperties().get(key); 367 } 368 369 375 public void setUserProperty(String key, Object value) { 376 getUserProperties().put(key, value); 377 } 378 379 380 384 public QueryEngine getParent() { 385 awakeFromDeserialization(); 386 return parent; 387 } 388 389 398 public DataDomain getParentDataDomain() { 399 return (DataDomain) getParent(); 400 } 401 402 405 public void setParent(QueryEngine parent) { 406 this.parent = parent; 407 } 408 409 415 public void setDelegate(DataContextDelegate delegate) { 416 this.delegate = delegate; 417 } 418 419 424 public DataContextDelegate getDelegate() { 425 return delegate; 426 } 427 428 434 DataContextDelegate nonNullDelegate() { 435 return (delegate != null) ? delegate : DataContext.defaultDelegate; 436 } 437 438 441 public ObjectStore getObjectStore() { 442 awakeFromDeserialization(); 443 return objectStore; 444 } 445 446 450 public boolean hasChanges() { 451 return getObjectStore().hasChanges(); 452 } 453 454 458 public Collection newObjects() { 459 return getObjectStore().objectsInState(PersistenceState.NEW); 460 } 461 462 466 public Collection deletedObjects() { 467 return getObjectStore().objectsInState(PersistenceState.DELETED); 468 } 469 470 474 public Collection modifiedObjects() { 475 return getObjectStore().objectsInState(PersistenceState.MODIFIED); 476 } 477 478 483 public DataObject registeredObject(ObjectId oid) { 484 synchronized (getObjectStore()) { 486 DataObject obj = objectStore.getObject(oid); 487 if (obj == null) { 488 try { 489 obj = DataContext.newDataObject(oid.getObjectClass().getName()); 491 } 492 catch (Exception ex) { 493 String entity = (oid != null) ? getEntityResolver().lookupObjEntity( 494 oid.getObjectClass()).getName() : null; 495 throw new CayenneRuntimeException( 496 "Error creating object for entity '" + entity + "'.", 497 ex); 498 } 499 500 obj.setObjectId(oid); 501 obj.setPersistenceState(PersistenceState.HOLLOW); 502 obj.setDataContext(this); 503 objectStore.addObject(obj); 504 } 505 return obj; 506 } 507 } 508 509 514 public DataRow currentSnapshot(DataObject anObject) { 515 ObjEntity entity = getEntityResolver().lookupObjEntity(anObject); 516 517 if (anObject.getPersistenceState() == PersistenceState.HOLLOW 519 && anObject.getDataContext() != null) { 520 521 ObjectId id = anObject.getObjectId(); 522 return getObjectStore().getSnapshot(id, this); 523 } 524 525 DataRow snapshot = new DataRow(10); 526 527 Iterator attributes = entity.getAttributeMap().entrySet().iterator(); 528 while (attributes.hasNext()) { 529 Map.Entry entry = (Map.Entry ) attributes.next(); 530 String attrName = (String ) entry.getKey(); 531 ObjAttribute objAttr = (ObjAttribute) entry.getValue(); 532 533 snapshot.put(objAttr.getDbAttributePath(), anObject 535 .readPropertyDirectly(attrName)); 536 } 537 538 Iterator relationships = entity.getRelationshipMap().entrySet().iterator(); 539 while (relationships.hasNext()) { 540 Map.Entry entry = (Map.Entry ) relationships.next(); 541 ObjRelationship rel = (ObjRelationship) entry.getValue(); 542 543 if (rel.isSourceIndependentFromTargetChange()) { 545 continue; 546 } 547 548 Object targetObject = anObject.readPropertyDirectly(rel.getName()); 549 if (targetObject == null) { 550 continue; 551 } 552 553 if (targetObject instanceof Fault) { 556 DataRow storedSnapshot = getObjectStore().getSnapshot( 557 anObject.getObjectId(), 558 this); 559 if (storedSnapshot == null) { 560 throw new CayenneRuntimeException( 561 "No matching objects found for ObjectId " 562 + anObject.getObjectId() 563 + ". Object may have been deleted externally."); 564 } 565 566 DbRelationship dbRel = (DbRelationship) rel.getDbRelationships().get(0); 567 Iterator joins = dbRel.getJoins().iterator(); 568 while (joins.hasNext()) { 569 DbJoin join = (DbJoin) joins.next(); 570 String key = join.getSourceName(); 571 snapshot.put(key, storedSnapshot.get(key)); 572 } 573 574 continue; 575 } 576 577 DataObject target = (DataObject) targetObject; 580 Map idParts = target.getObjectId().getIdSnapshot(); 581 582 if (idParts.isEmpty()) { 584 continue; 585 } 586 587 DbRelationship dbRel = (DbRelationship) rel.getDbRelationships().get(0); 588 Map fk = dbRel.srcFkSnapshotWithTargetSnapshot(idParts); 589 snapshot.putAll(fk); 590 } 591 592 Map thisIdParts = anObject.getObjectId().getIdSnapshot(); 597 if (thisIdParts != null) { 598 599 Iterator idIterator = thisIdParts.entrySet().iterator(); 601 while (idIterator.hasNext()) { 602 Map.Entry entry = (Map.Entry ) idIterator.next(); 603 Object nextKey = entry.getKey(); 604 if (!snapshot.containsKey(nextKey)) { 605 snapshot.put(nextKey, entry.getValue()); 606 } 607 } 608 } 609 610 return snapshot; 611 } 612 613 620 public List localObjects(List objects) { 621 List localObjects = new ArrayList (objects.size()); 622 623 Iterator it = objects.iterator(); 624 while (it.hasNext()) { 625 DataObject object = (DataObject) it.next(); 626 627 if (object.getPersistenceState() != PersistenceState.COMMITTED 629 && object.getPersistenceState() != PersistenceState.HOLLOW) { 630 throw new CayenneRuntimeException( 631 "Only COMMITTED and HOLLOW objects can be transferred between contexts. " 632 + "Invalid object state '" 633 + PersistenceState.persistenceStateName(object 634 .getPersistenceState()) 635 + "', ObjectId: " 636 + object.getObjectId()); 637 } 638 639 DataObject localObject = (object.getDataContext() != this) 640 ? registeredObject(object.getObjectId()) 641 : object; 642 localObjects.add(localObject); 643 } 644 645 return localObjects; 646 } 647 648 653 public List objectsFromDataRows( 654 ObjEntity entity, 655 List dataRows, 656 boolean refresh, 657 boolean resolveInheritanceHierarchy) { 658 659 return new DataContextObjectFactory(this, refresh, resolveInheritanceHierarchy) 660 .objectsFromDataRows(entity, dataRows); 661 } 662 663 672 public List objectsFromDataRows( 673 Class objectClass, 674 List dataRows, 675 boolean refresh, 676 boolean resolveInheritanceHierarchy) { 677 ObjEntity entity = this.getEntityResolver().lookupObjEntity(objectClass); 678 return objectsFromDataRows(entity, dataRows, refresh, resolveInheritanceHierarchy); 679 } 680 681 688 public DataObject objectFromDataRow( 689 Class objectClass, 690 DataRow dataRow, 691 boolean refresh) { 692 List list = objectsFromDataRows( 693 objectClass, 694 Collections.singletonList(dataRow), 695 refresh, 696 true); 697 return (DataObject) list.get(0); 698 } 699 700 701 712 public DataObject createAndRegisterNewObject(String objEntityName) { 713 ObjEntity entity = this.getEntityResolver().getObjEntity(objEntityName); 714 715 if (entity == null) { 716 throw new IllegalArgumentException ("Invalid entity name: " + objEntityName); 717 } 718 719 String objClassName = entity.getClassName(); 720 DataObject dataObject = null; 721 try { 722 dataObject = DataContext.newDataObject(objClassName); 723 } 724 catch (Exception ex) { 725 throw new CayenneRuntimeException("Error instantiating object.", ex); 726 } 727 728 registerNewObjectWithEntity(dataObject, entity); 729 return dataObject; 730 } 731 732 738 public DataObject createAndRegisterNewObject(Class objectClass) { 739 if (objectClass == null) { 740 throw new NullPointerException ("DataObject class can't be null."); 741 } 742 743 ObjEntity entity = getEntityResolver().lookupObjEntity(objectClass); 744 if (entity == null) { 745 throw new IllegalArgumentException ("Class is not mapped with Cayenne: " 746 + objectClass.getName()); 747 } 748 749 DataObject dataObject = null; 750 try { 751 dataObject = (DataObject) objectClass.newInstance(); 752 } 753 catch (Exception ex) { 754 throw new CayenneRuntimeException("Error instantiating object.", ex); 755 } 756 757 registerNewObjectWithEntity(dataObject, entity); 758 return dataObject; 759 } 760 761 762 767 public void registerNewObject(DataObject dataObject) { 768 if (dataObject == null) { 769 throw new NullPointerException ("Can't register null object."); 770 } 771 772 if (dataObject.getObjectId() != null) { 774 if (dataObject.getDataContext() == this) { 775 return; 777 } 778 else if (dataObject.getDataContext() != null) { 779 throw new IllegalStateException ( 780 "DataObject is already registered with another DataContext. Try using 'localObjects()' instead."); 781 } 782 } 783 784 ObjEntity entity = getEntityResolver().lookupObjEntity(dataObject); 785 if (entity == null) { 786 throw new IllegalArgumentException ( 787 "Can't find ObjEntity for DataObject class: " 788 + dataObject.getClass().getName() 789 + ", class is likely not mapped."); 790 } 791 792 registerNewObjectWithEntity(dataObject, entity); 793 } 794 795 private void registerNewObjectWithEntity(DataObject dataObject, ObjEntity objEntity) { 796 799 if (dataObject.getObjectId() == null) { 800 dataObject.setObjectId(new TempObjectId(dataObject.getClass())); 801 } 802 803 Iterator it = objEntity.getRelationships().iterator(); 805 while (it.hasNext()) { 806 ObjRelationship rel = (ObjRelationship) it.next(); 807 if (rel.isToMany()) { 808 dataObject.writePropertyDirectly(rel.getName(), Fault.getToManyFault()); 809 } 810 } 811 812 getObjectStore().addObject(dataObject); 813 dataObject.setDataContext(this); 814 dataObject.setPersistenceState(PersistenceState.NEW); 815 } 816 817 822 public void unregisterObjects(Collection dataObjects) { 823 getObjectStore().objectsUnregistered(dataObjects); 824 } 825 826 831 public void invalidateObjects(Collection dataObjects) { 832 getObjectStore().objectsInvalidated(dataObjects); 833 } 834 835 849 public void deleteObjects(Collection objects) { 850 if (objects.isEmpty()) { 851 return; 852 } 853 854 Iterator it = new ArrayList (objects).iterator(); 857 while (it.hasNext()) { 858 DataObject object = (DataObject) it.next(); 859 deleteObject(object); 860 } 861 } 862 863 873 public void deleteObject(DataObject object) throws DeleteDenyException { 874 new DataContextDeleteAction(this).performDelete(object); 875 } 876 877 885 public DataObject refetchObject(ObjectId oid) { 886 887 if (oid == null) { 888 throw new NullPointerException ("Null ObjectId"); 889 } 890 891 if (oid.isTemporary()) { 892 throw new CayenneRuntimeException("Can't refetch ObjectId " 893 + oid 894 + ", as it is a temporary id."); 895 } 896 897 synchronized (getObjectStore()) { 898 DataObject object = objectStore.getObject(oid); 899 900 if (object != null) { 902 this.invalidateObjects(Collections.singleton(object)); 903 } 904 } 905 906 SelectQuery sel = QueryUtils.selectObjectForId(oid); 907 List results = this.performQuery(sel); 908 909 if (results.size() != 1) { 910 String msg = (results.size() == 0) 911 ? "Refetch failure: no matching objects found for ObjectId " + oid 912 : "Refetch failure: more than 1 object found for ObjectId " 913 + oid 914 + ". Fetch matched " 915 + results.size() 916 + " objects."; 917 918 throw new CayenneRuntimeException(msg); 919 } 920 921 return (DataObject) results.get(0); 922 } 923 924 929 public DataNode lookupDataNode(DataMap dataMap) { 930 if (this.getParent() == null) { 931 throw new CayenneRuntimeException("Cannot use a DataContext without a parent"); 932 } 933 return this.getParent().lookupDataNode(dataMap); 934 } 935 936 939 public void rollbackChanges() { 940 getObjectStore().objectsRolledBack(); 941 } 942 943 947 public void commitChanges() throws CayenneRuntimeException { 948 commitChanges(null); 949 } 950 951 958 public void commitChanges(Level logLevel) throws CayenneRuntimeException { 959 960 if (this.getParent() == null) { 961 throw new CayenneRuntimeException("Cannot use a DataContext without a parent"); 962 } 963 964 synchronized (getObjectStore()) { 966 if (!this.hasChanges()) { 968 return; 969 } 970 971 if (isValidatingObjectsOnCommit()) { 972 getObjectStore().validateUncommittedObjects(); 973 } 974 975 DataContextCommitAction worker = new DataContextCommitAction(this); 976 977 try { 978 worker.commit(logLevel); 979 } 980 catch (CayenneException ex) { 981 Throwable unwound = Util.unwindException(ex); 982 983 if (unwound instanceof CayenneRuntimeException) { 984 throw (CayenneRuntimeException) unwound; 985 } 986 else { 987 throw new CayenneRuntimeException("Commit Exception", unwound); 988 } 989 } 990 } 991 } 992 993 999 public int[] performNonSelectingQuery(Query query) { 1000 QueryResult result = new QueryResult(); 1001 performQueries(Collections.singletonList(query), result); 1002 List updateCounts = result.getUpdates(query); 1003 1004 if (updateCounts == null || updateCounts.isEmpty()) { 1005 return new int[0]; 1006 } 1007 1008 int len = updateCounts.size(); 1009 int[] counts = new int[len]; 1010 1011 for (int i = 0; i < len; i++) { 1012 counts[i] = ((Number ) updateCounts.get(i)).intValue(); 1013 } 1014 1015 return counts; 1016 } 1017 1018 1024 public int[] performNonSelectingQuery(String queryName) { 1025 return performNonSelectingQuery(queryName, Collections.EMPTY_MAP); 1026 } 1027 1028 1034 public int[] performNonSelectingQuery(String queryName, Map parameters) { 1035 Query query = getEntityResolver().getQuery(queryName); 1037 if (query == null) { 1038 throw new CayenneRuntimeException("There is no saved query for name '" 1039 + queryName 1040 + "'."); 1041 } 1042 1043 if (parameters != null 1044 && !parameters.isEmpty() 1045 && query instanceof ParameterizedQuery) { 1046 query = ((ParameterizedQuery) query).createQuery(parameters); 1047 } 1048 1049 return performNonSelectingQuery(query); 1050 } 1051 1052 1056 public ResultIterator performIteratedQuery(GenericSelectQuery query) 1057 throws CayenneException { 1058 1059 IteratedSelectObserver observer = new IteratedSelectObserver(); 1060 observer.setLoggingLevel(query.getLoggingLevel()); 1061 performQueries(Collections.singletonList(query), observer); 1062 return observer.getResultIterator(); 1063 } 1064 1065 1070 public void performQueries(Collection queries, OperationObserver observer) { 1071 Transaction transaction = (observer.isIteratedResult()) 1074 ? Transaction.externalTransaction(getParentDataDomain() 1075 .getTransactionDelegate()) 1076 : getParentDataDomain().createTransaction(); 1077 1078 transaction.performQueries(this, queries, observer); 1079 } 1080 1081 1086 public void performQueries( 1087 Collection queries, 1088 OperationObserver resultConsumer, 1089 Transaction transaction) { 1090 1091 if (this.getParent() == null) { 1092 throw new CayenneRuntimeException("Cannot use a DataContext without a parent"); 1093 } 1094 1095 DataContextDelegate localDelegate = nonNullDelegate(); 1096 List finalQueries = new ArrayList (queries.size()); 1097 1098 Iterator it = queries.iterator(); 1099 while (it.hasNext()) { 1100 Object query = it.next(); 1101 1102 if (query instanceof GenericSelectQuery) { 1103 GenericSelectQuery genericSelect = (GenericSelectQuery) query; 1104 1105 GenericSelectQuery filteredSelect = localDelegate.willPerformSelect( 1107 this, 1108 genericSelect); 1109 1110 if (filteredSelect != null) { 1112 finalQueries.add(filteredSelect); 1113 } 1114 } 1115 else { 1116 finalQueries.add(query); 1117 } 1118 } 1119 1120 this.getParent().performQueries(finalQueries, resultConsumer, transaction); 1121 } 1122 1123 1132 public void prefetchRelationships(SelectQuery query, List objects) { 1133 Collection prefetches = query.getPrefetches(); 1134 1135 if (objects == null || objects.size() == 0 || prefetches.size() == 0) { 1136 return; 1137 } 1138 1139 ObjEntity entity = getEntityResolver().lookupObjEntity(query); 1140 Iterator prefetchesIt = prefetches.iterator(); 1141 while (prefetchesIt.hasNext()) { 1142 String prefetchKey = (String ) prefetchesIt.next(); 1143 if (prefetchKey.indexOf(Entity.PATH_SEPARATOR) >= 0) { 1144 throw new CayenneRuntimeException("Only one-step relationships are " 1145 + "supported at the moment, this will be fixed soon. " 1146 + "Unsupported path : " 1147 + prefetchKey); 1148 } 1149 1150 ObjRelationship relationship = (ObjRelationship) entity 1151 .getRelationship(prefetchKey); 1152 if (relationship == null) { 1153 throw new CayenneRuntimeException("Invalid relationship: " + prefetchKey); 1154 } 1155 1156 if (relationship.isToMany()) { 1157 throw new CayenneRuntimeException( 1158 "Only to-one relationships are supported at the moment. " 1159 + "Can't prefetch to-many: " 1160 + prefetchKey); 1161 } 1162 1163 PrefetchHelper.resolveToOneRelations(this, objects, prefetchKey); 1164 } 1165 1166 } 1167 1168 1186 public List performQuery(GenericSelectQuery query) { 1187 return new DataContextSelectAction(this).performQuery(query); 1188 } 1189 1190 1202 public List performQuery(String queryName, boolean refresh) { 1203 return performQuery(queryName, Collections.EMPTY_MAP, refresh); 1204 } 1205 1206 1219 public List performQuery(String queryName, Map parameters, boolean refresh) { 1220 Query query = getEntityResolver().getQuery(queryName); 1222 if (query == null) { 1223 throw new CayenneRuntimeException("There is no saved query for name '" 1224 + queryName 1225 + "'."); 1226 } 1227 1228 1233 1237 if (query instanceof SelectQuery) { 1238 SelectQuery select = (SelectQuery) query; 1239 if (select.getQualifier() != null) { 1240 query = select.createQuery(parameters != null 1241 ? parameters 1242 : Collections.EMPTY_MAP); 1243 } 1244 } 1245 else if (parameters != null 1246 && !parameters.isEmpty() 1247 && query instanceof ParameterizedQuery) { 1248 query = ((ParameterizedQuery) query).createQuery(parameters); 1249 } 1250 1251 if (!(query instanceof GenericSelectQuery)) { 1252 throw new CayenneRuntimeException("Query for name '" 1253 + queryName 1254 + "' is not a GenericSelectQuery: " 1255 + query); 1256 } 1257 1258 return new DataContextSelectAction(this).performQuery((GenericSelectQuery) query, query 1259 .getName(), refresh); 1260 } 1261 1262 1263 1264 private void writeObject(ObjectOutputStream out) throws IOException { 1266 out.defaultWriteObject(); 1267 1268 1274 if (this.parent == null && this.lazyInitParentDomainName != null) { 1275 out.writeObject(lazyInitParentDomainName); 1276 } 1277 else if (this.parent instanceof DataDomain) { 1278 DataDomain domain = (DataDomain) this.parent; 1279 out.writeObject(domain.getName()); 1280 } 1281 else { 1282 out.writeObject(this.parent); 1284 } 1285 1286 if (!isUsingSharedSnapshotCache()) { 1288 out.writeObject(objectStore.getDataRowCache()); 1289 } 1290 } 1291 1292 private void readObject(ObjectInputStream in) throws IOException , 1294 ClassNotFoundException { 1295 1296 in.defaultReadObject(); 1298 1299 Object value = in.readObject(); 1301 if (value instanceof QueryEngine) { 1302 this.parent = (QueryEngine) value; 1304 } 1305 else if (value instanceof String ) { 1306 this.lazyInitParentDomainName = (String ) value; 1308 } 1309 else { 1310 throw new CayenneRuntimeException( 1311 "Parent attribute of DataContext was neither a QueryEngine nor " 1312 + "the name of a valid DataDomain:" 1313 + value); 1314 } 1315 1316 if (!isUsingSharedSnapshotCache()) { 1318 DataRowStore cache = (DataRowStore) in.readObject(); 1319 objectStore.setDataRowCache(cache); 1320 } 1321 1322 1329 synchronized (getObjectStore()) { 1330 Iterator it = objectStore.getObjectIterator(); 1331 while (it.hasNext()) { 1332 DataObject object = (DataObject) it.next(); 1333 object.setDataContext(this); 1334 } 1335 } 1336 } 1337 1338 1341 public EntityResolver getEntityResolver() { 1342 if (this.getParent() == null) { 1343 throw new CayenneRuntimeException("Cannot use a DataContext without a parent"); 1344 } 1345 return this.getParent().getEntityResolver(); 1346 } 1347 1348 1351 public static void setTransactionEventsEnabledDefault(boolean flag) { 1352 transactionEventsEnabledDefault = flag; 1353 } 1354 1355 1358 public void setTransactionEventsEnabled(boolean flag) { 1359 this.transactionEventsEnabled = flag; 1360 } 1361 1362 public boolean isTransactionEventsEnabled() { 1363 return this.transactionEventsEnabled; 1364 } 1365 1366 1372 public boolean isUsingSharedSnapshotCache() { 1373 return usingSharedSnaphsotCache; 1374 } 1375 1376 1382 public boolean isValidatingObjectsOnCommit() { 1383 return validatingObjectsOnCommit; 1384 } 1385 1386 1392 public void setValidatingObjectsOnCommit(boolean flag) { 1393 this.validatingObjectsOnCommit = flag; 1394 } 1395 1396 public Collection getDataMaps() { 1397 return (parent != null) ? parent.getDataMaps() : Collections.EMPTY_LIST; 1398 } 1399 1400 void fireWillCommit() { 1401 if (this.transactionEventsEnabled) { 1403 EventManager eventMgr = EventManager.getDefaultManager(); 1404 DataContextEvent commitChangesEvent = new DataContextEvent(this); 1405 eventMgr.postEvent(commitChangesEvent, DataContext.WILL_COMMIT); 1406 } 1407 } 1408 1409 void fireTransactionRolledback() { 1410 if ((this.transactionEventsEnabled)) { 1412 EventManager eventMgr = EventManager.getDefaultManager(); 1413 DataContextEvent commitChangesEvent = new DataContextEvent(this); 1414 eventMgr.postEvent(commitChangesEvent, DataContext.DID_ROLLBACK); 1415 } 1416 } 1417 1418 void fireTransactionCommitted() { 1419 if ((this.transactionEventsEnabled)) { 1421 EventManager eventMgr = EventManager.getDefaultManager(); 1422 DataContextEvent commitChangesEvent = new DataContextEvent(this); 1423 eventMgr.postEvent(commitChangesEvent, DataContext.DID_COMMIT); 1424 } 1425 } 1426} | Popular Tags |