ClassLoaderResolver clr = om.getClassLoaderResolver();
MappedStoreManager storeMgr = (MappedStoreManager)om.getStoreManager();
DatastoreAdapter dba = storeMgr.getDatastoreAdapter();
// Create an index listing for ALL (fetchable) fields in the result class.
final AbstractClassMetaData candidateCmd = om.getMetaDataManager().getMetaDataForClass(candidateClass, clr);
int fieldCount = candidateCmd.getNoOfManagedMembers() + candidateCmd.getNoOfInheritedManagedMembers();
Map columnFieldNumberMap = new HashMap(); // Map of field numbers keyed by the column name
statementExpressionIndex = new StatementExpressionIndex[fieldCount];
DatastoreClass tbl = storeMgr.getDatastoreClass(candidateClass.getName(), clr);
for (int fieldNumber = 0; fieldNumber < fieldCount; ++fieldNumber)
{
statementExpressionIndex[fieldNumber] = new StatementExpressionIndex();
AbstractMemberMetaData fmd = candidateCmd.getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber);
String fieldName = fmd.getName();
Class fieldType = fmd.getType();
if (fmd.getPersistenceModifier() != FieldPersistenceModifier.NONE)
{
JavaTypeMapping m = null;
if (tbl != null)
{
// Get the field mapping from the candidate table
m = tbl.getFieldMapping(fmd);
}
else
{
// Fall back to generating a mapping for this type - does this ever happen?
m = dba.getMapping(fieldType, storeMgr, clr);
}
if (m.includeInFetchStatement())
{
// Set mapping for this field since it can potentially be returned from a fetch
statementExpressionIndex[fieldNumber].setMapping(m);
String columnName = null;
if (fmd.getColumnMetaData() != null && fmd.getColumnMetaData().length > 0)
{
for (int colNum = 0;colNum<fmd.getColumnMetaData().length;colNum++)
{
columnName = fmd.getColumnMetaData()[colNum].getName();
columnFieldNumberMap.put(columnName, new Integer(fieldNumber));
}
}
else
{
columnName = storeMgr.getIdentifierFactory().newDatastoreFieldIdentifier(
fieldName, om.getOMFContext().getTypeManager().isDefaultEmbeddedType(fieldType),
FieldRole.ROLE_NONE).getIdentifier();
columnFieldNumberMap.put(columnName, new Integer(fieldNumber));
}
}
else
{
// Dont put anything in this position (field has no col in the result set)
}
}
else
{
// Dont put anything in this position (field has no col in the result set)
}
}
if (columnFieldNumberMap.size() == 0)
{
// None of the fields in the class have columns in the datastore table!
// TODO Localise the message
throw new JPOXUserException("SQL query class has no persistent fields in the SELECT : " +
candidateClass.getName()).setFatal();
}
// Generate id column field information for later checking the id is present
DatastoreClass table = storeMgr.getDatastoreClass(candidateClass.getName(), clr);
PersistenceCapableMapping idMapping = (PersistenceCapableMapping)table.getIDMapping();
String[] idColNames = new String[idMapping.getNumberOfDatastoreFields()];
boolean[] idColMissing = new boolean[idMapping.getNumberOfDatastoreFields()];
for (int i=0;i<idMapping.getNumberOfDatastoreFields();i++)
{
DatastoreMapping m = idMapping.getDataStoreMapping(i);
idColNames[i] = m.getDatastoreField().getIdentifier().toString();
idColMissing[i] = true;
}
// Generate discriminator/version information for later checking they are present
String discriminatorColName = table.getDiscriminatorMapping(false) != null ?
table.getDiscriminatorMapping(false).getDataStoreMapping(0).getDatastoreField().getIdentifier().toString() : null;
String versionColName = table.getVersionMapping(false) != null ?
table.getVersionMapping(false).getDataStoreMapping(0).getDatastoreField().getIdentifier().toString() : null;
boolean discrimMissing = (discriminatorColName != null);
boolean versionMissing = true;
if (versionColName == null)
{
versionMissing = false;
}
// Go through the fields of the ResultSet and map to the required fields in the candidate
// Note that we check the existence of the columns again here even though they were checked at compilation
// TODO This could be removed from here since its now done at compile time
ResultSetMetaData rsmd = rs.getMetaData();
HashSet remainingColumnNames = new HashSet(columnFieldNumberMap.size());
int colCount = rsmd.getColumnCount();
int[] datastoreIndex = null;
int[] versionIndex = null;
int[] matchedFieldNumbers = new int[colCount];
int fieldNumberPosition = 0;
for (int colNum=1; colNum<=colCount; ++colNum)
{
String colName = rsmd.getColumnName(colNum);
int fieldNumber = -1;
Integer fieldNum = (Integer)columnFieldNumberMap.get(colName);
if (fieldNum != null)
{
fieldNumber = fieldNum.intValue();
}
if (fieldNumber >= 0)
{
int[] exprIndices = null;
if (statementExpressionIndex[fieldNumber].getExpressionIndex() != null)
{
exprIndices = new int[statementExpressionIndex[fieldNumber].getExpressionIndex().length+1];
for (int i=0;i<statementExpressionIndex[fieldNumber].getExpressionIndex().length;i++)
{
exprIndices[i] = statementExpressionIndex[fieldNumber].getExpressionIndex()[i];
}
exprIndices[exprIndices.length-1] = colNum;
}
else
{
exprIndices = new int[] {colNum};
}
statementExpressionIndex[fieldNumber].setExpressionIndex(exprIndices);
remainingColumnNames.remove(colName);
matchedFieldNumbers[fieldNumberPosition++] = fieldNumber;
}
if (versionColName != null && colName.equals(versionColName))
{
// Identify the location of the version column
versionIndex = new int[1];
versionIndex[0] = colNum;
versionMissing = false;
}
if (candidateCmd.getIdentityType() == IdentityType.DATASTORE)
{
// Check for existence of id column, allowing for any RDBMS using quoted identifiers
if (columnNamesAreTheSame(dba, idColNames[0], colName))
{
datastoreIndex = new int[1];
datastoreIndex[0] = colNum;
idColMissing[0] = false;
}
}
else if (candidateCmd.getIdentityType() == IdentityType.APPLICATION)
{
for (int j=0;j<idColNames.length;j++)
{
// Check for existence of id column, allowing for any RDBMS using quoted identifiers
if (columnNamesAreTheSame(dba, idColNames[j], colName))