1 19 20 package org.apache.cayenne; 21 22 import java.util.ArrayList ; 23 import java.util.Collection ; 24 import java.util.Iterator ; 25 import java.util.List ; 26 27 import org.apache.cayenne.cache.MapQueryCache; 28 import org.apache.cayenne.cache.QueryCache; 29 import org.apache.cayenne.event.EventManager; 30 import org.apache.cayenne.graph.GraphDiff; 31 import org.apache.cayenne.graph.GraphManager; 32 import org.apache.cayenne.map.EntityResolver; 33 import org.apache.cayenne.map.ObjEntity; 34 import org.apache.cayenne.query.Query; 35 import org.apache.cayenne.reflect.ClassDescriptor; 36 import org.apache.cayenne.util.EventUtil; 37 import org.apache.cayenne.validation.ValidationException; 38 import org.apache.cayenne.validation.ValidationResult; 39 40 48 public class CayenneContext extends BaseContext { 49 50 protected EntityResolver entityResolver; 51 52 CayenneContextGraphManager graphManager; 53 54 CayenneContextGraphAction graphAction; 59 60 CayenneContextMergeHandler mergeHandler; 62 63 QueryCache queryCache; 64 65 68 public CayenneContext() { 69 this(null); 70 } 71 72 77 public CayenneContext(DataChannel channel) { 78 this(channel, false, false); 79 } 80 81 86 public CayenneContext(DataChannel channel, boolean changeEventsEnabled, 87 boolean syncEventsEnabled) { 88 89 this.graphAction = new CayenneContextGraphAction(this); 90 this.graphManager = new CayenneContextGraphManager( 91 this, 92 changeEventsEnabled, 93 syncEventsEnabled); 94 95 setChannel(channel); 96 } 97 98 103 QueryCache getQueryCache() { 104 105 if (queryCache == null) { 106 synchronized (this) { 107 if (queryCache == null) { 108 queryCache = new MapQueryCache(); 111 } 112 } 113 } 114 115 return queryCache; 116 } 117 118 121 public void setChannel(DataChannel channel) { 122 if (this.channel != channel) { 123 124 if (this.mergeHandler != null) { 125 this.mergeHandler.active = false; 126 this.mergeHandler = null; 127 } 128 129 this.channel = channel; 130 131 EventManager eventManager = (channel != null) 132 ? channel.getEventManager() 133 : null; 134 if (eventManager != null) { 135 this.mergeHandler = new CayenneContextMergeHandler(this); 136 137 EventUtil.listenForChannelEvents(channel, mergeHandler); 141 } 142 } 143 } 144 145 149 public boolean isChangeEventsEnabled() { 150 return graphManager.changeEventsEnabled; 151 } 152 153 159 public boolean isLifecycleEventsEnabled() { 160 return graphManager.lifecycleEventsEnabled; 161 } 162 163 168 public EntityResolver getEntityResolver() { 169 if (entityResolver == null) { 171 synchronized (this) { 172 if (entityResolver == null) { 173 setEntityResolver(channel.getEntityResolver()); 174 } 175 } 176 } 177 178 return entityResolver; 179 } 180 181 public void setEntityResolver(EntityResolver entityResolver) { 182 this.entityResolver = entityResolver; 183 } 184 185 public GraphManager getGraphManager() { 186 return graphManager; 187 } 188 189 CayenneContextGraphManager internalGraphManager() { 190 return graphManager; 191 } 192 193 CayenneContextGraphAction internalGraphAction() { 194 return graphAction; 195 } 196 197 202 public void commitChanges() { 203 doCommitChanges(true); 204 } 205 206 GraphDiff doCommitChanges(boolean cascade) { 207 208 int syncType = cascade 209 ? DataChannel.FLUSH_CASCADE_SYNC 210 : DataChannel.FLUSH_NOCASCADE_SYNC; 211 212 GraphDiff commitDiff = null; 213 214 synchronized (graphManager) { 215 216 if (graphManager.hasChanges()) { 217 218 ValidationResult result = new ValidationResult(); 219 Iterator it = graphManager.dirtyNodes().iterator(); 220 while (it.hasNext()) { 221 Persistent p = (Persistent) it.next(); 222 if (p instanceof Validating) { 223 switch (p.getPersistenceState()) { 224 case PersistenceState.NEW: 225 ((Validating) p).validateForInsert(result); 226 break; 227 case PersistenceState.MODIFIED: 228 ((Validating) p).validateForUpdate(result); 229 break; 230 case PersistenceState.DELETED: 231 ((Validating) p).validateForDelete(result); 232 break; 233 } 234 } 235 } 236 237 if (result.hasFailures()) { 238 throw new ValidationException(result); 239 } 240 241 graphManager.graphCommitStarted(); 242 243 try { 244 commitDiff = channel.onSync(this, graphManager 245 .getDiffsSinceLastFlush(), syncType); 246 } 247 catch (Throwable th) { 248 graphManager.graphCommitAborted(); 249 250 if (th instanceof CayenneRuntimeException) { 251 throw (CayenneRuntimeException) th; 252 } 253 else { 254 throw new CayenneRuntimeException("Commit error", th); 255 } 256 } 257 258 graphManager.graphCommitted(commitDiff); 259 } 260 } 261 262 return commitDiff; 263 } 264 265 public void commitChangesToParent() { 266 doCommitChanges(false); 267 } 268 269 public void rollbackChanges() { 270 synchronized (graphManager) { 271 if (graphManager.hasChanges()) { 272 273 GraphDiff diff = graphManager.getDiffs(); 274 graphManager.graphReverted(); 275 276 channel.onSync(this, diff, DataChannel.ROLLBACK_CASCADE_SYNC); 277 } 278 } 279 } 280 281 public void rollbackChangesLocally() { 282 synchronized (graphManager) { 283 if (graphManager.hasChanges()) { 284 graphManager.graphReverted(); 285 } 286 } 287 } 288 289 293 public void deleteObject(Object object) { 294 new ObjectContextDeleteAction(this).performDelete((Persistent) object); 295 } 296 297 300 public Persistent newObject(Class persistentClass) { 301 if (persistentClass == null) { 302 throw new NullPointerException ("Persistent class can't be null."); 303 } 304 305 ObjEntity entity = getEntityResolver().lookupObjEntity(persistentClass); 306 if (entity == null) { 307 throw new CayenneRuntimeException("No entity mapped for class: " 308 + persistentClass); 309 } 310 311 ClassDescriptor descriptor = getEntityResolver().getClassDescriptor( 312 entity.getName()); 313 Persistent object = (Persistent) descriptor.createObject(); 314 registerNewObject(object, entity.getName(), descriptor); 315 return object; 316 } 317 318 321 public void registerNewObject(Object object) { 322 if (object == null) { 323 throw new NullPointerException ("An attempt to register null object."); 324 } 325 326 ObjEntity entity = getEntityResolver().lookupObjEntity(object.getClass()); 327 ClassDescriptor descriptor = getEntityResolver().getClassDescriptor( 328 entity.getName()); 329 registerNewObject((Persistent) object, entity.getName(), descriptor); 330 } 331 332 335 public List performQuery(Query query) { 336 List result = onQuery(this, query).firstList(); 337 return result != null ? result : new ArrayList (1); 338 } 339 340 public QueryResponse performGenericQuery(Query query) { 341 return onQuery(this, query); 342 } 343 344 QueryResponse onQuery(ObjectContext context, Query query) { 347 return new CayenneContextQueryAction(this, context, query).execute(); 348 } 349 350 358 public Persistent localObject(ObjectId id, Object prototype) { 359 360 363 365 if (id == null) { 366 throw new IllegalArgumentException ("Null ObjectId"); 367 } 368 369 ClassDescriptor descriptor = getEntityResolver().getClassDescriptor( 370 id.getEntityName()); 371 372 Persistent cachedObject = (Persistent) getGraphManager().getNode(id); 373 374 if (cachedObject != null) { 376 377 if (cachedObject != prototype 379 && cachedObject.getPersistenceState() != PersistenceState.MODIFIED 380 && cachedObject.getPersistenceState() != PersistenceState.DELETED) { 381 382 if (prototype != null 383 && ((Persistent) prototype).getPersistenceState() != PersistenceState.HOLLOW) { 384 385 descriptor.shallowMerge(prototype, cachedObject); 386 387 if (cachedObject.getPersistenceState() == PersistenceState.HOLLOW) { 388 cachedObject.setPersistenceState(PersistenceState.COMMITTED); 389 } 390 } 391 } 392 393 return cachedObject; 394 } 395 else { 397 398 406 Persistent localObject; 407 synchronized (getGraphManager()) { 408 localObject = (Persistent) descriptor.createObject(); 409 410 localObject.setObjectContext(this); 411 localObject.setObjectId(id); 412 413 getGraphManager().registerNode(id, localObject); 414 } 415 416 if (prototype != null) { 417 localObject.setPersistenceState(PersistenceState.COMMITTED); 418 descriptor.shallowMerge(prototype, localObject); 419 } 420 else { 421 localObject.setPersistenceState(PersistenceState.HOLLOW); 422 } 423 424 return localObject; 425 } 426 427 } 429 430 public void propertyChanged( 431 Persistent object, 432 String property, 433 Object oldValue, 434 Object newValue) { 435 436 graphAction.handlePropertyChange(object, property, oldValue, newValue); 437 } 438 439 public Collection uncommittedObjects() { 440 synchronized (graphManager) { 441 return graphManager.dirtyNodes(); 442 } 443 } 444 445 public Collection deletedObjects() { 446 synchronized (graphManager) { 447 return graphManager.dirtyNodes(PersistenceState.DELETED); 448 } 449 } 450 451 public Collection modifiedObjects() { 452 synchronized (graphManager) { 453 return graphManager.dirtyNodes(PersistenceState.MODIFIED); 454 } 455 } 456 457 public Collection newObjects() { 458 synchronized (graphManager) { 459 return graphManager.dirtyNodes(PersistenceState.NEW); 460 } 461 } 462 463 465 void registerNewObject( 466 Persistent object, 467 String entityName, 468 ClassDescriptor descriptor) { 469 ObjectId id = new ObjectId(entityName); 470 471 object.setObjectId(id); 474 object.setObjectContext(this); 475 object.setPersistenceState(PersistenceState.NEW); 476 477 synchronized (graphManager) { 478 graphManager.registerNode(object.getObjectId(), object); 479 graphManager.nodeCreated(object.getObjectId()); 480 } 481 } 482 483 Persistent createFault(ObjectId id) { 484 ClassDescriptor descriptor = getEntityResolver().getClassDescriptor( 485 id.getEntityName()); 486 487 Persistent object; 488 synchronized (graphManager) { 489 object = (Persistent) descriptor.createObject(); 490 491 object.setPersistenceState(PersistenceState.HOLLOW); 492 object.setObjectContext(this); 493 object.setObjectId(id); 494 495 graphManager.registerNode(id, object); 496 } 497 498 return object; 499 } 500 } 501 | Popular Tags |