int lock, boolean canCreate, Identity insertBeforeThis, Stack stack)
throws LockingException
{
ContextEntry entry;
LockManager lockManager;
Swizzling swizzlingStrategy;
IndirectionHandler handler = null;
OTMKit kit = _tx.getKit();
// Are we building object's relations for the userObject in the transaction?
// Otherwise we just get data from the "userObject" and put it into
// the previously loaded/created object in the transaction
boolean buildingObject = false;
boolean lazySwizzle = false;
if (lock == LockType.NO_LOCK)
{
return null;
}
entry = (ContextEntry) _objects.get(oid);
if (userObject == null)
{
// invalidating object...
_original.remove(oid);
_checkpointed.remove(oid);
if (entry != null)
{
entry.userObject = null;
entry.cacheObject = null;
}
return entry;
}
lockManager = LockManager.getInstance();
swizzlingStrategy = kit.getSwizzlingStrategy();
handler = ProxyHelper.getIndirectionHandler(userObject);
if ((handler != null) && handler.alreadyMaterialized())
{
userObject = handler.getRealSubject();
handler = null;
}
if ((entry == null) || (entry.userObject == null))
{
// first insertion of the userObject into editing context
Object swizzledObject = swizzlingStrategy.swizzle(userObject, null, _pb, this);
entry = new ContextEntry(swizzledObject);
if (entry.handler != null)
{
ObjectCopyStrategy copyStrategy = _tx.getKit().getCopyStrategy(oid);
entry.cacheObject = copyStrategy.copy(userObject, _pb);
// Assume that object exists, otherwise were the proxy came from?
_objects.put(oid, entry);
lockManager.ensureLock(oid, _tx, lock, _pb); // lock after _objects.put to avoid hanged locks
entry.handler.addListener(this);
}
else
{
Object origCacheObj = _pb.getObjectByIdentity(oid);
if ((origCacheObj == null) && !canCreate)
{
// we don't create the objects by reachability
throw new IllegalStateException("Related object is neither persistent, nor otm-depentent: " + oid);
}
if (origCacheObj != null)
{
entry.cacheObject = origCacheObj;
}
buildingObject = true;
_objects.put(oid, entry);
lockManager.ensureLock(oid, _tx, lock, _pb); // lock after _objects.put to avoid hanged locks
if (userObject != null)
{
if ((origCacheObj == null) && canCreate)
{
ObjectCopyStrategy copyStrategy = _tx.getKit().getCopyStrategy(oid);
entry.cacheObject = copyStrategy.copy(userObject, _pb);
entry.state = State.PERSISTENT_NEW;
if (kit.isEagerInsert(userObject)
|| hasBidirectionalAssociation(userObject.getClass()))
{
_pb.store(entry.cacheObject, entry.state);
entry.state = State.PERSISTENT_CLEAN;
origCacheObj = entry.cacheObject;
}
}
if (origCacheObj != null)
{
_original.put(oid, getFields(userObject, false, true));
}
}
}
if (insertBeforeThis != null)
{
int insertIndex = _order.indexOf(insertBeforeThis);
_order.add(insertIndex, oid);
}
else
{
_order.add(oid);
}
}
else
{
// The object in context is the same object attempted an insert on
// Ensure we have the correct lock level
lockManager.ensureLock(oid, _tx, lock, _pb);
if (handler == null)
{
if (!swizzlingStrategy.isSameInstance(entry.userObject, userObject))
{
// the new object contains data to deal with
if (entry.handler != null)
{
// materialize old object even if it is not
// materialized yet, because we need a place
// to copy the data from the new object
entry.userObject = entry.handler.getRealSubject();
entry.handler = null;
}
// swizzle after lockReachableObjects(), when all related objects
// will be in the editing context
lazySwizzle = true;
}
}
}
// perform automatic read lock for all reachable objects
// if the inserted object is materialized
if ((handler == null) && !stack.contains(userObject))
{
stack.push(userObject);
lockReachableObjects(oid, userObject, entry.cacheObject, lock, stack, buildingObject);
stack.pop();
if (lazySwizzle)
{
entry.userObject = swizzlingStrategy.swizzle(userObject, entry.userObject, _pb, this);
}
}
return entry;
}