boolean bSkipInstance = (m_instanceList.getCount() < m_nOffset);
for (int nQuery = 0, nQueryCount = m_query.getOutputQueryCount(); nQuery < nQueryCount; ++nQuery)
{
Query query = m_query.getOutputQuery(nQuery);
Attribute assoc = query.getAttribute();
boolean bIdentity = query.isIdentity();
Instance container;
Attribute reverse;
OID oid;
// First output query must be main query node.
assert (nQuery == 0) == (query == m_query);
// Query ordinal is the output query ordinal (unless query is joined heterogeneously).
assert nQuery == query.getOrdinal() || query.getRoot() != m_query;
// Query ordinal is, by definition, the output query ordinal of its root.
assert query.getRoot().getOutputQuery(query.getOrdinal()) == query;
// Get the query class instance OID
if (query == m_query)
{
container = null;
reverse = null;
oid = (bIdentity) ? getKey(query.getItem()) : null;
}
else
{
assert bIdentity;
container = m_instanceArray[query.getParent().getOrdinal()];
if (container == null || !assoc.getMetaclass().isUpcast(container.getMetaclass()))
{
if (query.getRoot() == m_query)
{
m_instanceArray[query.getOrdinal()] = null;
}
continue;
}
assoc = container.getMetaclass().getDerivedAttribute(assoc);
reverse = assoc.getReverse();
if (reverse != null && reverse.isCollection())
{
reverse = null;
}
oid = getKey(query.getParentItem());
}
InstanceList instanceList;
boolean bAdd = true;
if (container == null)
{
instanceList = m_instanceList;
}
else
{
Object value = container.getOldValueDirect(assoc.getOrdinal());
if (value == Undefined.VALUE)
{
if (assoc.isCollection())
{
instanceList = new InstanceArrayList();
instanceList.setAssociation(container, assoc, true);
instanceList.setLazy(false);
container.setOldValueDirect(assoc.getOrdinal(), instanceList);
}
else
{
instanceList = null;
if (oid == null)
{
container.setOldValueDirect(assoc.getOrdinal(), null);
}
}
}
else
{
if (assoc.isCollection() && !(value instanceof Undefined))
{
instanceList = (InstanceList)value;
instanceList.setLazy(false);
}
else
{
instanceList = null;
bAdd = false;
}
}
}
Metaclass metaclass;
if (bIdentity)
{
if (oid == null)
{
if (query.getRoot() == m_query)
{
m_instanceArray[query.getOrdinal()] = null;
}
continue;
}
if (query.getRoot() != m_query && !query.isLazy())
{
if (!bSkipInstance)
{
query.addParentInstance(container, oid);
}
continue;
}
Field field = query.getTypeCodeField();
if (field != null)
{
metaclass = query.getPersistenceMapping().findMetaclassByTypeCode(getValue(field));
if (metaclass == null)
{
m_instanceArray[query.getOrdinal()] = null;
continue;
}
}
else
{
metaclass = getMetaclass(query);
}
}
else
{
metaclass = getMetaclass(query);
}
InstanceRef ref = m_query.getInvocationContext().findInstanceRef(metaclass, oid);
Instance instance = (ref == null) ? null : ref.getInstance();
// Check if the instance has already been retrieved
if (instance != null)
{
// Already retrieved instance
if (instance.isLazy())
{
if (query.isLazy())
{
if (!metaclass.isUpcast(instance.getLazyMetaclass()))
{
instance.setLazyMetaclass(metaclass);
}
}
else
{
instance.setMetaclass(metaclass);
}
}
if (instanceList != null)
{
bAdd = !instanceList.contains(instance);
if (bAdd &&
container == null &&
m_nMaxCount >= 0 &&
instanceList.getCount() == m_nOffset + m_nMaxCount)
{
m_bEOF = bDiscardExtra;
m_bEOP = !bDiscardExtra;
return false;
}
}
if (bAdd)
{
switch (instance.getState())
{
case Instance.DELETED:
bAdd = false;
break;
case Instance.DIRTY:
if (reverse != null)
{
Object reverseValue = instance.getValueDirect(reverse.getOrdinal());
if (reverseValue != Undefined.VALUE && reverseValue != container)
{
bAdd = false;
}
}
break;
}
if (!bAdd && instanceList == null)
{
if (container.getValueDirect(assoc.getOrdinal()) == Undefined.VALUE)
{
// Set the new value to null, old value to the retrieved instance
container.setValueDirect(assoc.getOrdinal(), null);
}
bAdd = true;
}
}
if (m_instanceSet.get(query, instance) == null)
{
// Merge the not yet retrieved attribute values
if (!bSkipInstance)
{
// Overwrite only if the instance is clean
boolean bOverwrite = (instance.getUnitOfWork() == null);
Field lockingField = query.getLockingField();
if (lockingField != null)
{
Attribute lockingAttribute = lockingField.getAttribute();
Object oldValue = instance.getNewValueDirect(lockingAttribute.getOrdinal());
if (oldValue != Undefined.VALUE)
{
// Check the old lock value
Primitive primitive = (Primitive)lockingAttribute.getType();
Object value = getValue(lockingField);
if (((Boolean)primitive.findNEFunction(primitive).invoke(oldValue, value)).booleanValue())
{
// The lock values do not match
// If the instance is dirty/deleted or share-locked, throw an exception
if (!bOverwrite || ref.isLocked())
{
throw new OptimisticLockException(instance);
}
// Discard all the instance attributes
for (int i = 0, n = metaclass.getInstanceAttributeCount(); i != n; ++i)
{
discard(instance, metaclass.getInstanceAttribute(i));
}
instance.setOldValueDirect(lockingAttribute.getOrdinal(), value);
}
else
{
if (bOverwrite)
{