throw new NucleusUserException(LOCALISER.msg("056039"));
}
// Make sure that the element is persisted in the datastore (reachability)
final Object newOwner = sm.getObject();
ObjectManager om = sm.getObjectManager();
boolean inserted = validateElementForWriting(sm, element, new FieldValues()
{
public void fetchFields(StateManager esm)
{
// Find the (element) table storing the FK back to the owner
boolean isPersistentInterface = storeMgr.getOMFContext().getMetaDataManager().isPersistentInterface(elementType);
DatastoreClass elementTable = null;
if (isPersistentInterface)
{
elementTable = storeMgr.getDatastoreClass(
storeMgr.getOMFContext().getMetaDataManager().getImplementationNameForPersistentInterface(elementType), clr);
}
else
{
elementTable = storeMgr.getDatastoreClass(elementType, clr);
}
if (elementTable == null)
{
// "subclass-table", persisted into table of other class
AbstractClassMetaData[] managingCmds = storeMgr.getClassesManagingTableForClass(emd, clr);
if (managingCmds != null && managingCmds.length > 0)
{
// Find which of these subclasses is appropriate for this element
for (int i=0;i<managingCmds.length;i++)
{
Class tblCls = clr.classForName(managingCmds[i].getFullClassName());
if (tblCls.isAssignableFrom(esm.getObject().getClass()))
{
elementTable = storeMgr.getDatastoreClass(managingCmds[i].getFullClassName(), clr);
break;
}
}
}
}
if (elementTable != null)
{
JavaTypeMapping externalFKMapping = elementTable.getExternalMapping(ownerMemberMetaData,
MappingConsumer.MAPPING_TYPE_EXTERNAL_FK);
if (externalFKMapping != null)
{
// The element has an external FK mapping so set the value it needs to use in the INSERT
esm.setAssociatedValue(externalFKMapping, sm.getObject());
}
if (relationDiscriminatorMapping != null)
{
// Element type has a shared FK so set the discriminator value for this relation
esm.setAssociatedValue(relationDiscriminatorMapping, relationDiscriminatorValue);
}
}
if (getFieldNumberInElementForBidirectional(esm) >= 0 &&
sm.getObjectManager().getOMFContext().getPersistenceConfiguration().getBooleanProperty("datanucleus.manageRelationships"))
{
// Managed Relations : 1-N bidir, so make sure owner is correct at persist
Object currentOwner = esm.provideField(getFieldNumberInElementForBidirectional(esm));
if (currentOwner == null)
{
// No owner, so correct it
NucleusLogger.JDO.info(LOCALISER.msg("056037",
StringUtils.toJVMIDString(sm.getObject()), ownerMemberMetaData.getFullFieldName(),
StringUtils.toJVMIDString(esm.getObject())));
esm.replaceField(getFieldNumberInElementForBidirectional(esm), newOwner, true);
}
else if (currentOwner != newOwner && sm.getReferencedPC() == null)
{
// Owner of the element is neither this container and not being attached
// Inconsistent owner, so throw exception
throw new NucleusUserException(LOCALISER.msg("056038",
StringUtils.toJVMIDString(sm.getObject()), ownerMemberMetaData.getFullFieldName(),
StringUtils.toJVMIDString(esm.getObject()),
StringUtils.toJVMIDString(currentOwner)));
}
}
}
public void fetchNonLoadedFields(StateManager sm)
{
}
public FetchPlan getFetchPlanForLoading()
{
return null;
}
});
if (inserted)
{
// Element has just been persisted so the FK will be set
return true;
}
else
{
// Element was already persistent so make sure the FK is in place
StateManager elementSM = om.findStateManager(element);
if (getFieldNumberInElementForBidirectional(elementSM) >= 0 &&
om.getOMFContext().getPersistenceConfiguration().getBooleanProperty("datanucleus.manageRelationships"))
{
// Managed Relations : 1-N bidir, so update the owner of the element
om.getApiAdapter().isLoaded(elementSM, getFieldNumberInElementForBidirectional(elementSM)); // Ensure is loaded
Object oldOwner = elementSM.provideField(getFieldNumberInElementForBidirectional(elementSM));
if (oldOwner != newOwner)
{
if (NucleusLogger.PERSISTENCE.isDebugEnabled())
{
NucleusLogger.PERSISTENCE.debug(LOCALISER.msg("055009",
StringUtils.toJVMIDString(sm.getObject()),
ownerMemberMetaData.getFullFieldName(),
StringUtils.toJVMIDString(element)));
}
PersistenceCapable pcElement = (PersistenceCapable) element;
elementSM.setObjectField(pcElement, getFieldNumberInElementForBidirectional(elementSM), oldOwner, newOwner);
if (om.isFlushing())
{
elementSM.flush();
}
}
return oldOwner != newOwner;