public ExpState initialize(Select sel, ExpContext ctx, int flags) {
PathExpState pstate = new PathExpState(sel.newJoins());
boolean key = false;
boolean forceOuter = false;
ClassMapping rel = _candidate;
// iterate to the final field
ClassMapping owner;
ClassMapping from, to;
Action action;
Variable var;
Iterator itr = (_actions == null) ? null : _actions.iterator();
FieldMapping field;
while (itr != null && itr.hasNext()) {
action = (Action) itr.next();
// treat subqueries like variables for alias generation purposes
if (action.op == Action.VAR)
pstate.joins = pstate.joins.setVariable((String) action.data);
else if (action.op == Action.SUBQUERY)
pstate.joins = pstate.joins.setSubselect((String) action.data);
else if (action.op == Action.UNBOUND_VAR) {
// unbound vars are cross-joined to the candidate table
var = (Variable) action.data;
rel = (ClassMapping) var.getMetaData();
pstate.joins = pstate.joins.setVariable(var.getName());
pstate.joins = pstate.joins.crossJoin(_candidate.getTable(),
rel.getTable());
} else {
// move past the previous field, if any
field = (action.op == Action.GET_XPATH) ? (FieldMapping) _xmlfield :
(FieldMapping) action.data;
if (pstate.field != null) {
// if this is the second-to-last field and the last is
// the related field this field joins to, no need to
// traverse: just use this field's fk columns
if (!itr.hasNext() && (flags & JOIN_REL) == 0
&& isJoinedField(pstate.field, key, field)) {
pstate.cmpfield = field;
break;
}
rel = traverseField(pstate, key, forceOuter, false);
}
// mark if the next traversal should go through
// the key rather than value
key = action.op == Action.GET_KEY;
forceOuter |= action.op == Action.GET_OUTER;
// get mapping for the current field
pstate.field = field;
owner = pstate.field.getDefiningMapping();
if (pstate.field.getManagement()
!= FieldMapping.MANAGE_PERSISTENT)
throw new UserException(_loc.get("non-pers-field",
pstate.field));
// find the most-derived type between the declared relation
// type and the field's owner, and join from that type to
// the lesser derived type
if (rel != owner && rel != null) {
if (rel.getDescribedType().isAssignableFrom
(owner.getDescribedType())) {
from = owner;
to = rel;
} else {
from = rel;
to = owner;
}
for (; from != null && from != to;
from = from.getJoinablePCSuperclassMapping())
pstate.joins = from.joinSuperclass(pstate.joins, false);
}
// nothing more to do from here on as we encountered an xpath action
if (action.op == Action.GET_XPATH)
break;
}