}
// note that per-object ClassDescriptor lookup is needed as even if all
// objects where fetched as a part of the same query, as they may belong to
// different subclasses
ClassDescriptor descriptor = getEntityResolver().getClassDescriptor(
id.getEntityName());
// have to synchronize almost the entire method to prevent multiple threads from
// messing up dataobjects per CAY-845. Originally only parts of "else" were
// synchronized, but we had to expand the lock scope to ensure consistent
// behavior.
synchronized (getGraphManager()) {
Persistent cachedObject = (Persistent) getGraphManager().getNode(id);
// merge into an existing object
if (cachedObject != null) {
int state = cachedObject.getPersistenceState();
// TODO: Andrus, 1/24/2006 implement smart merge for modified objects...
if (cachedObject != prototype
&& state != PersistenceState.MODIFIED
&& state != PersistenceState.DELETED) {
descriptor.injectValueHolders(cachedObject);
if (prototype != null
&& ((Persistent) prototype).getPersistenceState() != PersistenceState.HOLLOW) {
descriptor.shallowMerge(prototype, cachedObject);
if (state == PersistenceState.HOLLOW) {
cachedObject.setPersistenceState(PersistenceState.COMMITTED);
}
}
}
return cachedObject;
}
// create and merge into a new object
else {
Persistent localObject;
localObject = (Persistent) descriptor.createObject();
localObject.setObjectContext(this);
localObject.setObjectId(id);
getGraphManager().registerNode(id, localObject);
if (prototype != null
&& ((Persistent) prototype).getPersistenceState() != PersistenceState.HOLLOW) {
localObject.setPersistenceState(PersistenceState.COMMITTED);
descriptor.injectValueHolders(localObject);
descriptor.shallowMerge(prototype, localObject);
}
else {
localObject.setPersistenceState(PersistenceState.HOLLOW);
}