if (id == null) {
throw new IllegalArgumentException("Null ObjectId");
}
ClassDescriptor descriptor = getEntityResolver().getClassDescriptor(
id.getEntityName());
Persistent cachedObject = (Persistent) getGraphManager().getNode(id);
// merge into an existing object
if (cachedObject != null) {
// TODO: Andrus, 1/24/2006 implement smart merge for modified objects...
if (cachedObject != prototype
&& cachedObject.getPersistenceState() != PersistenceState.MODIFIED
&& cachedObject.getPersistenceState() != PersistenceState.DELETED) {
descriptor.injectValueHolders(cachedObject);
if (prototype != null
&& prototype.getPersistenceState() != PersistenceState.HOLLOW) {
descriptor.shallowMerge(prototype, cachedObject);
if (cachedObject.getPersistenceState() == PersistenceState.HOLLOW) {
cachedObject.setPersistenceState(PersistenceState.COMMITTED);
}
}
}
return cachedObject;
}
// create and merge into a new object
else {
// Andrus, 1/26/2006 - note that there is a tricky case of a temporary object
// passed from peer DataContext... In the past we used to throw an exception
// or return null. Now that we can have a valid (but generally
// indistinguishible) case of such object passed from parent, we let it
// slip... Not sure what's the best way of handling it that does not involve
// breaking encapsulation of the DataChannel to detect where in the hierarchy
// this context is.
Persistent localObject = (Persistent) descriptor.createObject();
localObject.setObjectContext(this);
localObject.setObjectId(id);
getGraphManager().registerNode(id, localObject);
if (prototype != null) {
localObject.setPersistenceState(PersistenceState.COMMITTED);
descriptor.injectValueHolders(localObject);
descriptor.shallowMerge(prototype, localObject);
}
else {
localObject.setPersistenceState(PersistenceState.HOLLOW);
}