use of org.datanucleus.enhancement.Persistable in project datanucleus-core by datanucleus.
the class StateManagerImpl method initialiseForEmbedded.
/**
* Initialises a state manager to manage a Persistable instance that will be EMBEDDED/SERIALISED into another Persistable object.
* The instance will not be assigned an identity in the process since it is a SCO.
* @param pc The Persistable to manage (see copyPc also)
* @param copyPc Whether the SM should manage a copy of the passed PC or that one
*/
public void initialiseForEmbedded(Persistable pc, boolean copyPc) {
// Default to an embedded PC object
objectType = ObjectProvider.EMBEDDED_PC;
// It is embedded at this point so dont need an ID since we're not persisting it
myID = null;
myLC = myEC.getNucleusContext().getApiAdapter().getLifeCycleState(LifeCycleState.P_CLEAN);
persistenceFlags = Persistable.LOAD_REQUIRED;
myPC = pc;
// Set SM for embedded PC to be this
replaceStateManager(myPC, this);
if (copyPc) {
// Create a new PC with the same field values
Persistable pcCopy = myPC.dnNewInstance(this);
pcCopy.dnCopyFields(myPC, cmd.getAllMemberPositions());
// Swap the managed PC to be the copy and not the input
replaceStateManager(pcCopy, this);
myPC = pcCopy;
disconnectClone(pc);
}
// Mark all fields as loaded since we are using the passed Persistable
for (int i = 0; i < loadedFields.length; i++) {
loadedFields[i] = true;
}
}
use of org.datanucleus.enhancement.Persistable in project datanucleus-core by datanucleus.
the class StateManagerImpl method detachCopy.
/**
* Method to make detached copy of this instance
* If the object is detachable then the copy will be migrated to DETACHED state, otherwise will migrate
* the copy to TRANSIENT. Used by "ExecutionContext.detachObjectCopy()".
* @param state State for the detachment process
* @return the detached Persistable instance
*/
public Persistable detachCopy(FetchPlanState state) {
if (myLC.isDeleted()) {
throw new NucleusUserException(Localiser.msg("026023", myPC.getClass().getName(), myID));
}
if (myEC.getApiAdapter().isDetached(myPC)) {
throw new NucleusUserException(Localiser.msg("026024", myPC.getClass().getName(), myID));
}
if (dirty) {
myEC.flushInternal(false);
}
if (isDetaching()) {
// Object in the process of detaching (recursive) so return the object which will be the detached object
return getReferencedPC();
}
// Look for an existing detached copy
DetachState detachState = (DetachState) state;
DetachState.Entry existingDetached = detachState.getDetachedCopyEntry(myPC);
Persistable detachedPC;
if (existingDetached == null) {
// No existing detached copy - create new one
detachedPC = myPC.dnNewInstance(this);
detachState.setDetachedCopyEntry(myPC, detachedPC);
} else {
// Found one - if it's sufficient for current FetchPlanState, return it immediately
detachedPC = (Persistable) existingDetached.getDetachedCopyObject();
if (existingDetached.checkCurrentState()) {
return detachedPC;
}
// Need to process the detached copy using current FetchPlanState
}
myEC.setAttachDetachReferencedObject(this, detachedPC);
// Check if detachable ... if so then we detach a copy, otherwise we return a transient copy
boolean detachable = myEC.getApiAdapter().isDetachable(myPC);
// make sure a detaching PC is not read by another thread while we are detaching
Object referencedPC = getReferencedPC();
synchronized (referencedPC) {
int[] detachFieldNums = getFieldsNumbersToDetach();
if (detachable) {
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
int[] fieldsToLoad = null;
if ((myEC.getFetchPlan().getDetachmentOptions() & FetchPlan.DETACH_LOAD_FIELDS) != 0) {
fieldsToLoad = ClassUtils.getFlagsSetTo(loadedFields, myFP.getMemberNumbers(), false);
}
NucleusLogger.PERSISTENCE.debug(Localiser.msg("010010", StringUtils.toJVMIDString(myPC), "" + state.getCurrentFetchDepth(), StringUtils.toJVMIDString(detachedPC), StringUtils.intArrayToString(detachFieldNums), StringUtils.intArrayToString(fieldsToLoad)));
}
// Call any "pre-detach" listeners
getCallbackHandler().preDetach(myPC);
}
try {
setDetaching(true);
// Handle any field loading/unloading before the detach
if ((myEC.getFetchPlan().getDetachmentOptions() & FetchPlan.DETACH_LOAD_FIELDS) != 0) {
// Load any unloaded fetch-plan fields
loadUnloadedFieldsInFetchPlan();
}
if (myLC == myEC.getNucleusContext().getApiAdapter().getLifeCycleState(LifeCycleState.HOLLOW) || myLC == myEC.getNucleusContext().getApiAdapter().getLifeCycleState(LifeCycleState.P_NONTRANS)) {
// Migrate any HOLLOW/P_NONTRANS to P_CLEAN etc
myLC = myLC.transitionReadField(this, true);
}
// Create a SM for our copy object
ObjectProvider smDetachedPC = new StateManagerImpl(myEC, cmd);
smDetachedPC.initialiseForDetached(detachedPC, getExternalObjectId(myPC), getVersion(myPC));
myEC.setAttachDetachReferencedObject(smDetachedPC, myPC);
// If detached copy already existed, take note of fields previously loaded
if (existingDetached != null) {
smDetachedPC.retrieveDetachState(smDetachedPC);
}
smDetachedPC.replaceFields(detachFieldNums, new DetachFieldManager(this, cmd.getSCOMutableMemberFlags(), myFP, state, true));
myEC.setAttachDetachReferencedObject(smDetachedPC, null);
if (detachable) {
// Update the object with its detached state - not to be confused with the "state" object above
detachedPC.dnReplaceFlags();
((Detachable) detachedPC).dnReplaceDetachedState();
} else {
smDetachedPC.makeTransient(null);
}
// Remove its StateManager since now detached or transient
replaceStateManager(detachedPC, null);
} catch (Exception e) {
// What could possibly be wrong here ? Log it and let the user provide a testcase, yeah right
NucleusLogger.PERSISTENCE.warn("DETACH ERROR : Error thrown while detaching " + StringUtils.toJVMIDString(myPC) + " (id=" + myID + "). Provide a testcase that demonstrates this", e);
} finally {
setDetaching(false);
referencedPC = null;
}
if (detachable && !myEC.getApiAdapter().isDetached(detachedPC)) {
// Sanity check on the objects detached state
throw new NucleusUserException(Localiser.msg("026025", detachedPC.getClass().getName(), myID));
}
if (detachable) {
// Call any "post-detach" listeners
getCallbackHandler().postDetach(myPC, detachedPC);
}
}
return detachedPC;
}
use of org.datanucleus.enhancement.Persistable in project datanucleus-core by datanucleus.
the class AppIdObjectIdFieldConsumer method storeObjectField.
public void storeObjectField(int fieldNumber, Object value) {
if (api.isPersistable(value)) {
// Embedded PC, so cascade down its PK fields
Persistable pc = (Persistable) value;
pc.dnCopyKeyFieldsFromObjectId(this, pc.dnGetObjectId());
return;
}
fm.storeObjectField(fieldNumber, value);
}
use of org.datanucleus.enhancement.Persistable in project datanucleus-api-jdo by datanucleus.
the class NucleusJDOHelper method getDirtyFields.
/**
* Accessor for the names of the dirty fields of the persistable object.
* @param obj The persistable object
* @param pm The Persistence Manager (only required if the object is detached)
* @return Names of the dirty fields
*/
public static String[] getDirtyFields(Object obj, PersistenceManager pm) {
if (obj == null || !(obj instanceof Persistable)) {
return null;
}
Persistable pc = (Persistable) obj;
if (isDetached(pc)) {
ExecutionContext ec = ((JDOPersistenceManager) pm).getExecutionContext();
// Temporarily attach a StateManager to access the detached field information
ObjectProvider op = ec.getNucleusContext().getObjectProviderFactory().newForDetached(ec, pc, getObjectId(pc), null);
pc.dnReplaceStateManager(op);
op.retrieveDetachState(op);
String[] dirtyFieldNames = op.getDirtyFieldNames();
pc.dnReplaceStateManager(null);
return dirtyFieldNames;
}
ExecutionContext ec = ((JDOPersistenceManager) pm).getExecutionContext();
ObjectProvider op = ec.findObjectProvider(pc);
if (op == null) {
return null;
}
return op.getDirtyFieldNames();
}
use of org.datanucleus.enhancement.Persistable in project datanucleus-api-jdo by datanucleus.
the class NucleusJDOHelper method getLoadedFields.
/**
* Accessor for the names of the loaded fields of the persistable object.
* @param obj Persistable object
* @param pm The Persistence Manager (only required if the object is detached)
* @return Names of the loaded fields
*/
public static String[] getLoadedFields(Object obj, PersistenceManager pm) {
if (obj == null || !(obj instanceof Persistable)) {
return null;
}
Persistable pc = (Persistable) obj;
if (isDetached(pc)) {
// Temporarily attach a StateManager to access the detached field information
ExecutionContext ec = ((JDOPersistenceManager) pm).getExecutionContext();
ObjectProvider op = ec.getNucleusContext().getObjectProviderFactory().newForDetached(ec, pc, getObjectId(pc), null);
pc.dnReplaceStateManager(op);
op.retrieveDetachState(op);
String[] loadedFieldNames = op.getLoadedFieldNames();
pc.dnReplaceStateManager(null);
return loadedFieldNames;
}
ExecutionContext ec = ((JDOPersistenceManager) pm).getExecutionContext();
ObjectProvider op = ec.findObjectProvider(pc);
if (op == null) {
return null;
}
return op.getLoadedFieldNames();
}
Aggregations