joo.classLoader.prepare("package joox.el",[

"import joo.lang.JOObject",
"import joox.cache.DependencyTracker",
"import joo.util.PropertyAware",""],

"public class ELResolver",function($jooPublic,$jooPrivate){with(joox.el)with($jooPublic)with($jooPrivate)return[

"public function getValue",function(elContext,base,property){
if(base==null||typeof base!="object"){
var valueExp=elContext.getVariableMapper().resolveVariable(property);
return valueExp?valueExp.getValue(elContext):undefined;
}
DependencyTracker.addDependency(base,property);
if(typeof property=="string"){
return PropertyAware.getProperty(base,property);
}

return base[property];
},

"public function getType",function(elContext,base,property){
return typeof base[property];
},

"public function isReadOnly",function(elContext,base,property){
return false;

},

"public function setValue",function(elContext,base,property,value){
var oldValue;
if(typeof property=="string"){
oldValue=PropertyAware.getProperty(base,property);
PropertyAware.setProperty(base,property,value);
}else{
oldValue=base[property];
base[property]=value;
}
if(!JOObject.equal(oldValue,value)){
DependencyTracker.fireDependency(base,property);
}




},
];},[]
);joo.classLoader.prepare("package org.joo.el",[

"import joox.el.ELContext",
"import org.joo.el.Literal",
"import org.joo.el.AbstractExpression",
"import joox.el.ELContext",""],

"public class ConditionalExpression extends AbstractExpression",function($jooPublic,$jooPrivate){with(org.joo.el)with($jooPublic)with($jooPrivate)return[function(){joo.classLoader.init(Literal,ELContext);},

"public static function create",function(conditionExp,thenExp,elseExp){
if(conditionExp.constructor===Literal){
if(thenExp.constructor===Literal&&elseExp.constructor===Literal){
var conditionalExp=new ConditionalExpression(conditionExp,thenExp,elseExp);
return new Literal(conditionalExp.evaluate(ELContext.instance));
}else{
return conditionExp.evaluate(ELContext.instance)?thenExp:elseExp;
}
}
return new ConditionalExpression(conditionExp,thenExp,elseExp);
},
"public function ConditionalExpression",function(conditionExp,thenExp,elseExp){
this[$super]();
this[$conditionExp]=conditionExp;
this[$thenExp]=thenExp;
this[$elseExp]=elseExp;
},
"override public function getLabel",function(){
return"? ... :";
},
"override public function getSubexpressions",function(){
return[this[$conditionExp],this[$thenExp],this[$elseExp]];
},
"override public function evaluate",function(elContext){
return this[$conditionExp].evaluate(elContext)?this[$thenExp].evaluate(elContext):this[$elseExp].evaluate(elContext);
},
"override public function toString",function(){
return["(",this[$conditionExp],"?",this[$thenExp],":",this[$elseExp],")"].join(" ");
},
"private var",{conditionExp: undefined},
"private var",{thenExp: undefined},
"private var",{elseExp: undefined},
];},["create"]
);joo.classLoader.prepare("package org.joo.el",[

"import joo.util.RegExpUtil",
"import org.joo.el.Terminal",
"import org.joo.el.Identifier",
"import org.joo.el.BeanExpression",
"import org.joo.el.PropertyExpression",
"import org.joo.el.UnaryExpression",
"import org.joo.el.BinaryExpression",
"import org.joo.el.ConditionalExpression",
"import org.joo.el.Literal",
"import org.joo.el.TokenHashSet",""],

"public class ELParser",function($jooPublic,$jooPrivate){with(org.joo.el)with($jooPublic)with($jooPrivate)return[function(){joo.classLoader.init(Literal,Terminal,Identifier);},

"public static const",{EXPRESSION_START_REG_EXP:/(?:^|[^\\])(#\{)/g},
"public static const",{TOKENS:function(){return({
COLON:new Terminal("COLON",[":"]),
QUESTIONMARK:new Terminal("QUESTIONMARK",["?"]),
BRACKET_OPEN:new Terminal("BRACKET_OPEN",["("]),
BRACKET_CLOSE:new Terminal("BRACKET_CLOSE",[")"]),
AND:new Terminal("AND",["&&","and"]),
OR:new Terminal("OR",["||","or"]),
PLUS:new Terminal("PLUS",["+"]),
MINUS:new Terminal("MINUS",["-"]),
MULT:new Terminal("MULT",["*"]),
DIV:new Terminal("DIV",["/","div"]),
MOD:new Terminal("MOD",["%","mod"]),
GT:new Terminal("GT",[">","gt"]),
LT:new Terminal("LT",["<","lt"]),
GE:new Terminal("GE",[">=","ge"]),
LE:new Terminal("LE",["<=","le"]),
EQ:new Terminal("EQ",["==","eq"]),
NE:new Terminal("NE",["!=","ne"]),
NOT:new Terminal("NOT",["!","not"]),
EMPTY:new Terminal("EMPTY",["empty"]),
DOT:new Terminal("DOT",["."]),
SQUARE_BRACKET_OPEN:new Terminal("SQUARE_BRACKET_OPEN",["["]),
SQUARE_BRACKET_CLOSE:new Terminal("SQUARE_BRACKET_CLOSE",["]"]),
COMMA:new Terminal("COMMA",[","]),
WHITE_SPACE:new Terminal("WHITE_SPACE",[" "]),
EXPRESSION_START:new Terminal("EXPRESSION_START",["#{"]),
EXPRESSION_END:new Terminal("EXPRESSION_END",["}"]),
EOS:new Terminal("EOS",[])
});}},
"public static const",{IDENTIFIER:"[a-zA-Z\\$_][a-zA-Z\\$_]*"},
"public static const",{INTEGER_LITERAL:"[0-9]+"},
"public static const",{INTEGER_REG_EXP:function(){return(RegExpUtil.compile("^("+INTEGER_LITERAL+")$"));}},
"public static const",{EXPONENT:"([eE][\\+-]?[0-9]+)"},
"public static const",{FLOATING_POINT_LITERAL:function(){return("[0-9]+\\.[0-9]*"+EXPONENT+"?|\\.[0-9]+"+EXPONENT+"?|[0-9]+"+EXPONENT);}},
"public static const",{FLOATING_POINT_REG_EXP:function(){return(RegExpUtil.compile("^("+FLOATING_POINT_LITERAL+")$"));}},
"public static const",{STRING_LITERAL:"'([^'\\\\]|\\\\'|\\\\\\\\)*'"
+"|\"([^\"\\\\]|\\\\\"|\\\\\\\\)*\""},
"public static const",{STRING_REG_EXP:function(){return(RegExpUtil.compile("^("+STRING_LITERAL+")$"));}},
"public static const",{BOOLEAN_LITERAL:"true|false"},
"public static const",{BOOLEAN_REG_EXP:function(){return(RegExpUtil.compile("^("+BOOLEAN_LITERAL+")$"));}},
"public static const",{NULL_LITERAL:"null"},
"public static const",{LITERAL:function(){return(FLOATING_POINT_LITERAL+"|"+INTEGER_LITERAL+"|"+STRING_LITERAL+"|"+BOOLEAN_LITERAL+"|"+NULL_LITERAL);}},
"public static const",{LITERAL_REG_EXP:function(){return(RegExpUtil.compile("^("+LITERAL+")$"));}},
"public static const",{TOKEN:function(){
var tokens=[IDENTIFIER,"|",LITERAL];
var SPECIAL_CHARS=RegExpUtil.compile("(\\\\|\\^|\\$|\\*|\\+|\\?|\\.|\\(|\\)|\\||\\{|\\}|\\,|\\[|\\])","g");
for(var token in Terminal.MATCHES){
tokens.push("|");
tokens.push(token.replace(SPECIAL_CHARS,"\\$1"));
}
return tokens.join("");
}},
"public static const",{TOKEN_REG_EXP:function(){return(RegExpUtil.compile(TOKEN,"g"));}},
"public static const",{BINARY_OP:function(){return(new TokenHashSet([
TOKENS.AND,TOKENS.OR,TOKENS.PLUS,TOKENS.MINUS,TOKENS.MULT,
TOKENS.DIV,TOKENS.MOD,TOKENS.GT,TOKENS.LT,TOKENS.GE,
TOKENS.LE,TOKENS.EQ,TOKENS.NE
]));}},
"public static const",{UNARY_OP:function(){return(new TokenHashSet([
TOKENS.MINUS,TOKENS.NOT,TOKENS.EMPTY
]));}},
"public static const",{VALUE_SUFFIX:function(){return(new TokenHashSet([
TOKENS.DOT,TOKENS.SQUARE_BRACKET_OPEN
]));}},

"public function toHTML",function(exp){
var out=[exp.getLabel()];
var subexps=exp.getSubexpressions();
if(subexps.length>0){
out.push("<ul>");
for(var i=0;i<subexps.length;++i){
out.push("<li>");
out.push(this.toHTML(subexps[i]));
out.push("</li>");
}
out.push("</ul>");
}
return out.join("");
},
"public function getType",function(value){
if(value==null){
return"null";
}
var type=typeof value;
if(type=="number"){
type=ELParser.FLOATING_POINT_REG_EXP.test(value)?"float":"integer";
}
return type;
},
"private function startTokenize",function(el){
this[$el]=el;
this[$token]=undefined;
this[$tokenEndPos]=0;
this[$nextToken]();
},
"private function nextToken",function(){

var startIndex=this[$tokenEndPos];
if(startIndex==this[$el].length){

return this[$setToken](TOKENS.EOS,startIndex,0);
}
var thisToken=this[$token];
var match;
if(!thisToken||thisToken==TOKENS.EXPRESSION_END){
EXPRESSION_START_REG_EXP.lastIndex=startIndex==0?0:startIndex-1;
match=EXPRESSION_START_REG_EXP.exec(this[$el]);
var string;
if(match){
var endIndex=match[0].length==3?match.index+1:match.index;
string=this[$el].substring(startIndex,endIndex);
}else{
string=this[$el].substring(startIndex);
}
if(string){
return this[$setToken](new Literal(string.replace(/\\#\{/g,"#{")),startIndex,string.length);
}
}
TOKEN_REG_EXP.lastIndex=startIndex;
var WHITE_SPACE=TOKENS.WHITE_SPACE;
while((match=TOKEN_REG_EXP.exec(this[$el]))!=null){
if(match.index!=startIndex){
throw"Syntax error: No token starts at "+startIndex+".";
}

var c=match[0];


thisToken=Terminal.MATCHES[c];
if(!thisToken){
var literalValue;
if(INTEGER_REG_EXP.test(c)){
literalValue=parseInt(c);
}else if(FLOATING_POINT_REG_EXP.test(c)){
literalValue=parseFloat(c);
}else if(STRING_REG_EXP.test(c)){
literalValue=c.substring(1,c.length-1);
}else if(BOOLEAN_REG_EXP.test(c)){
literalValue=c=="true";
}else if(c==NULL_LITERAL){
literalValue=null;
}
if(literalValue===undefined){
thisToken=new Identifier(c);
}else{
thisToken=new Literal(literalValue);
}
}else if(thisToken==WHITE_SPACE){
++startIndex;
continue;
}
return this[$setToken](thisToken,startIndex,c.length);
}
return undefined;
},
"private function setToken",function(token,start,length){
this[$tokenStartPos]=start;
this[$tokenEndPos]=start+length;
this[$token]=token;
return token;
},
"private bound function consume",function(tokenSet){
var thisToken=this[$token];
if(tokenSet.containsToken(thisToken)){

this[$nextToken]();
return thisToken;
}

return null;
},
"private function syntaxError",function(expected){
return new Error(["syntax error: expected ",expected,", found ",this[$token]," at character range ",this[$tokenStartPos],"-",this[$tokenEndPos],"."].join(""));
},
"private bound function expect",function(tokenSet){
var thisToken=this[$consume](tokenSet);
if(!thisToken)
throw this[$syntaxError](tokenSet);
return thisToken;
},

"public function parseLValue",function(el){
this[$startTokenize](el);
this[$expect](TOKENS.EXPRESSION_START);
var identifier=this[$consume](Identifier.TYPE);
var exp=identifier?new BeanExpression(identifier)
:this[$parseNonLiteralValuePrefix]();
if(!exp){
this[$syntaxError]("Identifier or NonLiteralValuePrefix");
}
exp=this[$parseValueSuffixes](exp);
this[$expect](TOKENS.EXPRESSION_END);
this[$expect](TOKENS.EOS);
return exp;
},

"public function parseMethodExpression",function(el){
return this.parseLValue(el);
},

"public function parseRValue",function(el){
this[$startTokenize](el);
var PLUS=TOKENS.PLUS;
var EOS=TOKENS.EOS;
var exp=null;
while(!this[$consume](EOS)){
var nextExp=this[$consume](Literal.TYPE);
if(!nextExp){
this[$expect](TOKENS.EXPRESSION_START);
nextExp=this[$parseExpression]();
this[$expect](TOKENS.EXPRESSION_END);
}
exp=exp?BinaryExpression.create(exp,PLUS,nextExp):nextExp;
}
if(!exp){
exp=new Literal("");
}
return exp;
},

"private function parseExpression",function(){
var exp=this[$parseUnaryExpression]();
if(!exp)
throw this[$syntaxError]("expression");
exp=this[$parseExpressionRest](exp);
var binaryOp;
while(binaryOp=this[$consume](BINARY_OP)){
var rightExp=this[$parseUnaryExpression]();
exp=BinaryExpression.create(exp,binaryOp,rightExp);
exp=this[$parseExpressionRest](exp);
}
return exp;
},

"private function parseExpressionRest",function(exp){
if(this[$consume](TOKENS.QUESTIONMARK)){
var thenExp=this[$parseExpression]();
this[$expect](TOKENS.COLON);
var elseExp=this[$parseExpression]();
exp=ConditionalExpression.create(exp,thenExp,elseExp);
}
return exp;
},

"private function parseUnaryExpression",function(){
var thisToken;
if((thisToken=this[$consume](UNARY_OP))){
return UnaryExpression.create(thisToken,this[$parseUnaryExpression]());
}else{
var exp=this[$consume](Literal.TYPE)||this[$parseNonLiteralValuePrefix]();
exp=this[$parseValueSuffixes](exp);
return exp;
}
},

"private function parseNonLiteralValuePrefix",function(){
var exp=null;
if(this[$consume](TOKENS.BRACKET_OPEN)){
exp=this[$parseExpression]();
this[$expect](TOKENS.BRACKET_CLOSE);
}else{
var identifier;
identifier=this[$consume](Identifier.TYPE);
if(identifier){
var scopeIdentifier=null;
var isFunction=! !this[$consume](TOKENS.COLON);
if(isFunction){
scopeIdentifier=identifier;
identifier=this[$expect](Identifier.TYPE);
}
if((isFunction?this[$expect]:this[$consume])(TOKENS.BRACKET_OPEN)){
var paramExps=[];
if(!this[$consume](TOKENS.BRACKET_CLOSE)){
do{
var paramExp=this[$parseExpression]();
paramExps.push(paramExp);
}while(this[$consume](TOKENS.COMMA));
this[$expect](TOKENS.BRACKET_CLOSE);
}
exp=new FunctionExpression(scopeIdentifier,identifier,paramExps);
}else{
exp=new BeanExpression(identifier);
}
}
}
return exp;
},

"private function parseValueSuffixes",function(exp){
var valueSuffix;
while(valueSuffix=this[$parseValueSuffix]()){
exp=new PropertyExpression(exp,valueSuffix);
}
return exp;
},

"private function parseValueSuffix",function(){
var exp=null;
if(this[$consume](TOKENS.DOT)){
var propertyIdentifier=this[$expect](Identifier.TYPE);
exp=new Literal(propertyIdentifier.getName());
}else if(this[$consume](TOKENS.SQUARE_BRACKET_OPEN)){
exp=this[$parseExpression]();
this[$expect](TOKENS.SQUARE_BRACKET_CLOSE);
}
return exp;
},
"private var",{el: undefined},
"private var",{token: undefined},
"private var",{tokenStartPos:-1},
"private var",{tokenEndPos:-1},
];},[]
);joo.classLoader.prepare("package joox.cache",[

"import joo.lang.JOObject",
"import joo.util.PropertyAware",
"import joox.cache.DependencyTracker",""],

"public class DependencyAwareAspect extends PropertyAware",function($jooPublic,$jooPrivate){with(joox.cache)with($jooPublic)with($jooPrivate)return[
"private static const",{DEBUG:false},

"private static function functionWithName",function(f,name){
f["getName"]=function(){return name;};
return f;
},

"private static function wrapGetter",function(propertyName,getter){
return function(){
DependencyTracker.addDependency(this,propertyName);
return getter.call(this);
};
},

"private static function wrapSetter",function(propertyName,getter,setter){
return function(value){
var oldValue=getter.call(this);
var result=setter.call(this,value);
var newValue=getter.call(this);
if(!JOObject.equal(oldValue,newValue)){
DependencyTracker.fireDependency(this,propertyName);
}
return result;
};
},

"public static function instrumentClass",function(clazz){

joo.classLoader.init(clazz);
if(DEBUG)
trace("Instrumenting "+clazz["getName"]()+"...");
var classPrototype=clazz.prototype;

for(var getterName in classPrototype){
var getter=classPrototype[getterName];

if(typeof getter=="function"){
var propertyName=PropertyAware.toPropertyName(getterName);
if(propertyName){

var setterName=PropertyAware.toSetterName(propertyName);
var setter=classPrototype[setterName];
if(typeof setter=="function"){
classPrototype[getterName]=functionWithName(wrapGetter(propertyName,getter),getterName);
classPrototype[setterName]=functionWithName(wrapSetter(propertyName,getter,setter),setterName);
if(DEBUG)
trace("Instrumenting "+clazz.getName()+"#"+propertyName);
}
}
}
}
},

];},["instrumentClass"]
);joo.classLoader.prepare("package org.joo.el",[

"import joo.lang.JOObject",
"import org.joo.el.Token",""],

"public class Identifier extends JOObject implements Token",function($jooPublic,$jooPrivate){with(org.joo.el)with($jooPublic)with($jooPrivate)return[

"public static const",{TYPE:function(){return(new Identifier(undefined));}},
"public function Identifier",function(name){this[$super]();
this[$name]=name;
},
"public function getName",function(){
return this[$name];
},

"public function containsToken",function(token){
return token.constructor===Identifier;
},
"override public function toString",function(){
return"IDENTIFIER";
},
"private var",{name: undefined},
];},[]
);joo.classLoader.prepare("package org.joo.el",[

"import joox.el.ELContext",
"import org.joo.el.AbstractExpression",
"import org.joo.el.Literal",
"import org.joo.el.ELParser",""],

"public class UnaryExpression extends AbstractExpression",function($jooPublic,$jooPrivate){with(org.joo.el)with($jooPublic)with($jooPrivate)return[function(){joo.classLoader.init(Literal,ELContext,ELParser);},

"public static function create",function(unaryOp,exp){
var unaryExp=new UnaryExpression(unaryOp,exp);
if(exp.constructor===Literal){
return new Literal(unaryExp.evaluate(ELContext.instance));
}
return unaryExp;
},
"public function UnaryExpression",function(unaryOp,exp){
this[$super]();
this[$unaryOp]=unaryOp;
this[$exp]=exp;
},
"override public function getLabel",function(){
return this[$unaryOp].toString();
},
"override public function getSubexpressions",function(){
return[this[$exp]];
},
"override public function evaluate",function(elContext){
var value=this[$exp].evaluate(elContext);
switch(this[$unaryOp]){
case ELParser.TOKENS.NOT:return!value;
case ELParser.TOKENS.EMPTY:return isEmpty(value);
}
throw new Error("Invalid unary operator "+this[$unaryOp]);
},
"private static function isEmpty",function(obj){
if(obj===null)
return true;
var type=typeof obj;
if(type=="undefined"||type=="string"&&obj.length===0)
return true;
if(obj.constructor==Array){
return obj.length===0;
}
if(type=="object"){

for(var m in obj){
return false;
}
return true;
}
return false;
},
"override public function toString",function(){
return["(",this[$unaryOp].unparse(),"(",this[$exp],"))"].join("");
},
"private var",{unaryOp: undefined},
"private var",{exp: undefined},
];},["create"]
);joo.classLoader.prepare("package joox.el",[

"import org.joo.el.AbstractExpression",
"import org.joo.el.BeanExpression",
"import org.joo.el.PropertyExpression",
"import joox.el.Expression",
"import joox.cache.DependencySet",
"import joox.cache.DependencyListener",""],


"public class ConstantValueExpression extends Expression implements DependencyListener",function($jooPublic,$jooPrivate){with(joox.el)with($jooPublic)with($jooPrivate)return[function(){joo.classLoader.init(BeanExpression,PropertyExpression);},

"public function ConstantValueExpression",function(expressionString,value){
this[$super](expressionString,value);
},
"public function getValue",function(elContext){
return this.getExpression().evaluate(elContext);









},
"public function invalidated",function(dependencySet){

},
"public function isReadOnly",function(){
return this[$readOnly];
},
"public function setValue",function(elContext,newValue){
if(this.isReadOnly())
throw"Trying to set read-only property in expression "+this+".";
var exp=this.getExpression();

if(exp.constructor===PropertyExpression){
var exps=exp.getSubexpressions();
var baseExp=exps[0];
var base=baseExp.evaluate(elContext);
var propertyExp=exps[1];
var property=propertyExp.evaluate(elContext);
elContext.getELResolver().setValue(elContext,base,property,newValue);
}else if(exp.constructor===BeanExpression){

elContext.getVariableMapper().setVariable(exp.getBeanName(),newValue);
}

},
"private var",{readOnly:false},

];},[]
);joo.classLoader.prepare("package joox.el",[

"import joox.el.ELResolver",
"import joox.el.FunctionMapper",
"import joox.el.VariableMapper",""],

"public class ELContext",function($jooPublic,$jooPrivate){with(joox.el)with($jooPublic)with($jooPrivate)return[

"public static const",{instance:function(){return(new ELContext(new ELResolver(),new FunctionMapper(),new VariableMapper()));}},

"public function ELContext",function(elResolver,functionMapper,variableMapper){this[$super]();
this[$elResolver]=elResolver;
this[$functionMapper]=functionMapper;
this[$variableMapper]=variableMapper;
},
"public function setELResolver",function(elResolver){
this[$elResolver]=elResolver;
},
"public function getELResolver",function(){
return this[$elResolver];
},
"public function getFunctionMapper",function(){
return this[$functionMapper];
},
"public function getVariableMapper",function(){
return this[$variableMapper];
},
"private var",{elResolver: undefined},
"private var",{functionMapper: undefined},
"private var",{variableMapper: undefined},
];},[]
);joo.classLoader.prepare("package joox.el",[""],

"public class FunctionMapper",function($jooPublic,$jooPrivate){with(joox.el)with($jooPublic)with($jooPrivate)return[

"public function setFunction",function(prefix,fun){
var withPrefix=this[$functions][prefix];
if(!withPrefix)
this[$functions][prefix]=withPrefix={};
withPrefix[fun.getName()]=fun;
},

"public function resolveFunction",function(prefix,localName){
return this[$functions][localName];
},
"private var",{functions:function(){return({});}},
];},[]
);joo.classLoader.prepare("package org.joo.el",[

"import org.joo.el.Token",
"import org.joo.el.AbstractExpression",
"import joox.el.ELContext",""],

"public class Literal extends AbstractExpression implements Token",function($jooPublic,$jooPrivate){with(org.joo.el)with($jooPublic)with($jooPrivate)return[function(){joo.classLoader.init(ELContext);},

"public static const",{TYPE:function(){return(new Literal(undefined));}},
"public function Literal",function(value){
this[$super]();
this[$value]=value;
},

"public function containsToken",function(token){
return token.constructor===Literal;
},
"override public function hashCode",function(){
return"LITERAL";
},
"override public function getLabel",function(){
return this.hashCode()+" "+this.toString();
},
"override public function evaluate",function(elContext){
return this[$value];
},
"override public function toString",function(){
var val=this.evaluate(ELContext.instance);
if(typeof val=="string"){
return'"'+String(val).replace('"',"\\\"","g").replace(/\\/g,"\\\\")+'"';
}
return String(val);
},
"private var",{value: undefined},
];},[]
);joo.classLoader.prepare("package org.joo.el",[""],

"public interface TokenSet",function($jooPublic,$jooPrivate){with(org.joo.el)with($jooPublic)with($jooPrivate)return[

,

];},[]

);joo.classLoader.prepare("package joox.cache",[""],

"public interface PropertyChangeListener",function($jooPublic,$jooPrivate){with(joox.cache)with($jooPublic)with($jooPrivate)return[

,

];},[]

);joo.classLoader.prepare("package joox.cache",[

"import joo.lang.JOObject",""],

"public class Dependency",function($jooPublic,$jooPrivate){with(joox.cache)with($jooPublic)with($jooPrivate)return[

"public function Dependency",function(base,property){
this[$super]();
this.base=base;
this.property=property;
this[$hashCodeValue]=JOObject.getHashCode(this.base)+"#"+this.property;
},
"public function hashCode",function(){
return this[$hashCodeValue];
},
"public var",{base: undefined},
"public var",{property: undefined},
"private var",{hashCodeValue: undefined},
];},[]
);joo.classLoader.prepare("package org.joo.el",[

"import joox.el.ELContext",
"import org.joo.el.AbstractExpression",""],

"public class BeanExpression extends AbstractExpression",function($jooPublic,$jooPrivate){with(org.joo.el)with($jooPublic)with($jooPrivate)return[

"public function BeanExpression",function(identifier){
this[$super]();
this[$beanName]=identifier.getName();
},
"public function getBeanName",function(){
return this[$beanName];
},
"override public function getLabel",function(){
return"BEAN "+this.getBeanName();
},
"override public function evaluate",function(elContext){
return elContext.getELResolver().getValue(elContext,null,this.getBeanName());
},
"override public function toString",function(){
return["b(\"",this.getBeanName(),"\")"].join("");
},
"private var",{beanName: undefined},
];},[]
);joo.classLoader.prepare("package org.joo.el",[

"import joox.el.ELContext",
"import org.joo.el.AbstractExpression",""],

"public class LiteralExpression extends AbstractExpression implements TokenSet",function($jooPublic,$jooPrivate){with(org.joo.el)with($jooPublic)with($jooPrivate)return[

"public static const",{TYPE:function(){return(new LiteralExpression(""));}},
"public function LiteralExpression",function(unparsedString){
this[$super]();
this[$string]=unparsedString.replace(/\\#\{/g,"#{");
},
"public function getString",function(){
return this[$string];
},

"public function containsToken",function(token){
return token.constructor===LiteralExpression;
},
"override public function hashCode",function(){
return"LITERAL_EXPRESSION";
},
"override public function getLabel",function(){
return this.hashCode()+" "+this.toString();
},
"override public function evaluate",function(elContext){
return this.getString();
},
"override public function toString",function(){
return'"'+this.getString().replace('"',"\\\"")+'"';
},
"private var",{string: undefined},
];},[]
);joo.classLoader.prepare("package org.joo.el",[

"import org.joo.el.AbstractExpression",
"import joox.el.ELContext",""],

"public class FunctionExpression extends AbstractExpression",function($jooPublic,$jooPrivate){with(org.joo.el)with($jooPublic)with($jooPrivate)return[

"public function FunctionExpression",function(scopeIdentifier,functionIdentifier,paramExps){
this[$super]();
if(scopeIdentifier)
this[$scopeIdentifier]=scopeIdentifier.getName();
this[$functionIdentifier]=functionIdentifier.getName();
this[$paramExps]=paramExps;
},
"public function getName",function(){
return(this[$scopeIdentifier]?this[$scopeIdentifier]+":":"")+this[$functionIdentifier];
},
"override public function getLabel",function(){
return this.getName()+"(...)";
},
"override public function getSubexpressions",function(){
return this[$paramExps];
},
"override public function evaluate",function(elContext){
var theFunction=window[this[$scopeIdentifier]][this[$functionIdentifier]];
var params=[];
for(var i=0;i<this[$paramExps].length;++i){
var paramExp=this[$paramExps][i];
params.push(paramExp.evaluate(elContext));
}
return theFunction.apply(null,params);
},
"override public function toString",function(){
return["f(",this[$scopeIdentifier],",",this[$functionIdentifier],")(",this[$paramExps].join(", "),")"].join("");
},
"private var",{scopeIdentifier: undefined},
"private var",{functionIdentifier: undefined},
"private var",{paramExps: undefined},
];},[]
);joo.classLoader.prepare("package org.joo.el",[

"import joox.el.ELContext",""],

"public class EvalAdapter",function($jooPublic,$jooPrivate){with(org.joo.el)with($jooPublic)with($jooPrivate)return[

"public function EvalAdapter",function(elContext){this[$super]();
this[$elContext]=elContext;
},
"public function b",function(beanName){
return this.p(null,beanName);
},
"public function p",function(base,property){
return this[$elContext].getELResolver().getValue(this[$elContext],base,property);
},
"public function f",function(prefix,localName){
return this[$elContext].getFunctionMapper().resolveFunction(prefix,localName);
},
"public function empty",function(obj){
if(obj===null)
return true;
var type=typeof obj;
if(type=="undefined"||type=="string"&&obj.length===0)
return true;
if(obj.constructor==Array){
return obj.length===0;
}
if(type=="object"){

for(var m in obj){
return false;
}
return true;
}
return false;
},
"private var",{elContext: undefined},
];},[]
);joo.classLoader.prepare("package org.joo.el",[

"import joo.lang.JOObject",
"import org.joo.el.Token",""],

"public class Terminal extends JOObject implements Token",function($jooPublic,$jooPrivate){with(org.joo.el)with($jooPublic)with($jooPrivate)return[

"public static const",{MATCHES:function(){return({});}},
"public function Terminal",function(token,matches){this[$super]();
this[$token]=token;
if(matches.length>0){
this[$unparsed]=matches[0];
for(var i=0;i<matches.length;++i){
MATCHES[matches[i]]=this;
}
}
},
"override public function hashCode",function(){
return this[$token];
},

"public function containsToken",function(token){
return this==token;
},
"public function unparse",function(){
return this[$unparsed];
},
"override public function toString",function(){
return this[$token];
},
"private var",{token: undefined},
"private var",{unparsed:""},
];},[]
);joo.classLoader.prepare(


"package joox.cache",[

"import joo.util.HashSet",
"import joo.util.GapArrayIterator",
"import joox.cache.PropertyChangeListener",""],

"public class DependencySet extends HashSet implements PropertyChangeListener",function($jooPublic,$jooPrivate){with(joox.cache)with($jooPublic)with($jooPrivate)return[

"private static const",{DEBUG:false},function()

{
if(DEBUG){this.
loadFirebugConsole();
}
},
"public function DependencySet",function(listener,msg){
this[$super]();
this[$listener]=listener;
this[$msg]=msg;
},
"public function addDependency",function(dependency){
if(this.add(dependency)){
var base=dependency.base;
var propertyChangeListenersByName=base["_pcl"];
if(!propertyChangeListenersByName){
propertyChangeListenersByName=base["_pcl"]={};
}
var property=dependency.property;
var propertyChangeListeners=propertyChangeListenersByName[property];
if(!propertyChangeListeners){
propertyChangeListeners=propertyChangeListenersByName[property]=new HashSet();
}
propertyChangeListeners.add(this);
if(DEBUG){
trace(this[$msg]+": recorded dependency for ("+base+")."+property);
}
}
},
"public function removeDependency",function(base,property){
this.remove(new Dependency(base,property));
var depSet=base["_pcl"][property];
depSet.remove(this);
},
"override public function clear",function(){
var it=this.iterator();
while(it.hasNext()){
var dependency=it.next();
var depSet=dependency.base["_pcl"][dependency.property];
depSet.remove(this);
}
this[$clear]();
},
"public function propertyChanged",function(base,property){
if(DEBUG){
trace(this[$msg]+": propertyChanged("+base+")."+property);
}
this[$listener].invalidated(this);
this.clear();
},
"private var",{listener: undefined},
"private var",{msg: undefined},
];},[]
);joo.classLoader.prepare("package joox.el",[

"import org.joo.el.ELParser",
"import org.joo.el.Literal",
"import org.joo.el.AbstractExpression",
"import org.joo.el.BinaryExpression",
"import org.joo.el.PropertyExpression",
"import joox.el.ValueExpression",
"import joox.el.MethodExpression",""],

"public class ExpressionFactory",function($jooPublic,$jooPrivate){with(joox.el)with($jooPublic)with($jooPrivate)return[function(){joo.classLoader.init(ValueExpression,ELParser);},

"public static const",{instance:function(){return(new ExpressionFactory(new ELParser()));}},
"public function ExpressionFactory",function(parser){
this[$super]();
this[$parser]=parser;
},

"public function createValueExpression",function(elContext,expressionString){
var expression;
var readOnly=false;
try{
expression=this[$parser].parseLValue(expressionString);
}catch(e){if(is(e,Error)){
expression=this[$parser].parseRValue(expressionString);
readOnly=true;
}}
return new ValueExpression(expressionString,expression,readOnly);
},
"public function createIndexValueExpression",function(valueExpression,
offsetValueExpression,
relativeIndex){

if(typeof offsetValueExpression=="number"){
offsetValueExpression=this.createObjectValueExpression(offsetValueExpression);
}


return new ValueExpression(["(",valueExpression.getExpressionString(),")[",offsetValueExpression.getExpressionString(),
"+",relativeIndex,"]"].join(""),
new PropertyExpression(valueExpression.getExpression(),
BinaryExpression.create(offsetValueExpression.getExpression(),
ELParser.TOKENS.PLUS,
new Literal(relativeIndex))),
false);
},
"public function createObjectValueExpression",function(object){
if(typeof object=="object"){

return{
constructor:ValueExpression,
getValue:function(){return object;}
};
}
return new ValueExpression(String(object),new Literal(object));
},

"public function createMethodExpression",function(elContext,expressionString){
return new MethodExpression(expressionString,this[$parser].parseMethodExpression(expressionString));
},
"private var",{parser: undefined},
];},[]
);joo.classLoader.prepare("package joox.cache",[""],

"public interface DependencyListener",function($jooPublic,$jooPrivate){with(joox.cache)with($jooPublic)with($jooPrivate)return[

,

];},[]

);joo.classLoader.prepare("package org.joo.el",[

"import joo.lang.JOObject",
"import joox.el.ELContext",""],


"public class AbstractExpression extends JOObject",function($jooPublic,$jooPrivate){with(org.joo.el)with($jooPublic)with($jooPrivate)return[

"private static const",{NO_SUBEXPS:function(){return([]);}},

"public function getLabel",function(){
throw new Error("AbstractExpression#getLabel(): abstract method.");
},
"public function getSubexpressions",function(){
return NO_SUBEXPS;
},
"public function evaluate",function(elContext){
throw new Error("AbstractMethod");
},
"private var",{expFunc: undefined},
];},[]
);joo.classLoader.prepare("package joox.el",[

"import joox.el.Expression",
"import org.joo.el.AbstractExpression",""],

"public class MethodExpression extends Expression",function($jooPublic,$jooPrivate){with(joox.el)with($jooPublic)with($jooPrivate)return[

"public function MethodExpression",function(expressionString,expression){
this[$super](expressionString,expression);
},
"public function invoke",function(elContext,parameters){

var exps=this.getExpression().getSubexpressions();
var beanExp=exps[0];
var bean=beanExp.evaluate(elContext);
var methodNameExp=exps[1];
var methodName=methodNameExp.evaluate(elContext);
var method=bean[methodName];
return method.apply(bean,parameters);
},
];},[]
);joo.classLoader.prepare("package org.joo.el",[

"import org.joo.el.AbstractExpression",
"import joox.el.ELContext",""],

"public class PropertyExpression extends AbstractExpression",function($jooPublic,$jooPrivate){with(org.joo.el)with($jooPublic)with($jooPrivate)return[

"public function PropertyExpression",function(beanExp,propertyExp){
this[$super]();
this[$beanExp]=beanExp;
this[$propertyExp]=propertyExp;
},
"override public function getLabel",function(){
return"PROPERTY";
},
"override public function getSubexpressions",function(){
return[this[$beanExp],this[$propertyExp]];
},
"override public function evaluate",function(elContext){
return elContext.getELResolver().getValue(elContext,this[$beanExp].evaluate(elContext),this[$propertyExp].evaluate(elContext));
},
"override public function toString",function(){
return["p(",this[$beanExp],",",this[$propertyExp],")"].join("");
},
"private var",{beanExp: undefined},
"private var",{propertyExp: undefined},
];},[]
);joo.classLoader.prepare("package org.joo.el",[

"import org.joo.el.TokenSet",
"import joo.util.HashSet",""],

"public class TokenHashSet extends HashSet implements TokenSet",function($jooPublic,$jooPrivate){with(org.joo.el)with($jooPublic)with($jooPrivate)return[

"public function TokenHashSet",function(tokens){
this[$super](tokens);
},

"public function containsToken",function(token){
return this.contains(token);
},
];},[]

);joo.classLoader.prepare("package org.joo.el",[

"import org.joo.el.TokenSet",""],

"public interface Token extends TokenSet",function($jooPublic,$jooPrivate){with(org.joo.el)with($jooPublic)with($jooPrivate)return[

];},[]

);joo.classLoader.prepare("package joox.cache",[

"import joo.util.HashSet",
"import joo.util.GapArrayIterator",
"import joox.cache.DependencySet",
"import joox.cache.Dependency",""],

"public class DependencyTracker",function($jooPublic,$jooPrivate){with(joox.cache)with($jooPublic)with($jooPrivate)return[

"public static function start",function(listener,msg){
dependencies.push(new DependencySet(listener,msg));
},
"public static function addDependency",function(base,property){
var dependencyStack=dependencies;
if(dependencyStack.length>0){
var depSet=dependencyStack[dependencyStack.length-1];
depSet.addDependency(new Dependency(base,property));
}
},
"public static function stop",function(){
return dependencies.pop();
},
"public static function fireDependency",function(base,property){
if(typeof base["_pcl"]=="object"){
var listeners=base["_pcl"][property];
if(listeners){
var dependencySet=dependencies[dependencies.length-1];
for(var listenerI=listeners.iterator();listenerI.hasNext();){
var listener=listenerI.next();
listener.propertyChanged(base,property);
}
}
}
},
"private static var",{dependencies:function(){return([]);}},
];},["start","addDependency","stop","fireDependency"]
);joo.classLoader.prepare("package joox.el",[

"import joox.el.ExpressionFactory",
"import joox.el.ELContext",""],

"public class VariableMapper",function($jooPublic,$jooPrivate){with(joox.el)with($jooPublic)with($jooPrivate)return[function(){joo.classLoader.init(ELContext,ExpressionFactory);},

"public function setVariable",function(name,valueExpression){
if(typeof valueExpression=="string"){
valueExpression=ExpressionFactory.instance.createValueExpression(ELContext.instance,valueExpression);
}
this[$variables][name]=valueExpression;
},
"public function resolveVariable",function(name){
var exp=this[$variables][name];
if(exp)
return exp;

return ExpressionFactory.instance.createObjectValueExpression(window[name]);
},
"private var",{variables:function(){return({});}},
];},[]
);joo.classLoader.prepare("package joox.el",[

"import joo.lang.JOObject",
"import org.joo.el.AbstractExpression",
"import org.joo.el.ELParser",""],

"public class Expression extends JOObject",function($jooPublic,$jooPrivate){with(joox.el)with($jooPublic)with($jooPrivate)return[

"protected static const",{PARSER:function(){return(new ELParser());}},

"public function Expression",function(expressionString,expression,
literalText){if(arguments.length<3){literalText=false;}
this[$super]();
this[$expressionString]=expressionString;
this[$expression]=expression;
if(typeof literalText=="boolean"){
this[$literalText]=! !literalText;
}
},
"public function getExpressionString",function(){
return this[$expressionString];
},
"public function getExpression",function(){
return this[$expression];
},
"public function isLiteralText",function(){
return this[$literalText];
},
"override public function toString",function(){
return this.getExpressionString();
},
"private var",{expressionString: undefined},
"private var",{expression: undefined},
"private var",{literalText:false},
];},[]
);joo.classLoader.prepare("package joox.el",[

"import joox.el.Expression",
"import org.joo.el.AbstractExpression",
"import org.joo.el.BeanExpression",
"import joox.cache.DependencyListener",
"import joox.cache.DependencySet",

"import org.joo.el.PropertyExpression",""],

"public class ValueExpression extends Expression implements DependencyListener",function($jooPublic,$jooPrivate){with(joox.el)with($jooPublic)with($jooPrivate)return[function(){joo.classLoader.init(BeanExpression,PropertyExpression);},

"public function ValueExpression",function(expressionString,expression,
readOnly){if(arguments.length<3){readOnly=false;}
this[$super](expressionString,expression);
this[$readOnly]=readOnly;
},
"public function getValue",function(elContext){
return this.getExpression().evaluate(elContext);








},
"private function setCachedValue",function(value){
this[$isCached]=true;
return this[$cachedValue]=value;
},
"public function invalidated",function(dependencySet){
this[$isCached]=false;
},

"public function isReadOnly",function(elContext){
return this[$readOnly];
},
"public function setValue",function(elContext,newValue){
if(this.isReadOnly(elContext))
throw"Trying to set read-only property in expression "+this+".";
var exp=this.getExpression();

if(exp.constructor===PropertyExpression){
var exps=exp.getSubexpressions();
var baseExp=exps[0];
var base=baseExp.evaluate(elContext);
var propertyExp=exps[1];
var property=propertyExp.evaluate(elContext);
elContext.getELResolver().setValue(elContext,base,property,newValue);
}else if(exp.constructor===BeanExpression){
elContext.getVariableMapper().setVariable((exp).getBeanName(),newValue);
}
this[$isCached]=true;
this[$cachedValue]=newValue;
},
"private var",{readOnly:false},
"private var",{isCached:false},
"private var",{cachedValue: undefined},
];},[]
);joo.classLoader.prepare("package org.joo.el",[

"import org.joo.el.AbstractExpression",
"import org.joo.el.ELParser",
"import org.joo.el.Literal",
"import joox.el.ELContext",""],

"public class BinaryExpression extends AbstractExpression",function($jooPublic,$jooPrivate){with(org.joo.el)with($jooPublic)with($jooPrivate)return[function(){joo.classLoader.init(Literal,ELContext,ELParser);},

"public static function create",function(leftExp,binaryOp,rightExp){
if(leftExp.constructor===Literal){
if(rightExp.constructor===Literal){
var binaryExp=new BinaryExpression(leftExp,binaryOp,rightExp);
return new Literal(binaryExp.evaluate(ELContext.instance));
}else{
var TOKENS=ELParser.TOKENS;

if(binaryOp==TOKENS.AND||binaryOp==TOKENS.OR){
var leftValue=leftExp.evaluate(ELContext.instance);
return binaryOp==TOKENS.AND&&leftValue||binaryOp==TOKENS.OR&&!leftValue
?rightExp:leftExp;
}
}
}
return new BinaryExpression(leftExp,binaryOp,rightExp);
},
"public function BinaryExpression",function(leftExp,binaryOp,rightExp){
this[$super]();
this[$leftExp]=leftExp;
this[$binaryOp]=binaryOp;
this[$rightExp]=rightExp;
},
"override public function getLabel",function(){
return this[$binaryOp].toString();
},
"override public function getSubexpressions",function(){
return[this[$leftExp],this[$rightExp]];
},
"override public function evaluate",function(elContext){
var leftValue=this[$leftExp].evaluate(elContext);

switch(this[$binaryOp]){
case ELParser.TOKENS.AND:return leftValue&&this[$rightExp].evaluate(elContext);
case ELParser.TOKENS.OR:return leftValue||this[$rightExp].evaluate(elContext);
}
var rightValue=this[$rightExp].evaluate(elContext);
switch(this[$binaryOp]){
case ELParser.TOKENS.PLUS:return leftValue+rightValue;
case ELParser.TOKENS.MINUS:return leftValue-rightValue;
case ELParser.TOKENS.MULT:return leftValue*rightValue;
case ELParser.TOKENS.DIV:return leftValue/rightValue;
case ELParser.TOKENS.MOD:return leftValue%rightValue;
case ELParser.TOKENS.GT:return leftValue>rightValue;
case ELParser.TOKENS.LT:return leftValue<rightValue;
case ELParser.TOKENS.GE:return leftValue>=rightValue;
case ELParser.TOKENS.LE:return leftValue<=rightValue;
case ELParser.TOKENS.EQ:return leftValue==rightValue;
case ELParser.TOKENS.NE:return leftValue!=rightValue;
}
throw new Error("Invalid binary operator "+this[$binaryOp]);
},
"override public function toString",function(){
return["(",this[$leftExp],this[$binaryOp].unparse(),this[$rightExp],")"].join("");
},
"private var",{leftExp: undefined},
"private var",{binaryOp: undefined},
"private var",{rightExp: undefined},
];},["create"]
);
