Search in sources :

Example 1 with SCOCollection

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);
    }
}
Also used : NucleusUserException(org.datanucleus.exceptions.NucleusUserException) RelationType(org.datanucleus.metadata.RelationType) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) TypeManager(org.datanucleus.store.types.TypeManager) Collection(java.util.Collection) SCOCollection(org.datanucleus.store.types.SCOCollection) SCOCollection(org.datanucleus.store.types.SCOCollection) ObjectProvider(org.datanucleus.state.ObjectProvider) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) ElementContainerHandler(org.datanucleus.store.types.ElementContainerHandler) PersistableRelationStore(org.datanucleus.store.types.scostore.PersistableRelationStore)

Example 2 with SCOCollection

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);
    }
}
Also used : NucleusUserException(org.datanucleus.exceptions.NucleusUserException) RelationType(org.datanucleus.metadata.RelationType) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) TypeManager(org.datanucleus.store.types.TypeManager) Collection(java.util.Collection) SCOCollection(org.datanucleus.store.types.SCOCollection) SCOCollection(org.datanucleus.store.types.SCOCollection) DNStateManager(org.datanucleus.state.DNStateManager) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) ElementContainerHandler(org.datanucleus.store.types.containers.ElementContainerHandler) PersistableRelationStore(org.datanucleus.store.types.scostore.PersistableRelationStore)

Example 3 with SCOCollection

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));
                }
            }
        }
    }
}
Also used : Collection(java.util.Collection) SCOCollection(org.datanucleus.store.types.SCOCollection) SCOCollection(org.datanucleus.store.types.SCOCollection) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 4 with SCOCollection

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);
    }
}
Also used : EmbeddedOwnerRelation(org.datanucleus.ExecutionContext.EmbeddedOwnerRelation) SCOCollection(org.datanucleus.store.types.SCOCollection) SCOMap(org.datanucleus.store.types.SCOMap) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 5 with SCOCollection

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;
    }
}
Also used : ExecutionContext(org.datanucleus.ExecutionContext) Collection(java.util.Collection) Iterator(java.util.Iterator) SCOCollectionIterator(org.datanucleus.store.types.SCOCollectionIterator) Collection(java.util.Collection) SCOCollection(org.datanucleus.store.types.SCOCollection) SCOCollection(org.datanucleus.store.types.SCOCollection) ObjectProvider(org.datanucleus.state.ObjectProvider)

Aggregations

SCOCollection (org.datanucleus.store.types.SCOCollection)10 Collection (java.util.Collection)8 ObjectProvider (org.datanucleus.state.ObjectProvider)7 Iterator (java.util.Iterator)6 ExecutionContext (org.datanucleus.ExecutionContext)6 SCOCollectionIterator (org.datanucleus.store.types.SCOCollectionIterator)6 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)4 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)2 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)2 RelationType (org.datanucleus.metadata.RelationType)2 TypeManager (org.datanucleus.store.types.TypeManager)2 PersistableRelationStore (org.datanucleus.store.types.scostore.PersistableRelationStore)2 Set (java.util.Set)1 EmbeddedOwnerRelation (org.datanucleus.ExecutionContext.EmbeddedOwnerRelation)1 NucleusDataStoreException (org.datanucleus.exceptions.NucleusDataStoreException)1 CollectionAddOperation (org.datanucleus.flush.CollectionAddOperation)1 CollectionClearOperation (org.datanucleus.flush.CollectionClearOperation)1 DNStateManager (org.datanucleus.state.DNStateManager)1 ElementContainerHandler (org.datanucleus.store.types.ElementContainerHandler)1 SCOMap (org.datanucleus.store.types.SCOMap)1