/** * INTERNAL: Return the value of the field from the row or a value holder on the query to obtain * the object. Check for batch + aggregation reading. */ @Override public Object valueFromRow( AbstractRecord row, JoinedAttributeManager joinManager, ObjectBuildingQuery sourceQuery, AbstractSession executionSession) throws DatabaseException { // If any field in the foreign key is null then it means there are no referenced objects for (Enumeration enumeration = getFields().elements(); enumeration.hasMoreElements(); ) { DatabaseField field = (DatabaseField) enumeration.nextElement(); if (row.get(field) == null) { return getIndirectionPolicy().nullValueFromRow(); } } if (getTypeField() != null) { // If the query used batched reading, return a special value holder, // or retrieve the object from the query property. if (sourceQuery.isReadAllQuery() && (((ReadAllQuery) sourceQuery).isAttributeBatchRead(getDescriptor(), getAttributeName()) || shouldUseBatchReading())) { return batchedValueFromRow(row, ((ReadAllQuery) sourceQuery)); } // If the field is empty we cannot load the object because we do not know what class it will // be if (row.get(getTypeField()) == null) { return getIndirectionPolicy().nullValueFromRow(); } Class implementerClass = (Class) getImplementorForType(row.get(getTypeField()), executionSession); ReadObjectQuery query = (ReadObjectQuery) getSelectionQuery().clone(); query.setReferenceClass(implementerClass); query.setSelectionCriteria(getSelectionCriteria()); query.setDescriptor(null); // Must set to null so the right descriptor is used if (sourceQuery.isObjectLevelReadQuery() && (sourceQuery.shouldCascadeAllParts() || (sourceQuery.shouldCascadePrivateParts() && isPrivateOwned()) || (sourceQuery.shouldCascadeByMapping() && this.cascadeRefresh))) { query.setShouldRefreshIdentityMapResult(sourceQuery.shouldRefreshIdentityMapResult()); query.setCascadePolicy(sourceQuery.getCascadePolicy()); query.setShouldMaintainCache(sourceQuery.shouldMaintainCache()); // For flashback. if (((ObjectLevelReadQuery) sourceQuery).hasAsOfClause()) { query.setAsOfClause(((ObjectLevelReadQuery) sourceQuery).getAsOfClause()); } // CR #4365 - used to prevent infinit recursion on refresh object cascade all query.setQueryId(sourceQuery.getQueryId()); } return getIndirectionPolicy().valueFromQuery(query, row, executionSession); } else { return super.valueFromRow(row, joinManager, sourceQuery, executionSession); } }