// processWhenExisting = false;
// }
}
ExecutionContext ec = attachedOP.getExecutionContext();
ApiAdapter api = ec.getApiAdapter();
if (value == null)
{
Object oldValue = null;
if (mmd.isDependent() && persistent)
{
// Get any old value of this field so we can do cascade-delete if being nulled
try
{
attachedOP.loadFieldFromDatastore(fieldNumber);
}
catch (Exception e)
{
// Error loading the field so didn't exist before attaching anyway
}
oldValue = attachedOP.provideField(fieldNumber);
}
attachedOP.replaceField(fieldNumber, null);
if (dirtyFields[fieldNumber] || !persistent)
{
attachedOP.makeDirty(fieldNumber);
}
if (mmd.isDependent() && !mmd.isEmbedded() &&
oldValue != null && value == null && api.isPersistable(oldValue))
{
// Check for a field storing a PC where it is being nulled and the other object is dependent
attachedOP.flush(); // Flush the nulling of the field
NucleusLogger.PERSISTENCE.debug(LOCALISER.msg("026026", oldValue, mmd.getFullFieldName()));
ec.deleteObjectInternal(oldValue);
}
}
else if (secondClassMutableFields[fieldNumber])
{
if (mmd.isSerialized())
{
// SCO Field is serialised so just update the column with this new value
attachedOP.replaceFieldMakeDirty(fieldNumber, value);
attachedOP.makeDirty(fieldNumber);
}
else
{
// Make sure that the value is a SCO wrapper
Object oldValue = attachedOP.provideField(fieldNumber);
if (oldValue == null && !attachedOP.getLoadedFields()[fieldNumber] && persistent)
{
// Retrieve old value for field
attachedOP.loadField(fieldNumber);
oldValue = attachedOP.provideField(fieldNumber);
}
SCO sco;
if (oldValue == null || (oldValue != null && !(oldValue instanceof SCO)))
{
// Detached object didn't use wrapped field
if (NucleusLogger.PERSISTENCE.isDebugEnabled())
{
NucleusLogger.PERSISTENCE.debug(LOCALISER.msg("026029", StringUtils.toJVMIDString(attachedOP.getObject()),
attachedOP.getInternalObjectId(), mmd.getName()));
}
sco = SCOUtils.newSCOInstance(attachedOP, mmd, mmd.getType(), null, null, false, false, false);
if (sco instanceof SCOContainer)
{
// Load any containers to avoid update issues
((SCOContainer)sco).load();
}
attachedOP.replaceFieldMakeDirty(fieldNumber, sco);
}
else
{
// The field is already a SCO wrapper, so just copy the new values to it
sco = (SCO) oldValue;
}
if (cascadeAttach)
{
// Only trigger the cascade when required
if (copy)
{
// Attach copy of the SCO
sco.attachCopy(value);
}
else
{
// Attach SCO in-situ
// TODO This doesn't seem to handle any removal of things while detached
// Should be changed to do things like in attachCopy above.
if (sco instanceof Collection)
{
// Attach all PC elements of the collection
SCOUtils.attachForCollection(attachedOP, ((Collection)value).toArray(),
SCOUtils.collectionHasElementsWithoutIdentity(mmd));
}
else if (sco instanceof Map)
{
// Attach all PC keys/values of the map
SCOUtils.attachForMap(attachedOP, ((Map)value).entrySet(),
SCOUtils.mapHasKeysWithoutIdentity(mmd),
SCOUtils.mapHasValuesWithoutIdentity(mmd));
}
else
{
// Initialise the SCO with the new value
sco.initialise(value, false, false);
}
}
}
if (dirtyFields[fieldNumber] || !persistent)
{
attachedOP.makeDirty(fieldNumber);
}
}
}
else if (api.isPersistable(value))
{
// Field containing PC object
ObjectProvider valueSM = ec.findObjectProvider(value);
if (valueSM != null && valueSM.getReferencedPC() != null && !api.isPersistent(value))
{
// Value has StateManager and has referenced object so is being attached, so refer to attached PC
attachedOP.replaceFieldMakeDirty(fieldNumber, valueSM.getReferencedPC());
}
if (cascadeAttach)
{
// Determine if field is "second-class" (no identity) - if has "embedded" info or serialised
boolean sco = (mmd.getEmbeddedMetaData() != null || mmd.isSerialized() || mmd.isEmbedded());
if (copy)
{
// Attach copy of the PC
value = ec.attachObjectCopy(attachedOP, value, sco);
attachedOP.replaceFieldMakeDirty(fieldNumber, value);
}
else
{
// Attach PC in-situ
ec.attachObject(attachedOP, value, sco);
}
// Make sure the field is marked as dirty
if (dirtyFields[fieldNumber] || !persistent)
{
attachedOP.makeDirty(fieldNumber);
}
else if (sco && value != null && api.isDirty(value))
{
attachedOP.makeDirty(fieldNumber);
}
}
else if (dirtyFields[fieldNumber] || !persistent)