public QueryExpression getQueryStatement(DatastoreIdentifier candidateAlias)
{
if (storeMgr.getOMFContext().getTypeManager().isSupportedType(candidateFullClassName))
{
// SCO candidates, embedded in the source so just select the source table
QueryExpression qs = dba.newQueryStatement(sourceTable, candidateAlias, clr);
qs.select(sourceMapping);
return qs;
}
else
{
// FCO candidates
if (candidateTable == null)
{
// Candidate class has no table! so see if it has one subclass (with table) only and use that
AbstractClassMetaData acmd = storeMgr.getOMFContext().getMetaDataManager().getMetaDataForClass(candidateFullClassName, clr);
AbstractClassMetaData subclassCmds[] = storeMgr.getClassesManagingTableForClass(acmd, clr);
if (subclassCmds != null && subclassCmds.length == 1)
{
// Candidate uses "subclass-table" and only one subclass
candidateTable = storeMgr.getDatastoreClass(subclassCmds[0].getFullClassName(), clr);
candidateFullClassName = subclassCmds[0].getFullClassName();
}
else
{
throw new JPOXUserException("Attempt to create iterator for class " + candidateFullClassName +
" that is using \"subclass-table\" inheritance strategy and that doesnt have only 1 subclass." +
" This is not currently supported");
}
}
if (!includeSubclasses && withMetadata == null)
{
// No need to include the JPOXMETADATA if no subclasses considered
withMetadata = Boolean.FALSE;
}
// Find set of possible candidates
Set subclasses = null;
if (includeSubclasses)
{
subclasses = storeMgr.getSubClassesForClass(candidateFullClassName, true, clr);
Iterator iter = subclasses.iterator();
while (iter.hasNext())
{
String subclassName = (String)iter.next();
try
{
Class subclass = clr.classForName(subclassName);
if (Modifier.isAbstract(subclass.getModifiers()))
{
// Remove since abstract hence not instantiable
iter.remove();
}
}
catch (Exception e)
{
// Remove since class not found
iter.remove();
}
}
}
// Create the main query
String queryCandidateClassName = candidateFullClassName;
try
{
Class candidateClass = clr.classForName(candidateFullClassName);
if (Modifier.isAbstract(candidateClass.getModifiers()))
{
// Candidate is abstract so not instantiable so try to find a subclass using same table
Iterator iter = subclasses.iterator();
while (iter.hasNext())
{
String subclassName = (String)iter.next();
DatastoreClass subclassTable = storeMgr.getDatastoreClass(subclassName, clr);
if (subclassTable == candidateTable)
{
// Input candidate is abstract but this subclass uses the same table so swap it for that
queryCandidateClassName = subclassName;
iter.remove(); // Not needed as subclass now since used as primary class
break;
}
}
}
}
catch (Exception e) {}
QueryExpression stmt = getQueryForElement(queryCandidateClassName, candidateTable, false, candidateAlias);
if (includeSubclasses)
{
// Add a select for each subclass elements, and union the selects
Iterator iterator = subclasses.iterator();
while (iterator.hasNext())
{
String subCandidateType = (String) iterator.next();
DatastoreClass subCandidateTable = storeMgr.getDatastoreClass(subCandidateType, clr);
if (subCandidateTable != null)
{
// Add UNION to any subclasses that have their own table
// This omits those using "subclass-table".
// Those will have their own subclasses where they store their objects.
QueryExpression stmt_subclass = getQueryForElement(subCandidateType, subCandidateTable,
false, candidateAlias);
stmt.union(stmt_subclass);
}
}
}
if (allowsNull && sourceTable instanceof SCOTable)
{
// JoinTable case where we select the join table and join to the element table, and need to allow for nulls
// Add a SELECT for nulls in the join table, and UNION it to the main query
// TODO Add statement for nulls [CORE-2994]
/**
* SELECT NULL AS JPOXMETADATA
* FROM JOINTBL THIS
* LEFT OUTER JOIN ELEM_TBL ELEM1 ON ELEM1.ID = THIS.ELEM_ID
* WHERE THIS.ELEM_ID IS NULL
*/
QueryExpression nullStmt = getQueryForElement(candidateFullClassName,
storeMgr.getDatastoreClass(candidateFullClassName, clr), true, candidateAlias);
ScalarExpression elemIdExpr = sourceMapping.newScalarExpression(nullStmt, nullStmt.getMainTableExpression());
nullStmt.andCondition(new NullLiteral(nullStmt).eq(elemIdExpr));
stmt.union(nullStmt);
}
return stmt;
}