use of org.datanucleus.api.ApiAdapter in project datanucleus-core by datanucleus.
the class ExecutionContextImpl method persistObjectInternal.
/**
* Method to make an object persistent which should be called from internal calls only.
* All PM/EM calls should go via persistObject(Object obj).
* @param obj The object
* @param preInsertChanges Any changes to make before inserting
* @param ownerOP ObjectProvider of the owner when embedded
* @param ownerFieldNum Field number in the owner where this is embedded (or -1 if not embedded)
* @param objectType Type of object (see org.datanucleus.ObjectProvider, e.g ObjectProvider.PC)
* @return The persisted object
* @throws NucleusUserException if the object is managed by a different manager
*/
public <T> T persistObjectInternal(T obj, FieldValues preInsertChanges, ObjectProvider ownerOP, int ownerFieldNum, int objectType) {
if (obj == null) {
return null;
}
// TODO Support embeddedOwner/objectType, so we can add ObjectProvider for embedded objects here
ApiAdapter api = getApiAdapter();
// Id of the object that was persisted during this process (if any)
Object id = null;
try {
clr.setPrimary(obj.getClass().getClassLoader());
assertClassPersistable(obj.getClass());
ExecutionContext ec = api.getExecutionContext(obj);
if (ec != null && ec != this) {
// Object managed by a different manager
throw new NucleusUserException(Localiser.msg("010007", obj));
}
boolean cacheable = false;
// Persisted object is the passed in pc (unless being attached as a copy)
T persistedPc = obj;
if (api.isDetached(obj)) {
// Detached : attach it
assertDetachable(obj);
if (getBooleanProperty(PropertyNames.PROPERTY_COPY_ON_ATTACH)) {
// Attach a copy and return the copy
persistedPc = attachObjectCopy(ownerOP, obj, api.getIdForObject(obj) == null);
} else {
// Attach the object
attachObject(ownerOP, obj, api.getIdForObject(obj) == null);
persistedPc = obj;
}
} else if (api.isTransactional(obj) && !api.isPersistent(obj)) {
// TransientTransactional : persist it
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("010015", StringUtils.toJVMIDString(obj)));
}
ObjectProvider op = findObjectProvider(obj);
if (op == null) {
throw new NucleusUserException(Localiser.msg("010007", getApiAdapter().getIdForObject(obj)));
}
op.makePersistentTransactionalTransient();
} else if (!api.isPersistent(obj)) {
// Transient : persist it
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("010015", StringUtils.toJVMIDString(obj)));
}
boolean merged = false;
ThreadContextInfo threadInfo = acquireThreadContextInfo();
try {
if (threadInfo.merging) {
AbstractClassMetaData cmd = getMetaDataManager().getMetaDataForClass(obj.getClass(), clr);
if (cmd.getIdentityType() == IdentityType.APPLICATION) {
Object transientId = nucCtx.getIdentityManager().getApplicationId(obj, cmd);
if (transientId != null) {
// User has set id field(s) so find the datastore object (if exists)
T existingObj = (T) findObject(transientId, true, true, cmd.getFullClassName());
ObjectProvider existingOP = findObjectProvider(existingObj);
existingOP.attach(obj);
id = transientId;
merged = true;
persistedPc = existingObj;
}
}
cacheable = nucCtx.isClassCacheable(cmd);
}
} catch (NucleusObjectNotFoundException onfe) {
// Object with this id doesn't exist, so just persist the transient (below)
} finally {
releaseThreadContextInfo();
}
if (!merged) {
ObjectProvider<T> op = findObjectProvider(obj);
if (op == null) {
if ((objectType == ObjectProvider.EMBEDDED_COLLECTION_ELEMENT_PC || objectType == ObjectProvider.EMBEDDED_MAP_KEY_PC || objectType == ObjectProvider.EMBEDDED_MAP_VALUE_PC || objectType == ObjectProvider.EMBEDDED_PC) && ownerOP != null) {
// SCO object
op = nucCtx.getObjectProviderFactory().newForEmbedded(this, obj, false, ownerOP, ownerFieldNum);
op.setPcObjectType((short) objectType);
op.makePersistent();
id = op.getInternalObjectId();
} else {
// FCO object
op = nucCtx.getObjectProviderFactory().newForPersistentNew(this, obj, preInsertChanges);
op.makePersistent();
id = op.getInternalObjectId();
}
} else {
if (op.getReferencedPC() == null) {
// Persist it
op.makePersistent();
id = op.getInternalObjectId();
} else {
// Being attached, so use the attached object
persistedPc = op.getReferencedPC();
}
}
if (op != null) {
cacheable = nucCtx.isClassCacheable(op.getClassMetaData());
}
}
} else if (api.isPersistent(obj) && api.getIdForObject(obj) == null) {
// Should we be making a copy of the object here ?
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("010015", StringUtils.toJVMIDString(obj)));
}
ObjectProvider op = findObjectProvider(obj);
op.makePersistent();
id = op.getInternalObjectId();
cacheable = nucCtx.isClassCacheable(op.getClassMetaData());
} else if (api.isDeleted(obj)) {
// Deleted : (re)-persist it (permitted in JPA, but not JDO - see ObjectProvider)
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("010015", StringUtils.toJVMIDString(obj)));
}
ObjectProvider op = findObjectProvider(obj);
op.makePersistent();
id = op.getInternalObjectId();
cacheable = nucCtx.isClassCacheable(op.getClassMetaData());
} else {
if (api.isPersistent(obj) && api.isTransactional(obj) && api.isDirty(obj) && isDelayDatastoreOperationsEnabled()) {
// Object provisionally persistent (but not in datastore) so re-run reachability maybe
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("010015", StringUtils.toJVMIDString(obj)));
}
ObjectProvider op = findObjectProvider(obj);
op.makePersistent();
id = op.getInternalObjectId();
cacheable = nucCtx.isClassCacheable(op.getClassMetaData());
}
}
if (id != null && l2CacheTxIds != null && cacheable) {
l2CacheTxIds.add(id);
}
return persistedPc;
} finally {
clr.unsetPrimary();
}
}
use of org.datanucleus.api.ApiAdapter in project datanucleus-core by datanucleus.
the class ExecutionContextImpl method processNontransactionalAtomicChanges.
/**
* Handler for all outstanding changes to be "committed" atomically.
* If a transaction is active, non-tx writes are disabled, or atomic updates not enabled then will do nothing.
* Otherwise will flush any updates that are outstanding (updates to an object), will perform detachAllOnCommit
* if enabled (so user always has detached objects), update objects in any L2 cache, and migrates any
* objects through lifecycle changes.
* Is similar in content to "flush"+"preCommit"+"postCommit"
* Note that this handling for updates is not part of standard JDO which expects non-tx updates to migrate an
* object to P_NONTRANS_DIRTY rather than committing it directly.
* TODO If any update fails we should throw the appropriate exception for the API
*/
protected void processNontransactionalAtomicChanges() {
if (tx.isActive() || !tx.getNontransactionalWrite() || !tx.getNontransactionalWriteAutoCommit()) {
return;
}
if (!dirtyOPs.isEmpty()) {
// Make sure all non-tx dirty objects are enlisted so they get lifecycle changes
for (ObjectProvider op : dirtyOPs) {
if (NucleusLogger.TRANSACTION.isDebugEnabled()) {
NucleusLogger.TRANSACTION.debug(Localiser.msg("015017", StringUtils.toJVMIDString(op.getObject()), op.getInternalObjectId().toString()));
}
enlistedOPCache.put(op.getInternalObjectId(), op);
}
// Flush any outstanding changes to the datastore
flushInternal(true);
if (l2CacheEnabled) {
// L2 caching of enlisted objects
performLevel2CacheUpdateAtCommit();
}
if (properties.getFrequentProperties().getDetachAllOnCommit()) {
// "detach-on-commit"
performDetachAllOnTxnEndPreparation();
performDetachAllOnTxnEnd();
}
// Make sure lifecycle changes take place to all "enlisted" objects
List failures = null;
try {
// "commit" all enlisted ObjectProviders
ApiAdapter api = getApiAdapter();
ObjectProvider[] ops = enlistedOPCache.values().toArray(new ObjectProvider[enlistedOPCache.size()]);
for (int i = 0; i < ops.length; ++i) {
try {
// Run through "postCommit" to migrate the lifecycle state
if (ops[i] != null && ops[i].getObject() != null && api.isPersistent(ops[i].getObject()) && api.isDirty(ops[i].getObject())) {
ops[i].postCommit(getTransaction());
} else {
NucleusLogger.PERSISTENCE.debug(">> Atomic nontransactional processing : Not performing postCommit on " + ops[i]);
}
} catch (RuntimeException e) {
if (failures == null) {
failures = new ArrayList();
}
failures.add(e);
}
}
} finally {
resetTransactionalVariables();
}
if (failures != null && !failures.isEmpty()) {
throw new CommitStateTransitionException((Exception[]) failures.toArray(new Exception[failures.size()]));
}
}
if (nontxProcessedOPs != null && !nontxProcessedOPs.isEmpty()) {
for (ObjectProvider op : nontxProcessedOPs) {
if (op != null && op.getLifecycleState() != null && op.getLifecycleState().isDeleted()) {
removeObjectFromLevel1Cache(op.getInternalObjectId());
removeObjectFromLevel2Cache(op.getInternalObjectId());
}
}
nontxProcessedOPs.clear();
}
}
use of org.datanucleus.api.ApiAdapter in project datanucleus-core by datanucleus.
the class AbstractClassMetaData method validateObjectIdClass.
/**
* Validate the objectid-class of this class.
* @param clr ClassLoader resolver
*/
protected void validateObjectIdClass(ClassLoaderResolver clr) {
if (getPersistableSuperclass() == null) {
// Only check root persistable class PK
if (objectidClass != null) {
ApiAdapter api = mmgr.getApiAdapter();
Class obj_cls = null;
try {
// Load the class, using the same class loader resolver as this class
obj_cls = clr.classForName(objectidClass);
} catch (ClassNotResolvedException cnre) {
// ObjectIdClass not found
throw new InvalidClassMetaDataException("044079", fullName, objectidClass);
}
boolean validated = false;
Set<Throwable> errors = new HashSet<>();
try {
// Check against the API Adapter in use for this MetaData
if (api.isValidPrimaryKeyClass(obj_cls, this, clr, getNoOfPopulatedPKMembers(), mmgr)) {
validated = true;
}
} catch (NucleusException ex) {
errors.add(ex);
}
if (!validated) {
// This needs coordinating with the test expectations in the enhancer unit tests.
throw new NucleusUserException(Localiser.msg("019016", getFullClassName(), obj_cls.getName()), errors.toArray(new Throwable[errors.size()]));
}
}
}
}
use of org.datanucleus.api.ApiAdapter in project datanucleus-core by datanucleus.
the class AbstractMemberMetaData method populate.
/**
* Method to provide the details of the field being represented by this MetaData hence populating
* certain parts of the MetaData. This is used to firstly provide defaults for attributes that aren't
* specified in the MetaData, and secondly to report any errors with attributes that have been specifed
* that are inconsistent with the field being represented.
* Either a field or a method should be passed in (one or the other) depending on what is being represented
* by this "member".
* @param clr ClassLoaderResolver to use for any class loading
* @param field Field that we are representing (if it's a field)
* @param method Method(property) that we are representing (if it's a method).
* @param primary the primary ClassLoader to use (or null)
* @param mmgr MetaData manager
*/
public synchronized void populate(ClassLoaderResolver clr, Field field, Method method, ClassLoader primary, MetaDataManager mmgr) {
if (isPopulated() || isInitialised()) {
return;
}
// Set defaults for cascading when not yet set
ApiAdapter apiAdapter = mmgr.getNucleusContext().getApiAdapter();
if (cascadePersist == null) {
cascadePersist = apiAdapter.getDefaultCascadePersistForField();
}
if (cascadeUpdate == null) {
cascadeUpdate = apiAdapter.getDefaultCascadeUpdateForField();
}
if (cascadeDelete == null) {
cascadeDelete = apiAdapter.getDefaultCascadeDeleteForField();
}
if (cascadeDetach == null) {
cascadeDetach = apiAdapter.getDefaultCascadeDetachForField();
}
if (cascadeRefresh == null) {
cascadeRefresh = apiAdapter.getDefaultCascadeRefreshForField();
}
if (field == null && method == null) {
NucleusLogger.METADATA.error(Localiser.msg("044106", getClassName(), getName()));
throw new InvalidMemberMetaDataException("044106", getClassName(), getName());
}
// No class loader, so use System
if (clr == null) {
NucleusLogger.METADATA.warn(Localiser.msg("044067", name, getClassName(true)));
clr = mmgr.getNucleusContext().getClassLoaderResolver(null);
}
memberRepresented = field != null ? field : method;
if (type == null) {
// Type not yet set so set from field/method (will only be set if we are imposing the type due to Java generics TypeVariable usage)
if (field != null) {
this.type = field.getType();
} else if (method != null) {
this.type = method.getReturnType();
}
}
if (className != null) {
// Property is overriding a superclass property, so check that it is valid
Class thisClass = null;
if (parent instanceof EmbeddedMetaData) {
// <embedded> is contained in a <field>, <element>, <key>, <value>
// but could be multiple levels deep so adopt a generic strategy for finding the parent class
MetaData superMd = parent.getParent();
thisClass = ((AbstractMemberMetaData) superMd).getType();
} else {
// Overriding field in a superclass of this class
try {
thisClass = clr.classForName(getAbstractClassMetaData().getPackageName() + "." + getAbstractClassMetaData().getName());
} catch (ClassNotResolvedException cnre) {
// Do nothing
}
}
Class fieldClass = null;
try {
fieldClass = clr.classForName(className);
} catch (ClassNotResolvedException cnre) {
try {
fieldClass = clr.classForName(getAbstractClassMetaData().getPackageName() + "." + className);
className = getAbstractClassMetaData().getPackageName() + "." + className;
} catch (ClassNotResolvedException cnre2) {
NucleusLogger.METADATA.error(Localiser.msg("044113", getClassName(), getName(), className));
NucleusException ne = new InvalidMemberMetaDataException("044113", getClassName(), getName(), className);
ne.setNestedException(cnre);
throw ne;
}
}
if (fieldClass != null && !fieldClass.isAssignableFrom(thisClass)) {
// TODO We could also check if persistable, but won't work when enhancing
NucleusLogger.METADATA.error(Localiser.msg("044114", getClassName(), getName(), className));
throw new InvalidMemberMetaDataException("044114", getClassName(), getName(), className);
}
}
if (primaryKey == null) {
// Primary key not set by user so initialise it to false
primaryKey = Boolean.FALSE;
}
// Update "embedded" based on type
if (primaryKey == Boolean.FALSE && embedded == null) {
Class element_type = getType();
if (element_type.isArray()) {
element_type = element_type.getComponentType();
if (mmgr.getNucleusContext().getTypeManager().isDefaultEmbeddedType(element_type)) {
embedded = Boolean.TRUE;
}
} else if (mmgr.getNucleusContext().getTypeManager().isDefaultEmbeddedType(element_type)) {
embedded = Boolean.TRUE;
}
}
if (embedded == null) {
embedded = Boolean.FALSE;
}
// Update "persistence-modifier" according to type etc
if (FieldPersistenceModifier.DEFAULT.equals(persistenceModifier)) {
if (getTypeConverterName() != null) {
// Explicitly set a converter, so assume it is persistent
persistenceModifier = FieldPersistenceModifier.PERSISTENT;
} else {
boolean isPcClass = getType().isArray() ? isFieldArrayTypePersistable(mmgr) : mmgr.isFieldTypePersistable(type);
if (!isPcClass) {
if (getType().isArray() && getType().getComponentType().isInterface()) {
isPcClass = mmgr.getMetaDataForClassInternal(getType().getComponentType(), clr) != null;
} else if (getType().isInterface()) {
isPcClass = mmgr.getMetaDataForClassInternal(getType(), clr) != null;
}
}
persistenceModifier = getDefaultFieldPersistenceModifier(getType(), memberRepresented.getModifiers(), isPcClass, mmgr);
}
}
// TODO If this field is NONE in superclass, make it NONE here too
// If type is a container, load create the metadata. The field will be handled as a container if it
// has a ContainerHandler registered against it.
TypeManager typeMgr = mmgr.getNucleusContext().getTypeManager();
ContainerHandler containerHandler = typeMgr.getContainerHandler(type);
if (containerHandler == null) {
// No container handler registered for this type
if (hasContainer()) {
// Container metadata specified on a type that is not a valid or supported container
NucleusLogger.METADATA.error(Localiser.msg("044212", getClassName(), getName(), type));
NucleusException ne = new InvalidMemberMetaDataException("044212", getClassName(), getName(), type);
throw ne;
}
} else {
// Field is a container type
if (!hasContainer()) {
// No container metadata has not been specified yet, create a default empty one
setContainer(containerHandler.newMetaData());
}
containerHandler.populateMetaData(clr, primary, this);
}
// Update "default-fetch-group" according to type
if (defaultFetchGroup == null && persistenceModifier.equals(FieldPersistenceModifier.NONE)) {
defaultFetchGroup = Boolean.FALSE;
} else if (defaultFetchGroup == null && persistenceModifier.equals(FieldPersistenceModifier.TRANSACTIONAL)) {
defaultFetchGroup = Boolean.FALSE;
} else if (defaultFetchGroup == null) {
defaultFetchGroup = Boolean.FALSE;
if (!primaryKey.equals(Boolean.TRUE)) {
if (hasContainer() && containerHandler != null) {
defaultFetchGroup = containerHandler.isDefaultFetchGroup(clr, typeMgr, this);
} else if (typeMgr.isDefaultFetchGroup(getType())) {
// If still not determined rely on the type
defaultFetchGroup = Boolean.TRUE;
}
}
}
// Field is not specified as "persistent" yet has DFG or primary-key !
if (persistenceModifier.equals(FieldPersistenceModifier.TRANSACTIONAL) || persistenceModifier.equals(FieldPersistenceModifier.NONE)) {
if (defaultFetchGroup == Boolean.TRUE || primaryKey == Boolean.TRUE) {
throw new InvalidMemberMetaDataException("044109", getClassName(), name, this.getType().getName(), persistenceModifier.toString());
}
}
if (storeInLob) {
// Set up the jdbcType/serialized settings according to the field type in line with JPA
boolean useClob = false;
if (type == String.class || (type.isArray() && type.getComponentType() == Character.class) || (type.isArray() && type.getComponentType() == char.class)) {
useClob = true;
if (columns == null || columns.isEmpty()) {
// Create a CLOB column. What if the RDBMS doesn't support CLOB ?
ColumnMetaData colmd = new ColumnMetaData();
colmd.setName(column);
colmd.setJdbcType("CLOB");
addColumn(colmd);
} else {
ColumnMetaData colmd = columns.get(0);
colmd.setJdbcType("CLOB");
}
}
if (!useClob) {
serialized = Boolean.TRUE;
}
}
if (!mmgr.isDefaultNullable() && !hasContainer()) {
// Find column metadata definition, creating one if not specified
ColumnMetaData colMmd;
if (columns == null || columns.isEmpty()) {
newColumnMetaData();
}
colMmd = getColumnMetaData()[0];
// Set column not-null by default
if (colMmd.getAllowsNull() == null) {
colMmd.setAllowsNull(Boolean.FALSE);
}
}
if (this.containerMetaData != null && this.dependent != null) {
// Check for invalid dependent field specifications
NucleusLogger.METADATA.error(Localiser.msg("044110", getClassName(), getName(), ((ClassMetaData) this.parent).getName()));
throw new InvalidMemberMetaDataException("044110", getClassName(), getName(), ((ClassMetaData) this.parent).getName());
}
if (embedded == Boolean.TRUE && embeddedMetaData == null) {
// User specified "embedded" on the member, yet no embedded definition so add one TODO Omit this, since we should only use when provided
AbstractClassMetaData memberCmd = mmgr.getMetaDataForClassInternal(getType(), clr);
if (memberCmd != null) {
embeddedMetaData = new EmbeddedMetaData();
embeddedMetaData.setParent(this);
}
}
if (embeddedMetaData != null) {
// Update with any extensions (for lack of features in JPA)
if (hasExtension("null-indicator-column")) {
embeddedMetaData.setNullIndicatorColumn(getValueForExtension("null-indicator-column"));
if (hasExtension("null-indicator-value")) {
embeddedMetaData.setNullIndicatorValue(getValueForExtension("null-indicator-value"));
}
}
// Populate any embedded object
embeddedMetaData.populate(clr, primary);
embedded = Boolean.TRUE;
}
if (containerMetaData != null && persistenceModifier == FieldPersistenceModifier.PERSISTENT) {
// Populate any container
if (containerMetaData instanceof CollectionMetaData) {
// if (cascadeDelete)
// {
// // User has set cascade-delete (JPA) so set the element as dependent
// getCollection().element.dependent = Boolean.TRUE;
// }
// getCollection().populate(clr, primary, mmgr);
} else if (containerMetaData instanceof MapMetaData) {
// String keyCascadeVal = getValueForExtension("cascade-delete-key");
// if (cascadeDelete)
// {
// // User has set cascade-delete (JPA) so set the value as dependent
// getMap().key.dependent = Boolean.FALSE; // JPA spec doesn't define what this should be
// getMap().value.dependent = Boolean.TRUE;
// }
// if (keyCascadeVal != null)
// {
// if (keyCascadeVal.equalsIgnoreCase("true"))
// {
// getMap().key.dependent = Boolean.TRUE;
// }
// else
// {
// getMap().key.dependent = Boolean.FALSE;
// }
// }
// getMap().populate(clr, primary, mmgr);
} else if (containerMetaData instanceof ArrayMetaData) {
// if (cascadeDelete)
// {
// // User has set cascade-delete (JPA) so set the element as dependent
// getArray().element.dependent = Boolean.TRUE;
// }
// getArray().populate(clr, primary, mmgr);
}
}
if (mmgr.isFieldTypePersistable(type) && cascadeDelete) {
setDependent(true);
}
if (hasExtension(MetaData.EXTENSION_MEMBER_IMPLEMENTATION_CLASSES)) {
// Check the validity of the implementation-classes and qualify them where required.
StringBuilder str = new StringBuilder();
String[] implTypes = getValuesForExtension(MetaData.EXTENSION_MEMBER_IMPLEMENTATION_CLASSES);
for (int i = 0; i < implTypes.length; i++) {
String implTypeName = ClassUtils.createFullClassName(getAbstractClassMetaData().getPackageName(), implTypes[i]);
if (i > 0) {
str.append(",");
}
try {
clr.classForName(implTypeName);
str.append(implTypeName);
} catch (ClassNotResolvedException cnre) {
try {
// Maybe the user specified a java.lang class without fully-qualifying it
// This is beyond the scope of the JDO spec which expects java.lang cases to be fully-qualified
String langClassName = ClassUtils.getJavaLangClassForType(implTypeName);
clr.classForName(langClassName);
str.append(langClassName);
} catch (ClassNotResolvedException cnre2) {
// Implementation type not found
throw new InvalidMemberMetaDataException("044116", getClassName(), getName(), implTypes[i]);
}
}
}
// Replace with this new value
addExtension(MetaData.EXTENSION_MEMBER_IMPLEMENTATION_CLASSES, str.toString());
}
// Set up persistence flags for enhancement process
byte serializable = 0;
if (Serializable.class.isAssignableFrom(getType()) || getType().isPrimitive()) {
serializable = Persistable.SERIALIZABLE;
}
if (FieldPersistenceModifier.NONE.equals(persistenceModifier)) {
persistenceFlags = 0;
} else if (FieldPersistenceModifier.TRANSACTIONAL.equals(persistenceModifier) && Modifier.isTransient(memberRepresented.getModifiers())) {
persistenceFlags = (byte) (Persistable.CHECK_WRITE | serializable);
} else if (primaryKey.booleanValue()) {
persistenceFlags = (byte) (Persistable.MEDIATE_WRITE | serializable);
} else if (defaultFetchGroup.booleanValue()) {
persistenceFlags = (byte) (Persistable.CHECK_READ | Persistable.CHECK_WRITE | serializable);
} else if (!defaultFetchGroup.booleanValue()) {
persistenceFlags = (byte) (Persistable.MEDIATE_READ | Persistable.MEDIATE_WRITE | serializable);
} else {
persistenceFlags = 0;
}
// Set fields that are not relations
if (persistenceModifier != FieldPersistenceModifier.PERSISTENT) {
// Not a relation field so set relation information
relationType = RelationType.NONE;
} else if (containerMetaData == null && !mmgr.isFieldTypePersistable(type)) {
if (!type.getName().equals(ClassNameConstants.Object) && !type.isInterface()) {
// Not a container field, not a persistable type, nor a reference type so not a relation field
relationType = RelationType.NONE;
}
}
if (serialized == Boolean.TRUE && hasExtension(MetaData.EXTENSION_MEMBER_TYPE_CONVERTER_NAME)) {
NucleusLogger.METADATA.warn(Localiser.msg("044127", getClassName(), getName(), getValueForExtension(MetaData.EXTENSION_MEMBER_TYPE_CONVERTER_NAME)));
serialized = Boolean.FALSE;
}
setPopulated();
}
use of org.datanucleus.api.ApiAdapter in project datanucleus-core by datanucleus.
the class IdentityUtils method getApplicationIdentityForResultSetRow.
/**
* Method to return the object application identity for a row of the result set.
* If the class isn't using application identity then returns null
* @param ec Execution Context
* @param cmd Metadata for the class
* @param pcClass The class required
* @param inheritanceCheck Whether need an inheritance check (may be for a subclass)
* @param resultsFM FieldManager servicing the results
* @return The identity (if found) or null (if either not sure of inheritance, or not known).
*/
public static Object getApplicationIdentityForResultSetRow(ExecutionContext ec, AbstractClassMetaData cmd, Class pcClass, boolean inheritanceCheck, FieldManager resultsFM) {
if (cmd.getIdentityType() == IdentityType.APPLICATION) {
if (pcClass == null) {
pcClass = ec.getClassLoaderResolver().classForName(cmd.getFullClassName());
}
ApiAdapter api = ec.getApiAdapter();
int[] pkFieldNums = cmd.getPKMemberPositions();
Object[] pkFieldValues = new Object[pkFieldNums.length];
for (int i = 0; i < pkFieldNums.length; i++) {
AbstractMemberMetaData pkMmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(pkFieldNums[i]);
if (pkMmd.getType() == int.class) {
pkFieldValues[i] = resultsFM.fetchIntField(pkFieldNums[i]);
} else if (pkMmd.getType() == short.class) {
pkFieldValues[i] = resultsFM.fetchShortField(pkFieldNums[i]);
} else if (pkMmd.getType() == long.class) {
pkFieldValues[i] = resultsFM.fetchLongField(pkFieldNums[i]);
} else if (pkMmd.getType() == char.class) {
pkFieldValues[i] = resultsFM.fetchCharField(pkFieldNums[i]);
} else if (pkMmd.getType() == boolean.class) {
pkFieldValues[i] = resultsFM.fetchBooleanField(pkFieldNums[i]);
} else if (pkMmd.getType() == byte.class) {
pkFieldValues[i] = resultsFM.fetchByteField(pkFieldNums[i]);
} else if (pkMmd.getType() == double.class) {
pkFieldValues[i] = resultsFM.fetchDoubleField(pkFieldNums[i]);
} else if (pkMmd.getType() == float.class) {
pkFieldValues[i] = resultsFM.fetchFloatField(pkFieldNums[i]);
} else if (pkMmd.getType() == String.class) {
pkFieldValues[i] = resultsFM.fetchStringField(pkFieldNums[i]);
} else {
pkFieldValues[i] = resultsFM.fetchObjectField(pkFieldNums[i]);
}
}
Class idClass = ec.getClassLoaderResolver().classForName(cmd.getObjectidClass());
if (cmd.usesSingleFieldIdentityClass()) {
// Create SingleField identity with query key value
Object id = ec.getNucleusContext().getIdentityManager().getSingleFieldId(idClass, pcClass, pkFieldValues[0]);
if (inheritanceCheck) {
// Check if this identity exists in the cache(s)
if (ec.hasIdentityInCache(id)) {
return id;
}
// Check if this id for any known subclasses is in the cache to save searching
String[] subclasses = ec.getMetaDataManager().getSubclassesForClass(pcClass.getName(), true);
if (subclasses != null) {
for (int i = 0; i < subclasses.length; i++) {
Object subid = ec.getNucleusContext().getIdentityManager().getSingleFieldId(idClass, ec.getClassLoaderResolver().classForName(subclasses[i]), IdentityUtils.getTargetKeyForSingleFieldIdentity(id));
if (ec.hasIdentityInCache(subid)) {
return subid;
}
}
}
// Check the inheritance with the store manager (may involve a trip to the datastore)
String className = ec.getStoreManager().getClassNameForObjectID(id, ec.getClassLoaderResolver(), ec);
return ec.getNucleusContext().getIdentityManager().getSingleFieldId(idClass, ec.getClassLoaderResolver().classForName(className), pkFieldValues[0]);
}
return id;
}
// Create user-defined PK class with PK field values
try {
// All user-defined PK classes have a default constructor
Object id = idClass.newInstance();
for (int i = 0; i < pkFieldNums.length; i++) {
AbstractMemberMetaData pkMmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(pkFieldNums[i]);
Object value = pkFieldValues[i];
if (api.isPersistable(value)) {
// CompoundIdentity, so use id
value = api.getIdForObject(value);
}
if (pkMmd instanceof FieldMetaData) {
// Set the field directly (assumed to be public)
Field pkField = ClassUtils.getFieldForClass(idClass, pkMmd.getName());
pkField.set(id, value);
} else {
// Use the setter
Method pkMethod = ClassUtils.getSetterMethodForClass(idClass, pkMmd.getName(), pkMmd.getType());
pkMethod.invoke(id, value);
}
}
return id;
} catch (Exception e) {
return null;
}
}
return null;
}
Aggregations