return domainObject;
}
public Object getFromIdentityMap(Expression selectionCriteria, Class theClass, Record translationRow, int valueHolderPolicy, boolean conforming, boolean shouldReturnInvalidatedObjects, ClassDescriptor descriptor) {
UnitOfWorkImpl unitOfWork = (conforming) ? (UnitOfWorkImpl)this.session : null;
this.session.startOperationProfile(SessionProfiler.Caching);
try {
if (selectionCriteria != null) {
// PERF: Avoid clone of expression.
ExpressionBuilder builder = selectionCriteria.getBuilder();
if (builder.getSession() == null) {
builder.setSession(this.session.getRootSession(null));
builder.setQueryClass(theClass);
}
}
IdentityMap map = getIdentityMap(descriptor, false);
// Bug #321041 - if policy is set to trigger indirection, then make a copy of the cache keys collection
// and iterate over that to avoid a ConcurrentModificationException.
// This happens when the indirect attribute is of the same type (or has same mapped superclass) as
// the parent object. EclipseLink inserts the object into the same collection it is iterating over,
// which results in a ConcurrentModificationException.
// There's a slight performance hit in copying the collection, but we are already taking a hit
// by triggering indirection in the first place.
boolean copyKeyCollection = valueHolderPolicy == InMemoryQueryIndirectionPolicy.SHOULD_TRIGGER_INDIRECTION;
Vector cacheKeys = null;
if (copyKeyCollection) {
cacheKeys = new Vector(map.getSize());
for (Enumeration cacheEnum = map.keys(); cacheEnum.hasMoreElements();) {
CacheKey key = (CacheKey)cacheEnum.nextElement();
cacheKeys.add(key);
}
}
Enumeration cacheEnum = copyKeyCollection ? cacheKeys.elements() : map.keys();
// cache the current time to avoid calculating it every time through the loop
long currentTimeInMillis = System.currentTimeMillis();
while (cacheEnum.hasMoreElements()) {
CacheKey key = (CacheKey)cacheEnum.nextElement();
if (!shouldReturnInvalidatedObjects && descriptor.getCacheInvalidationPolicy().isInvalidated(key, currentTimeInMillis)) {
continue;
}
Object object = key.getObject();
// Bug # 3216337 - key.getObject() should check for null; object may be GC'd (MWN)
if (object == null) {
continue;
}
// Must check for inheritance.
if ((object.getClass() == theClass) || (theClass.isInstance(object))) {
if (selectionCriteria == null) {
// bug 2782991: if first found was deleted nothing returned.
if (!(conforming && unitOfWork.isObjectDeleted(object))) {
return object;
}
}
//CR 3677 integration of a ValueHolderPolicy
try {
if (selectionCriteria.doesConform(object, this.session, (AbstractRecord)translationRow, valueHolderPolicy)) {
// bug 2782991: if first found was deleted nothing returned.
if (!(conforming && unitOfWork.isObjectDeleted(object))) {
return object;
}
}
} catch (QueryException queryException) {
if (queryException.getErrorCode() == QueryException.MUST_INSTANTIATE_VALUEHOLDERS) {
if (valueHolderPolicy == InMemoryQueryIndirectionPolicy.SHOULD_IGNORE_EXCEPTION_RETURN_CONFORMED) {
// bug 2782991: if first found was deleted nothing returned.
if (!(conforming && unitOfWork.isObjectDeleted(object))) {
return object;
}
} else if (valueHolderPolicy == InMemoryQueryIndirectionPolicy.SHOULD_IGNORE_EXCEPTION_RETURN_NOT_CONFORMED) {
// For bug 2667870 just skip this item, but do not abort.
} else {