*/
public Object[] findObjects(Object[] identities, boolean validate)
{
assertIsOpen();
ApiAdapter api = getApiAdapter();
Object[] objs = new Object[identities.length];
Object[] ids = new Object[identities.length];
List idsToFind = new ArrayList();
for (int i=0;i<identities.length;i++)
{
if (identities[i] == null)
{
throw new NucleusUserException(LOCALISER.msg("010044"));
}
// Translate the identity if required
if (getNucleusContext().getIdentityStringTranslator() != null && identities[i] instanceof String)
{
// DataNucleus extension to translate input identities into valid persistent identities.
IdentityStringTranslator translator = getNucleusContext().getIdentityStringTranslator();
ids[i] = translator.getIdentity(this, (String)identities[i]);
}
else
{
ids[i] = identities[i];
}
// Find the object in the cache if possible
Object pc = getObjectFromCache(ids[i]);
if (pc != null)
{
objs[i] = pc;
if (ids[i] instanceof SCOID)
{
if (api.isPersistent(pc) && !api.isNew(pc) && !api.isDeleted(pc) && !api.isTransactional(pc))
{
// JDO2 [5.4.4] Can't return HOLLOW nondurable objects
throw new NucleusUserException(LOCALISER.msg("010005"));
}
}
}
else
{
idsToFind.add(ids[i]);
}
}
// Try to find missing objects direct from the datastore if supported by the StoreManager
Object[] foundPcs = null;
foundPcs = getStoreManager().getPersistenceHandler().findObjects(this, idsToFind.toArray());
int foundPcIdx = 0;
for (int i=0;i<ids.length;i++)
{
Object id = ids[i];
Object pc = objs[i];
boolean fromCache = true;
if (pc == null)
{
// Try the "findObjects" results in case supported by StoreManager
pc = foundPcs[foundPcIdx];
foundPcIdx++;
}
StateManager sm = null;
if (pc == null)
{
// Object not found yet, so work out class name
String className = null;
String originalClassName = null;
boolean checkedClassName = false;
if (id instanceof SCOID)
{
throw new NucleusUserException(LOCALISER.msg("010006"));
}
else if (id instanceof DatastoreUniqueOID)
{
// Should have been found using "persistenceHandler.findObject()"
throw new NucleusObjectNotFoundException(LOCALISER.msg("010026"), id);
}
else if (api.isDatastoreIdentity(id) || api.isSingleFieldIdentity(id))
{
// OID or SingleFieldIdentity, so check that the implied class is managed
originalClassName = getStoreManager().manageClassForIdentity(id, clr);
}
else
{
// We dont know the object class so try to deduce it from what is known by the StoreManager
originalClassName = getStoreManager().getClassNameForObjectID(id, clr, this);
checkedClassName = true;
}
if (validate)
{
// Validate the inheritance level
className =
(checkedClassName ? originalClassName : getStoreManager().getClassNameForObjectID(id, clr, this));
if (className == null)
{
throw new NucleusObjectNotFoundException(LOCALISER.msg("010026"), id);
}
if (originalClassName != null && !originalClassName.equals(className))
{
// Inheritance check implies different inheritance level, so retry
if (api.isDatastoreIdentity(id))
{
// Create new OID using correct target class, and recheck cache
id = OIDFactory.getInstance(getNucleusContext(), className, ((OID)id).getKeyValue());
pc = getObjectFromCache(id);
}
else if (api.isSingleFieldIdentity(id))
{
// Create new SingleFieldIdentity using correct targetClass, and recheck cache
id = api.getNewSingleFieldIdentity(id.getClass(), clr.classForName(className),
api.getTargetKeyForSingleFieldIdentity(id));
pc = getObjectFromCache(id);
}
}
}
else
{
className = originalClassName;
}
if (pc == null)
{
// Still not found so create a Hollow instance with the supplied field values
try
{
Class pcClass = clr.classForName(className, (id instanceof OID) ? null : id.getClass().getClassLoader());
sm = (StateManager) ObjectProviderFactory.newForHollow(this, pcClass, id);
pc = sm.getObject();
fromCache = false;
}
catch (ClassNotResolvedException e)
{
NucleusLogger.PERSISTENCE.warn(LOCALISER.msg("010027", getIdentityAsString(id)));
throw new NucleusUserException(LOCALISER.msg("010027", getIdentityAsString(id)), e);
}
}
}
// TODO Perform locate of uncached objects in single operation using persistenceHandler.locateObjects
boolean performValidationWhenCached =
(context.getPersistenceConfiguration().getBooleanProperty("datanucleus.findObject.validateWhenCached"));
if (validate && (!fromCache || performValidationWhenCached))
{
if (fromCache && pc != null && api.isTransactional(pc))
{
// JDO2 [12.6.5] Already an object with the same id and it's transactional, so use it
objs[i] = pc;
continue;
}