{
newObjects.clear();
countNewObjects = 0;
for (int i = 0; i < lockOrder.length; i++)
{
Identity oid = lockOrder[i];
ContextEntry entry = (ContextEntry) _objects.get(oid);
State state = entry.state;
if (entry.userObject == null) // invalidated
{
continue;
}
if (entry.handler == null) // materialized
{
if (!state.isDeleted())
{
Object[][] origFields = (Object[][]) _checkpointed.get(oid);
Object[][] newFields = getFields(entry.userObject, true, !isCommit);
if (origFields == null)
{
entry.needsCacheSwizzle = true;
newObjects.addAll(
handleDependentReferences(oid, entry.userObject,
null, newFields[0], newFields[2]));
newObjects.addAll(
handleDependentCollections(oid, entry.userObject,
null, newFields[1], newFields[3]));
}
else
{
if (isModified(origFields[0], newFields[0]))
{
entry.state = state.markDirty();
entry.needsCacheSwizzle = true;
lockManager.ensureLock(oid, _tx, LockType.WRITE_LOCK, _pb);
newObjects.addAll(
handleDependentReferences(oid, entry.userObject,
origFields[0], newFields[0], newFields[2]));
}
if (isModified(origFields[1], newFields[1]))
{
// there are modified collections,
// so we need to lock the object and to swizzle it to cache
entry.needsCacheSwizzle = true;
lockManager.ensureLock(oid, _tx, LockType.WRITE_LOCK, _pb);
newObjects.addAll(
handleDependentCollections(oid, entry.userObject,
origFields[1], newFields[1], newFields[3]));
changedCollections.add(oid);
}
}
}
}
}
countNewObjects = newObjects.size();
if (countNewObjects > 0)
{
// new objects are not locked, so we don't need to ensure the order
lockOrder = (Identity[]) newObjects.toArray(
new Identity[countNewObjects]);
}
}
while (countNewObjects > 0);
// Swizzle the context objects and the cache objects
for (Iterator it = _order.iterator(); it.hasNext(); )
{
Identity oid = (Identity) it.next();
ContextEntry entry = (ContextEntry) _objects.get(oid);
if (entry.needsCacheSwizzle)
{
entry.userObject = swizzlingStrategy.getRealTarget(entry.userObject);
entry.cacheObject = swizzlingStrategy.swizzle(
// we create the special ObjectCache implememntation
// that returns cacheObject, not userObject
entry.userObject, entry.cacheObject, _pb, new ObjectCache()
{
public Object lookup(Identity anOid)
{
ContextEntry ent = (ContextEntry) _objects.get(anOid);
return (ent == null ? null : ent.cacheObject);
}
public boolean contains(Identity oid)
{
return lookup(oid) != null;
}
public void cache(Identity anOid, Object obj)
{
// do nothing
}
public boolean cacheIfNew(Identity oid, Object obj)
{
return false;
}
public void clear()
{
// do nothing
}
public void remove(Identity anOid)
{
// do nothing
}
});
}
}
// Cascade delete for dependent objects
int countCascadeDeleted;
do
{
countCascadeDeleted = 0;
// Use intermediate new ArrayList(_order) because _order
// may be changed during cascade delete
for (Iterator it = (new ArrayList(_order)).iterator(); it.hasNext(); )
{
Identity oid = (Identity) it.next();
ContextEntry entry = (ContextEntry) _objects.get(oid);
if (entry.state.isDeleted())
{
countCascadeDeleted += doCascadeDelete(oid, entry.userObject);
}
}
}
while (countCascadeDeleted > 0);
// perform database operations
connMan.setBatchMode(true);
try
{
for (Iterator it = _order.iterator(); it.hasNext(); )
{
Identity oid = (Identity) it.next();
ContextEntry entry = (ContextEntry) _objects.get(oid);
State state = entry.state;
if (!state.needsInsert() && !state.needsUpdate()
&& !state.needsDelete())