use of org.datanucleus.api.ApiAdapter in project datanucleus-rdbms by datanucleus.
the class SerialisedReferenceMapping method setObject.
/**
* Method to populate parameter positions in a PreparedStatement with this object
* @param ec execution context
* @param ps The Prepared Statement
* @param exprIndex The parameter positions to populate
* @param value The value of the PC to use in populating the parameter positions
* @param ownerOP ObjectProvider for the owning object
* @param fieldNumber field number of this object in the owning object
*/
public void setObject(ExecutionContext ec, PreparedStatement ps, int[] exprIndex, Object value, ObjectProvider ownerOP, int fieldNumber) {
ApiAdapter api = ec.getApiAdapter();
if (api.isPersistable(value)) {
// Assign a StateManager to the serialised object if none present
ObjectProvider embSM = ec.findObjectProvider(value);
if (embSM == null || api.getExecutionContext(value) == null) {
embSM = ec.getNucleusContext().getObjectProviderFactory().newForEmbedded(ec, value, false, ownerOP, fieldNumber);
}
}
ObjectProvider sm = null;
if (api.isPersistable(value)) {
// Find SM for serialised PC object
sm = ec.findObjectProvider(value);
}
if (sm != null) {
sm.setStoringPC();
}
getDatastoreMapping(0).setObject(ps, exprIndex[0], value);
if (sm != null) {
sm.unsetStoringPC();
}
}
use of org.datanucleus.api.ApiAdapter in project datanucleus-rdbms by datanucleus.
the class JoinMapStore method clear.
/**
* Method to clear the map of all values.
* @param ownerOP ObjectProvider for the map.
*/
public void clear(ObjectProvider ownerOP) {
Collection dependentElements = null;
if (ownerMemberMetaData.getMap().isDependentKey() || ownerMemberMetaData.getMap().isDependentValue()) {
// Retain the PC dependent keys/values that need deleting after clearing
dependentElements = new HashSet();
ApiAdapter api = ownerOP.getExecutionContext().getApiAdapter();
Iterator iter = entrySetStore().iterator(ownerOP);
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
MapMetaData mapmd = ownerMemberMetaData.getMap();
if (api.isPersistable(entry.getKey()) && mapmd.isDependentKey() && !mapmd.isEmbeddedKey()) {
dependentElements.add(entry.getKey());
}
if (api.isPersistable(entry.getValue()) && mapmd.isDependentValue() && !mapmd.isEmbeddedValue()) {
dependentElements.add(entry.getValue());
}
}
}
clearInternal(ownerOP);
if (dependentElements != null && dependentElements.size() > 0) {
// Delete all dependent objects
ownerOP.getExecutionContext().deleteObjects(dependentElements.toArray());
}
}
use of org.datanucleus.api.ApiAdapter in project datanucleus-rdbms by datanucleus.
the class ExpressionUtils method getEqualityExpressionForObjectExpressions.
/**
* Method to generate an equality/inequality expression between two ObjectExpressions.
* Either or both of the expressions can be ObjectLiterals.
* @param expr1 First expression
* @param expr2 Second expression
* @param equals Whether it is equality (otherwise inequality)
* @return The expression
*/
public static BooleanExpression getEqualityExpressionForObjectExpressions(ObjectExpression expr1, ObjectExpression expr2, boolean equals) {
SQLStatement stmt = expr1.stmt;
RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
ClassLoaderResolver clr = stmt.getClassLoaderResolver();
ApiAdapter api = storeMgr.getApiAdapter();
if (expr1 instanceof ObjectLiteral && expr2 instanceof ObjectLiteral) {
// ObjectLiterall == ObjectLiteral
ObjectLiteral lit1 = (ObjectLiteral) expr1;
ObjectLiteral lit2 = (ObjectLiteral) expr2;
return new BooleanLiteral(stmt, expr1.mapping, equals ? lit1.getValue().equals(lit2.getValue()) : !lit1.getValue().equals(lit2.getValue()));
} else if (expr1 instanceof ObjectLiteral || expr2 instanceof ObjectLiteral) {
// ObjectExpression == ObjectLiteral, ObjectLiteral == ObjectExpression
BooleanExpression bExpr = null;
boolean secondIsLiteral = (expr2 instanceof ObjectLiteral);
Object value = (!secondIsLiteral ? ((ObjectLiteral) expr1).getValue() : ((ObjectLiteral) expr2).getValue());
if (IdentityUtils.isDatastoreIdentity(value)) {
// Object is an OID
Object valueKey = IdentityUtils.getTargetKeyForDatastoreIdentity(value);
JavaTypeMapping m = storeMgr.getSQLExpressionFactory().getMappingForType(valueKey.getClass(), false);
SQLExpression oidLit = exprFactory.newLiteral(stmt, m, valueKey);
if (equals) {
return (secondIsLiteral ? expr1.subExprs.getExpression(0).eq(oidLit) : expr2.subExprs.getExpression(0).eq(oidLit));
}
return (secondIsLiteral ? expr1.subExprs.getExpression(0).ne(oidLit) : expr2.subExprs.getExpression(0).ne(oidLit));
} else if (IdentityUtils.isSingleFieldIdentity(value)) {
// Object is SingleFieldIdentity
Object valueKey = IdentityUtils.getTargetKeyForSingleFieldIdentity(value);
// This used to use ((SingleFieldId)value).getTargetClass() for some reason, which contradicts the above datastore id method
JavaTypeMapping m = storeMgr.getSQLExpressionFactory().getMappingForType(valueKey.getClass(), false);
SQLExpression oidLit = exprFactory.newLiteral(stmt, m, valueKey);
if (equals) {
return (secondIsLiteral ? expr1.subExprs.getExpression(0).eq(oidLit) : expr2.subExprs.getExpression(0).eq(oidLit));
}
return (secondIsLiteral ? expr1.subExprs.getExpression(0).ne(oidLit) : expr2.subExprs.getExpression(0).ne(oidLit));
} else {
AbstractClassMetaData cmd = storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(value.getClass(), clr);
if (cmd != null) {
// Value is a persistable object
if (cmd.getIdentityType() == IdentityType.APPLICATION) {
// Application identity
if (api.getIdForObject(value) != null) {
// Persistent PC object (FCO)
// Cater for composite PKs and parts of PK being PC mappings, and recursion
ObjectExpression expr = (secondIsLiteral ? expr1 : expr2);
JavaTypeMapping[] pkMappingsApp = new JavaTypeMapping[expr.subExprs.size()];
Object[] pkFieldValues = new Object[expr.subExprs.size()];
int position = 0;
ExecutionContext ec = api.getExecutionContext(value);
JavaTypeMapping thisMapping = expr.mapping;
if (expr.mapping instanceof ReferenceMapping) {
// "InterfaceField == value", so pick an implementation mapping that is castable
thisMapping = null;
ReferenceMapping refMapping = (ReferenceMapping) expr.mapping;
JavaTypeMapping[] implMappings = refMapping.getJavaTypeMapping();
for (int i = 0; i < implMappings.length; i++) {
Class implType = clr.classForName(implMappings[i].getType());
if (implType.isAssignableFrom(value.getClass())) {
thisMapping = implMappings[i];
break;
}
}
}
if (thisMapping == null) {
// Just return a (1=0) since no implementation castable
return exprFactory.newLiteral(stmt, expr1.mapping, false).eq(exprFactory.newLiteral(stmt, expr1.mapping, true));
}
for (int i = 0; i < cmd.getNoOfPrimaryKeyMembers(); i++) {
AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(cmd.getPKMemberPositions()[i]);
Object fieldValue = ExpressionUtils.getValueForMemberOfObject(ec, mmd, value);
JavaTypeMapping mapping = ((PersistableMapping) thisMapping).getJavaTypeMapping()[i];
if (mapping instanceof PersistableMapping) {
position = ExpressionUtils.populatePrimaryKeyMappingsValuesForPCMapping(pkMappingsApp, pkFieldValues, position, (PersistableMapping) mapping, cmd, mmd, fieldValue, storeMgr, clr);
} else {
pkMappingsApp[position] = mapping;
pkFieldValues[position] = fieldValue;
position++;
}
}
for (int i = 0; i < expr.subExprs.size(); i++) {
SQLExpression source = expr.subExprs.getExpression(i);
SQLExpression target = exprFactory.newLiteral(stmt, pkMappingsApp[i], pkFieldValues[i]);
BooleanExpression subExpr = (secondIsLiteral ? source.eq(target) : target.eq(source));
if (bExpr == null) {
bExpr = subExpr;
} else {
bExpr = bExpr.and(subExpr);
}
}
} else {
// PC object with no id (embedded, or transient maybe)
if (secondIsLiteral) {
for (int i = 0; i < expr1.subExprs.size(); i++) {
// Query should return nothing (so just do "(1 = 0)")
NucleusLogger.QUERY.warn(Localiser.msg("037003", value));
bExpr = exprFactory.newLiteral(stmt, expr1.mapping, false).eq(exprFactory.newLiteral(stmt, expr1.mapping, true));
// It is arguable that we should compare the id with null (as below)
/*bExpr = expr.eq(new NullLiteral(qs));*/
}
} else {
for (int i = 0; i < expr2.subExprs.size(); i++) {
// Query should return nothing (so just do "(1 = 0)")
NucleusLogger.QUERY.warn(Localiser.msg("037003", value));
bExpr = exprFactory.newLiteral(stmt, expr2.mapping, false).eq(exprFactory.newLiteral(stmt, expr2.mapping, true));
// It is arguable that we should compare the id with null (as below)
/*bExpr = expr.eq(new NullLiteral(qs));*/
}
}
}
// TODO Allow for !equals
return bExpr;
} else if (cmd.getIdentityType() == IdentityType.DATASTORE) {
// Datastore identity
SQLExpression source = (secondIsLiteral ? expr1.subExprs.getExpression(0) : expr2.subExprs.getExpression(0));
JavaTypeMapping mapping = (secondIsLiteral ? expr1.mapping : expr2.mapping);
Object objectId = api.getIdForObject(value);
if (objectId == null) {
// PC object with no id (embedded, or transient maybe)
// Query should return nothing (so just do "(1 = 0)")
NucleusLogger.QUERY.warn(Localiser.msg("037003", value));
// TODO Allow for !equals
return exprFactory.newLiteral(stmt, mapping, false).eq(exprFactory.newLiteral(stmt, mapping, true));
// It is arguable that we should compare the id with null (as below)
/*bExpr = expr.eq(new NullLiteral(qs));*/
}
Object objectIdKey = IdentityUtils.getTargetKeyForDatastoreIdentity(objectId);
JavaTypeMapping m = storeMgr.getSQLExpressionFactory().getMappingForType(objectIdKey.getClass(), false);
SQLExpression oidExpr = exprFactory.newLiteral(stmt, m, objectIdKey);
if (equals) {
return source.eq(oidExpr);
}
return source.ne(oidExpr);
}
} else {
// No metadata, so we either have an application identity, or any object
String pcClassName = storeMgr.getClassNameForObjectID(value, clr, null);
if (pcClassName != null) {
// Object is an application identity
cmd = storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(pcClassName, clr);
return (secondIsLiteral ? ExpressionUtils.getAppIdEqualityExpression(value, expr1, storeMgr, clr, cmd, null, null) : ExpressionUtils.getAppIdEqualityExpression(value, expr2, storeMgr, clr, cmd, null, null));
// TODO Allow for !equals
}
// Value not persistable nor an identity, so return nothing "(1 = 0)"
return exprFactory.newLiteral(stmt, expr1.mapping, false).eq(exprFactory.newLiteral(stmt, expr1.mapping, true));
// TODO Allow for !equals
}
}
} else {
// ObjectExpression == ObjectExpression
BooleanExpression resultExpr = null;
for (int i = 0; i < expr1.subExprs.size(); i++) {
SQLExpression sourceExpr = expr1.subExprs.getExpression(i);
SQLExpression targetExpr = expr2.subExprs.getExpression(i);
if (resultExpr == null) {
resultExpr = sourceExpr.eq(targetExpr);
} else {
resultExpr = resultExpr.and(sourceExpr.eq(targetExpr));
}
}
if (!equals) {
resultExpr = new BooleanExpression(Expression.OP_NOT, resultExpr != null ? resultExpr.encloseInParentheses() : null);
}
return resultExpr;
}
return null;
}
use of org.datanucleus.api.ApiAdapter in project datanucleus-core by datanucleus.
the class ExecutionContextImpl method attachObject.
/**
* Method to attach a persistent detached object.
* If a different object with the same identity as this object exists in the L1 cache then an exception
* will be thrown.
* @param ownerOP ObjectProvider of the owner object that has this in a field that causes this attach
* @param pc The persistable object
* @param sco Whether the PC object is stored without an identity (embedded/serialised)
*/
public void attachObject(ObjectProvider ownerOP, Object pc, boolean sco) {
assertClassPersistable(pc.getClass());
// Store the owner for this persistable object being attached
// For the current thread
Map attachedOwnerByObject = getThreadContextInfo().attachedOwnerByObject;
if (attachedOwnerByObject != null) {
attachedOwnerByObject.put(pc, ownerOP);
}
ApiAdapter api = getApiAdapter();
Object id = api.getIdForObject(pc);
if (id != null && isInserting(pc)) {
// Object is being inserted in this transaction so just return
return;
} else if (id == null && !sco) {
// Transient object so needs persisting
persistObjectInternal(pc, null, null, -1, ObjectProvider.PC);
return;
}
if (api.isDetached(pc)) {
// Detached, so migrate to attached
if (cache != null) {
ObjectProvider l1CachedOP = cache.get(id);
if (l1CachedOP != null && l1CachedOP.getObject() != pc) {
// attached object with the same id already present in the L1 cache so cannot attach in-situ
throw new NucleusUserException(Localiser.msg("010017", StringUtils.toJVMIDString(pc)));
}
}
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("010016", StringUtils.toJVMIDString(pc)));
}
ObjectProvider op = nucCtx.getObjectProviderFactory().newForDetached(this, pc, id, api.getVersionForObject(pc));
op.attach(sco);
} else {
// Not detached so can't attach it. Just return
return;
}
}
use of org.datanucleus.api.ApiAdapter in project datanucleus-core by datanucleus.
the class ExecutionContextImpl method findObjectsById.
/**
* Accessor for objects with the specified identities.
* @param identities Ids of the object(s).
* @param validate Whether to validate the object state
* @return The Objects with these ids (same order)
* @throws NucleusObjectNotFoundException if an object doesn't exist in the datastore
*/
public Object[] findObjectsById(Object[] identities, boolean validate) {
if (identities == null) {
return null;
} else if (identities.length == 1) {
return new Object[] { findObject(identities[0], validate, validate, null) };
}
for (int i = 0; i < identities.length; i++) {
if (identities[i] == null) {
throw new NucleusUserException(Localiser.msg("010044"));
}
}
// Set the identities array
Object[] ids = new Object[identities.length];
for (int i = 0; i < identities.length; i++) {
// Translate the identity if required
if (identities[i] instanceof String) {
IdentityStringTranslator idStringTranslator = getNucleusContext().getIdentityManager().getIdentityStringTranslator();
if (idStringTranslator != null) {
// DataNucleus extension to translate input identities into valid persistent identities.
ids[i] = idStringTranslator.getIdentity(this, (String) identities[i]);
continue;
}
}
ids[i] = identities[i];
}
Map pcById = new HashMap(identities.length);
List idsToFind = new ArrayList();
ApiAdapter api = getApiAdapter();
// Check the L1 cache
for (int i = 0; i < ids.length; i++) {
Object pc = getObjectFromLevel1Cache(ids[i]);
if (pc != null) {
if (ids[i] instanceof SCOID) {
if (api.isPersistent(pc) && !api.isNew(pc) && !api.isDeleted(pc) && !api.isTransactional(pc)) {
// JDO [5.4.4] Can't return HOLLOW nondurable objects
throw new NucleusUserException(Localiser.msg("010005"));
}
}
pcById.put(ids[i], pc);
} else {
idsToFind.add(ids[i]);
}
}
if (!idsToFind.isEmpty() && l2CacheEnabled) {
// Check the L2 cache for those not found
Map pcsById = getObjectsFromLevel2Cache(idsToFind);
if (!pcsById.isEmpty()) {
// Found some so add to the values, and remove from the "toFind" list
Iterator<Map.Entry> entryIter = pcsById.entrySet().iterator();
while (entryIter.hasNext()) {
Map.Entry entry = entryIter.next();
pcById.put(entry.getKey(), entry.getValue());
idsToFind.remove(entry.getKey());
}
}
}
boolean performValidationWhenCached = nucCtx.getConfiguration().getBooleanProperty(PropertyNames.PROPERTY_FIND_OBJECT_VALIDATE_WHEN_CACHED);
List<ObjectProvider> opsToValidate = new ArrayList<>();
if (validate) {
if (performValidationWhenCached) {
// Mark all ObjectProviders for validation (performed at end)
Collection pcValues = pcById.values();
for (Object pc : pcValues) {
if (api.isTransactional(pc)) {
// This object is transactional, so no need to validate
continue;
}
// Mark this object for validation
ObjectProvider op = findObjectProvider(pc);
opsToValidate.add(op);
}
}
}
Object[] foundPcs = null;
if (!idsToFind.isEmpty()) {
// Try to find unresolved objects direct from the datastore if supported by the datastore (e.g ODBMS)
foundPcs = getStoreManager().getPersistenceHandler().findObjects(this, idsToFind.toArray());
}
int foundPcIdx = 0;
for (Object id : idsToFind) {
// Id target class could change due to inheritance level
Object idOrig = id;
Object pc = foundPcs != null ? foundPcs[foundPcIdx++] : null;
ObjectProvider op = null;
if (pc != null) {
// Object created by store plugin
op = findObjectProvider(pc);
putObjectIntoLevel1Cache(op);
} else {
// Object not found yet, so maybe class name is not correct inheritance level
ClassDetailsForId details = getClassDetailsForId(id, null, validate);
String className = details.className;
id = details.id;
if (details.pc != null) {
// Found in cache from updated id
pc = details.pc;
op = findObjectProvider(pc);
if (performValidationWhenCached && validate) {
if (!api.isTransactional(pc)) {
// Mark this object for validation
opsToValidate.add(op);
}
}
} else {
// Still not found so create a Hollow instance with the supplied field values
try {
Class pcClass = clr.classForName(className, (id instanceof DatastoreId) ? null : id.getClass().getClassLoader());
if (Modifier.isAbstract(pcClass.getModifiers())) {
// This class is abstract so impossible to have an instance of this type
throw new NucleusObjectNotFoundException(Localiser.msg("010027", IdentityUtils.getPersistableIdentityForId(id), className));
}
op = nucCtx.getObjectProviderFactory().newForHollow(this, pcClass, id);
pc = op.getObject();
if (!validate) {
// Mark the ObjectProvider as needing to validate this object before loading fields
op.markForInheritanceValidation();
}
// Cache it in case we have bidir relations
putObjectIntoLevel1Cache(op);
} catch (ClassNotResolvedException e) {
NucleusLogger.PERSISTENCE.warn(Localiser.msg("010027", IdentityUtils.getPersistableIdentityForId(id)));
throw new NucleusUserException(Localiser.msg("010027", IdentityUtils.getPersistableIdentityForId(id)), e);
}
if (validate) {
// Mark this object for validation
opsToValidate.add(op);
}
}
}
// Put in map under input id, so we find it later
pcById.put(idOrig, pc);
}
if (!opsToValidate.isEmpty()) {
// Validate the objects that need it
try {
getStoreManager().getPersistenceHandler().locateObjects(opsToValidate.toArray(new ObjectProvider[opsToValidate.size()]));
} catch (NucleusObjectNotFoundException nonfe) {
NucleusObjectNotFoundException[] nonfes = (NucleusObjectNotFoundException[]) nonfe.getNestedExceptions();
if (nonfes != null) {
for (int i = 0; i < nonfes.length; i++) {
Object missingId = nonfes[i].getFailedObject();
removeObjectFromLevel1Cache(missingId);
}
}
throw nonfe;
}
}
Object[] objs = new Object[ids.length];
for (int i = 0; i < ids.length; i++) {
Object id = ids[i];
objs[i] = pcById.get(id);
}
return objs;
}
Aggregations