use of org.datanucleus.store.types.SCOCollection in project datanucleus-rdbms by datanucleus.
the class PersistableMapping method postInsert.
/**
* Method executed just after the insert of the owning object, allowing any necessary action
* to this field and the object stored in it.
* @param op ObjectProvider for the owner
*/
public void postInsert(ObjectProvider op) {
Object pc = op.provideField(mmd.getAbsoluteFieldNumber());
TypeManager typeManager = op.getExecutionContext().getTypeManager();
pc = mmd.isSingleCollection() ? singleCollectionValue(typeManager, pc) : pc;
if (pc == null) {
// Has been set to null so nothing to do
return;
}
ClassLoaderResolver clr = op.getExecutionContext().getClassLoaderResolver();
AbstractMemberMetaData[] relatedMmds = mmd.getRelatedMemberMetaData(clr);
RelationType relationType = mmd.getRelationType(clr);
if (relationType == RelationType.ONE_TO_ONE_BI) {
ObjectProvider otherOP = op.getExecutionContext().findObjectProvider(pc);
if (otherOP == null) {
return;
}
AbstractMemberMetaData relatedMmd = mmd.getRelatedMemberMetaDataForObject(clr, op.getObject(), pc);
if (relatedMmd == null) {
// Fsck knows why
throw new NucleusUserException("You have a field " + mmd.getFullFieldName() + " that is 1-1 bidir yet cannot find the equivalent field at the other side. Why is that?");
}
Object relatedValue = otherOP.provideField(relatedMmd.getAbsoluteFieldNumber());
relatedValue = relatedMmd.isSingleCollection() ? singleCollectionValue(typeManager, relatedValue) : relatedValue;
if (relatedValue == null) {
// Managed Relations : Other side not set so update it in memory
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("041018", op.getObjectAsPrintable(), mmd.getFullFieldName(), StringUtils.toJVMIDString(pc), relatedMmd.getFullFieldName()));
}
Object replaceValue = op.getObject();
if (relatedMmd.isSingleCollection()) {
ElementContainerHandler containerHandler = typeManager.getContainerHandler(relatedMmd.getType());
replaceValue = containerHandler.newContainer(relatedMmd, op.getObject());
}
otherOP.replaceField(relatedMmd.getAbsoluteFieldNumber(), replaceValue);
} else if (relatedValue != op.getObject()) {
// Managed Relations : Other side is inconsistent so throw exception
throw new NucleusUserException(Localiser.msg("041020", op.getObjectAsPrintable(), mmd.getFullFieldName(), StringUtils.toJVMIDString(pc), StringUtils.toJVMIDString(relatedValue)));
}
} else if (relationType == RelationType.MANY_TO_ONE_BI && relatedMmds[0].hasCollection()) {
// TODO Make sure we have this PC in the collection at the other side
ObjectProvider otherOP = op.getExecutionContext().findObjectProvider(pc);
if (otherOP != null) {
// Managed Relations : add to the collection on the other side
Collection relatedColl = (Collection) otherOP.provideField(relatedMmds[0].getAbsoluteFieldNumber());
if (relatedColl != null && !(relatedColl instanceof SCOCollection)) {
// TODO Make sure the collection is a wrapper
boolean contained = relatedColl.contains(op.getObject());
if (!contained) {
NucleusLogger.PERSISTENCE.info(Localiser.msg("041022", op.getObjectAsPrintable(), mmd.getFullFieldName(), StringUtils.toJVMIDString(pc), relatedMmds[0].getFullFieldName()));
// TODO Enable this. Currently causes issues with PMImplTest, InheritanceStrategyTest, TCK "inheritance1.conf"
/*relatedColl.add(op.getObject());*/
}
}
}
} else if (relationType == RelationType.MANY_TO_ONE_UNI) {
ObjectProvider otherOP = op.getExecutionContext().findObjectProvider(pc);
if (otherOP == null) {
// Related object is not yet persisted so persist it
Object other = op.getExecutionContext().persistObjectInternal(pc, null, -1, ObjectProvider.PC);
otherOP = op.getExecutionContext().findObjectProvider(other);
}
// Add join table entry
PersistableRelationStore store = (PersistableRelationStore) storeMgr.getBackingStoreForField(clr, mmd, mmd.getType());
store.add(op, otherOP);
}
}
use of org.datanucleus.store.types.SCOCollection in project datanucleus-rdbms by datanucleus.
the class PersistableMapping method postInsert.
/**
* Method executed just after the insert of the owning object, allowing any necessary action
* to this field and the object stored in it.
* @param sm StateManager for the owner
*/
public void postInsert(DNStateManager sm) {
Object pc = sm.provideField(mmd.getAbsoluteFieldNumber());
TypeManager typeManager = sm.getExecutionContext().getTypeManager();
pc = mmd.isSingleCollection() ? singleCollectionValue(typeManager, pc) : pc;
if (pc == null) {
// Has been set to null so nothing to do
return;
}
ClassLoaderResolver clr = sm.getExecutionContext().getClassLoaderResolver();
AbstractMemberMetaData[] relatedMmds = mmd.getRelatedMemberMetaData(clr);
RelationType relationType = mmd.getRelationType(clr);
if (relationType == RelationType.ONE_TO_ONE_BI) {
DNStateManager otherSM = sm.getExecutionContext().findStateManager(pc);
if (otherSM == null) {
return;
}
AbstractMemberMetaData relatedMmd = mmd.getRelatedMemberMetaDataForObject(clr, sm.getObject(), pc);
if (relatedMmd == null) {
// Fsck knows why
throw new NucleusUserException("You have a field " + mmd.getFullFieldName() + " that is 1-1 bidir yet cannot find the equivalent field at the other side. Why is that?");
}
Object relatedValue = otherSM.provideField(relatedMmd.getAbsoluteFieldNumber());
relatedValue = relatedMmd.isSingleCollection() ? singleCollectionValue(typeManager, relatedValue) : relatedValue;
if (relatedValue == null) {
// Managed Relations : Other side not set so update it in memory
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("041018", sm.getObjectAsPrintable(), mmd.getFullFieldName(), StringUtils.toJVMIDString(pc), relatedMmd.getFullFieldName()));
}
Object replaceValue = sm.getObject();
if (relatedMmd.isSingleCollection()) {
ElementContainerHandler containerHandler = typeManager.getContainerHandler(relatedMmd.getType());
replaceValue = containerHandler.newContainer(relatedMmd, sm.getObject());
}
otherSM.replaceField(relatedMmd.getAbsoluteFieldNumber(), replaceValue);
} else if (relatedValue != sm.getObject()) {
// Managed Relations : Other side is inconsistent so throw exception
throw new NucleusUserException(Localiser.msg("041020", sm.getObjectAsPrintable(), mmd.getFullFieldName(), StringUtils.toJVMIDString(pc), StringUtils.toJVMIDString(relatedValue)));
}
} else if (relationType == RelationType.MANY_TO_ONE_BI && relatedMmds[0].hasCollection()) {
// TODO Make sure we have this PC in the collection at the other side
DNStateManager otherSM = sm.getExecutionContext().findStateManager(pc);
if (otherSM != null) {
// Managed Relations : add to the collection on the other side
Collection relatedColl = (Collection) otherSM.provideField(relatedMmds[0].getAbsoluteFieldNumber());
if (relatedColl != null && !(relatedColl instanceof SCOCollection)) {
// TODO Make sure the collection is a wrapper
boolean contained = relatedColl.contains(sm.getObject());
if (!contained) {
NucleusLogger.PERSISTENCE.info(Localiser.msg("041022", sm.getObjectAsPrintable(), mmd.getFullFieldName(), StringUtils.toJVMIDString(pc), relatedMmds[0].getFullFieldName()));
// TODO Enable this. Currently causes issues with PMImplTest, InheritanceStrategyTest, TCK "inheritance1.conf"
/*relatedColl.add(op.getObject());*/
}
}
}
} else if (relationType == RelationType.MANY_TO_ONE_UNI) {
DNStateManager otherSM = sm.getExecutionContext().findStateManager(pc);
if (otherSM == null) {
// Related object is not yet persisted so persist it
Object other = sm.getExecutionContext().persistObjectInternal(pc, null, -1, PersistableObjectType.PC);
otherSM = sm.getExecutionContext().findStateManager(other);
}
// Add join table entry
PersistableRelationStore store = (PersistableRelationStore) storeMgr.getBackingStoreForField(clr, mmd, mmd.getType());
store.add(sm, otherSM);
}
}
use of org.datanucleus.store.types.SCOCollection in project datanucleus-core by datanucleus.
the class RelationshipManagerImpl method processManyToOneBidirectionalRelation.
/**
* Method to process all N-1 bidirectional fields.
* Processes the case where we had an N-1 field set at this side previously to some value and now to
* some other value.That is, this object was in some collection/map originally, and now should be in some
* other collection/map. So in terms of an example this object "a" was in collection "b1.as" before and is
* now in "b2.as". The following changes are likely to be necessary
* <ul>
* <li>b1.getAs().remove(a) - remove it from b1.as if still present</li>
* <li>b2.getAs().add(a) - add it to b1.as if not present</li>
* </ul>
* @param mmd MetaData for the field
* @param clr ClassLoader resolver
* @param ec ExecutionContext
* @param changes List of changes to the collection
*/
protected void processManyToOneBidirectionalRelation(AbstractMemberMetaData mmd, ClassLoaderResolver clr, ExecutionContext ec, List<RelationChange> changes) {
for (RelationChange change : changes) {
if (change.type == ChangeType.CHANGE_OBJECT) {
Object oldValue = change.oldValue;
// TODO Use change.value
Object newValue = ownerOP.provideField(mmd.getAbsoluteFieldNumber());
if (oldValue != null) {
// Has been removed from a Collection/Map
AbstractMemberMetaData relatedMmd = mmd.getRelatedMemberMetaDataForObject(clr, pc, oldValue);
ObjectProvider oldOP = ec.findObjectProvider(oldValue);
if (oldOP != null && relatedMmd != null && oldOP.getLoadedFields()[relatedMmd.getAbsoluteFieldNumber()]) {
if (oldOP.isFieldLoaded(relatedMmd.getAbsoluteFieldNumber())) {
Object oldContainerValue = oldOP.provideField(relatedMmd.getAbsoluteFieldNumber());
if (oldContainerValue instanceof Collection) {
Collection oldColl = (Collection) oldContainerValue;
if (oldColl.contains(pc)) {
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("013006", StringUtils.toJVMIDString(pc), mmd.getFullFieldName(), relatedMmd.getFullFieldName(), StringUtils.toJVMIDString(oldValue)));
}
if (oldColl instanceof SCOCollection) {
// Avoid any cascade deletes that could have been fired by this action
((SCOCollection) oldColl).remove(pc, false);
} else {
oldColl.remove(pc);
}
}
}
}
} else {
if (oldOP != null) {
ec.removeObjectFromLevel2Cache(oldOP.getInternalObjectId());
}
}
}
if (newValue != null) {
// Add new value to the Collection
AbstractMemberMetaData relatedMmd = mmd.getRelatedMemberMetaDataForObject(clr, pc, newValue);
ObjectProvider newOP = ec.findObjectProvider(newValue);
if (newOP != null && relatedMmd != null && newOP.getLoadedFields()[relatedMmd.getAbsoluteFieldNumber()]) {
Object newContainerValue = newOP.provideField(relatedMmd.getAbsoluteFieldNumber());
if (newContainerValue instanceof Collection) {
Collection newColl = (Collection) newContainerValue;
if (!newColl.contains(pc)) {
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("013007", StringUtils.toJVMIDString(pc), mmd.getFullFieldName(), relatedMmd.getFullFieldName(), StringUtils.toJVMIDString(newValue)));
}
newColl.add(pc);
}
}
} else {
// Relation field not loaded so evict it from the L2 cache to avoid loading old field values
ec.removeObjectFromLevel2Cache(ec.getApiAdapter().getIdForObject(newValue));
}
}
}
}
}
use of org.datanucleus.store.types.SCOCollection in project datanucleus-core by datanucleus.
the class StateManagerImpl method replaceField.
/**
* Method to change the value of a field in the PC object.
* Adds on handling for embedded fields to the superclass handler.
* @param pc The PC object
* @param fieldNumber Number of field
* @param value The new value of the field
* @param makeDirty Whether to make the field dirty while replacing its value (in embedded owners)
*/
protected void replaceField(Persistable pc, int fieldNumber, Object value, boolean makeDirty) {
List<EmbeddedOwnerRelation> embeddedOwners = myEC.getOwnerInformationForEmbedded(this);
if (embeddedOwners != null) {
// We do this before we actually change the object so we can compare with the old value
for (EmbeddedOwnerRelation ownerRel : embeddedOwners) {
StateManagerImpl ownerOP = (StateManagerImpl) ownerRel.getOwnerOP();
AbstractMemberMetaData ownerMmd = ownerOP.getClassMetaData().getMetaDataForManagedMemberAtAbsolutePosition(ownerRel.getOwnerFieldNum());
if (ownerMmd.getCollection() != null) {
// PC Object embedded in collection
Object ownerField = ownerOP.provideField(ownerRel.getOwnerFieldNum());
if (ownerField instanceof SCOCollection) {
((SCOCollection) ownerField).updateEmbeddedElement(myPC, fieldNumber, value, makeDirty);
}
if ((ownerOP.flags & FLAG_UPDATING_EMBEDDING_FIELDS_WITH_OWNER) == 0) {
// Update the owner when one of our fields have changed, EXCEPT when they have just notified us of our owner field!
if (makeDirty) {
ownerOP.makeDirty(ownerRel.getOwnerFieldNum());
}
}
} else if (ownerMmd.getMap() != null) {
// PC Object embedded in map
Object ownerField = ownerOP.provideField(ownerRel.getOwnerFieldNum());
if (ownerField instanceof SCOMap) {
if (objectType == ObjectProvider.EMBEDDED_MAP_KEY_PC) {
((SCOMap) ownerField).updateEmbeddedKey(myPC, fieldNumber, value, makeDirty);
}
if (objectType == ObjectProvider.EMBEDDED_MAP_VALUE_PC) {
((SCOMap) ownerField).updateEmbeddedValue(myPC, fieldNumber, value, makeDirty);
}
}
if ((ownerOP.flags & FLAG_UPDATING_EMBEDDING_FIELDS_WITH_OWNER) == 0) {
// Update the owner when one of our fields have changed, EXCEPT when they have just notified us of our owner field!
if (makeDirty) {
ownerOP.makeDirty(ownerRel.getOwnerFieldNum());
}
}
} else {
// PC Object embedded in PC object
if ((ownerOP.flags & FLAG_UPDATING_EMBEDDING_FIELDS_WITH_OWNER) == 0) {
// Update the owner when one of our fields have changed, EXCEPT when they have just notified us of our owner field!
if (makeDirty) {
ownerOP.replaceFieldMakeDirty(ownerRel.getOwnerFieldNum(), pc);
} else {
ownerOP.replaceField(ownerRel.getOwnerFieldNum(), pc);
}
}
}
}
}
// TODO Why don't we mark as dirty if non-tx ? Maybe need P_NONTRANS_DIRTY
if (embeddedOwners == null && makeDirty && !myLC.isDeleted() && myEC.getTransaction().isActive()) {
// Mark dirty (if not being deleted)
boolean wasDirty = preWriteField(fieldNumber);
replaceField(pc, fieldNumber, value);
postWriteField(wasDirty);
} else {
replaceField(pc, fieldNumber, value);
}
}
use of org.datanucleus.store.types.SCOCollection in project datanucleus-core by datanucleus.
the class SortedSet method initialise.
public void initialise(java.util.SortedSet<E> newValue, Object oldValue) {
if (newValue != null) {
// Check for the case of serialised PC elements, and assign ObjectProviders to the elements without
if (SCOUtils.collectionHasSerialisedElements(ownerMmd) && ownerMmd.getCollection().elementIsPersistent()) {
ExecutionContext ec = ownerOP.getExecutionContext();
Iterator iter = newValue.iterator();
while (iter.hasNext()) {
Object pc = iter.next();
ObjectProvider objSM = ec.findObjectProvider(pc);
if (objSM == null) {
objSM = ec.getNucleusContext().getObjectProviderFactory().newForEmbedded(ec, pc, false, ownerOP, ownerMmd.getAbsoluteFieldNumber());
}
}
}
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("023008", ownerOP.getObjectAsPrintable(), ownerMmd.getName(), "" + newValue.size()));
}
// Detect which objects are added and which are deleted
initialising = true;
if (useCache) {
Collection oldColl = (Collection) oldValue;
if (oldColl != null) {
delegate.addAll(oldColl);
}
isCacheLoaded = true;
SCOUtils.updateCollectionWithCollection(ownerOP.getExecutionContext().getApiAdapter(), this, newValue);
} else {
java.util.Collection oldColl = (java.util.Collection) oldValue;
if (oldColl instanceof SCOCollection) {
oldColl = (java.util.Collection) ((SCOCollection) oldColl).getValue();
}
for (E elem : newValue) {
if (oldColl == null || !oldColl.contains(elem)) {
add(elem);
}
}
if (oldColl != null) {
Iterator iter = oldColl.iterator();
while (iter.hasNext()) {
Object elem = iter.next();
if (!newValue.contains(elem)) {
remove(elem);
}
}
}
}
initialising = false;
}
}
Aggregations