public final String rewriteName(String name, Tag currentTag)
throws ExpressionEvaluationException
{
if (_logger.isDebugEnabled()) _logger.debug("rewrite expression \"" + name + "\"");
IDataAccessProvider dap = getCurrentProvider(currentTag);
// if the DAP is null, there is no rewriting to do
if (dap == null)
return name;
// given a hierarchy of "container.container.container.item.someProp", the correct parent needs
// to be found so that expression rewriting can happen correctly.
//
// ensure that this expression contains container.item
Expression parsed = getExpressionEvaluator().parseExpression(name);
assert parsed != null;
int containerCount = 0;
List tokens = parsed.getTokens();
for (int i = 0; i < tokens.size(); i++) {
String tok = tokens.get(i).toString();
if (i == 0) {
if (!tok.equals("container"))
break;
else
continue;
}
// this skips the "current" IDataAccessProvider
else if (tok.equals("container"))
containerCount++;
else if (tok.equals("item"))
break;
}
if (_logger.isDebugEnabled()) _logger.debug("container parent count: " + containerCount);
// now walk up the DataAccessProvier hierarchy until the top-most parent is found
// the top-most parent is the first one that does not reference "container.item" but
// is bound directly to a specific object such as "actionForm" or "pageFlow". This
// handles the case where a set of nested IDataAccessProvider tags are "skipped" by
// an expression like "container.container.container.item.foo". In order to find
// the correct root to start rewriting the names, one needs to walk up three
// DAPs in order to find the correct root from which to start.
//
// In general, containerCount is zero here for the "container.item.foo" case.
for (int i = 0; i < containerCount; i++) {
dap = dap.getProviderParent();
}
// now, the top-most DAP parent is known
assert dap != null;
// strip off the "container.item" from the expression that is being rewritten
// this should be two tokens into the expression.
if (containerCount > 0) {
name = parsed.getExpression(containerCount);
}
// now, change the binding context of the parent DAP hierarchy to create a
// String that looks like "actionForm.customers[42].order[12].lineItem[2].name"
// note, this is done without using the expression that was passed-in and
// is derived entirely from the IDataAccessProvider parent hierarchy.
String parentNames = rewriteNameInternal(dap);
if (_logger.isDebugEnabled()) _logger.debug("name hierarchy: " + parentNames + " name: " + name);
// with a newly re-written expression prefix, substitute this fully-qualified binding
// string into the given expression for "container.item".
String newName = changeContext(name, "container.item", parentNames, dap.getCurrentIndex());
if (_logger.isDebugEnabled()) _logger.debug("rewrittenName: " + newName);
return newName;
}