Assignment to EL variables turns out to be more complicated because an
EL variable
1. Takes a ValueExpression, and not a Object instance, and
2. Is "mapped, resolved, and bound" at parse time (EL 1.16)
I finally got it working I way I want it to. I have also updated the
wiki page, reproduced here.
================
Assignment
Syntax
expr-a = expr-b
* If expr-a is an identifier (with value name-a) and name-a is an EL
variable (i.e. it is defined in the VariableMapper), or name-a is
not resolved by the ELResolver
o Set name-a in the VariableMapper with the ValueExpression
for expr-b, without evaluation.
o Evaluate expr-b to value-b.
* Else
o Evaluate expr-b to value-b.
o Evaluate expr-a, up to (but not including) the last property
resolution.
o If expr-a is a . or [] operator, evaluate the base to
base-a, and the property to prop-a.
+ If base-a is null, throw a BeanNotFoundException.
+ If prop-a is null, throw a PropertyNotFoundException.
o Invoke ValueExpression.setValue for expr-a:
expr-a.setValue(context, value-b);
* If ValueEpxression.getValue was called to initiate this expression
evaluation, return value-b.
* If ValueExpression.setValue was called to initiate this expression
evaluation, throw a PropertyNotWritableException.
The last two bullet items ensure that the assignment operator returns
the correct value, and that it is not writable.
Note that EL variables are bound at parse time, so their assignment in
an expression only takes effect after the expression is evaluated. This
can lead to some unexpected behaviors. For example, consider the following.
elp = new ELProcessor();
elp.setVariable("x", "10");
int n = elp.getValue("(x = 20) + x}";
The value of n is 30 instead of 40, because the value of x is 10 when
the expression is parsed.
Operator Precedence
It has the lowest precedence, lower than the ?: operator.
Example
"x = a.b"
If x does not exist then same as calling defineVariable("x", "#{a.b});
"x.y = a.b"
Set x.y = a.b. Error if x does not exist.
==============
The inclusion of variables in assignment complicates things a bit, but
is well worth it, I think. :-)
I had a little trouble getting this to work, because the current
implementation takes a copy of the VariableMapper at parse time, without
the ability to set new values to variables at evaluation time. I am
sure Mark would run into the same issue when he implements this, since
we have basically the same code base. :-)
Kin-man