例:
expression1 = service.isInBlacklist(context.getOriginalMOId(),4)
expression2 = (currentTime-lastActiveDate(context))/1000/60/60/24>=%{day}
expression3 = inboundSMS.getAttribute("MODE_CODES")=="QF"
expression4 = results.getResults()== null || results.getResults().isEmpty()
Step1. 从表达式里获得参数名(ParameterNames)
——正则表达式处理
Step2. CompilingContext、ValueExpression、JavaDomainResolver
CompilingContext compilingContext = new CompilingContext(); ValueExpression val = new ValueExpression(); compilingContext.setValue(val); JavaDomainResolver resolver = ctx.getAppContext().createDomainResolver(artifactType); compilingContext.setResolver(resolver);
CompilingContext
ValueExpression
JavaDomainResolver
Step3. 将表达式里的%{paramName}换成__paramName
Step4. 将表达式解析(parse)java 代码
SimpleNode node = (SimpleNode) ELParser.parse("#{" + expr + "}"); //生成一个树,该node是根节点
String varName = compilingContext.getNextVarName(); val.setVarName(varName); node.jjtAccept(new JavaDialect(), compilingContext); //遍历树,每个节点接收visitor,visitor访问该节点;生成代码
StringBuffer code = new StringBuffer(); val.generateJavaCode(compilingContext, code);
//生成代码
Step5. 添加return语句
if(artifactType.equals(Constants.ARTIFACT_TYPE_CONDITION)){ if (val.getType() == Void.class ||val.getType()==void.class) { } else if (val.getType().isPrimitive()) { code.append("\nreturn ").append(getWrapper(val)).append(";\n"); } else { code.append("\nreturn ").append(val.getVarName()).append(";\n"); } }
expression=attrs.getAttribute("NEW2OLD_NEEDED_TX")!=null
&&attrs.getAttribute("NEW2OLD_NEEDED_TX")==true
将该表达式解析后的java代码如下:
boolean bool1 = false; Object localObject1 = ((UserAttributes)getData("attrs")).getAttribute("NEW2OLD_NEEDED_TX"); int i = (localObject1 != null) ? 1 : 0; if (i == 0) { bool1 = false; } else { Object localObject2 = ((UserAttributes)getData("attrs")).getAttribute("NEW2OLD_NEEDED_TX"); boolean bool2 = localObject2.equals(Boolean.valueOf(true)); if (bool2) bool1 = true; else { bool1 = false; } } return new Boolean(bool1).booleanValue();
问题1:上面step4中代码
SimpleNode node = (SimpleNode) ELParser.parse("#{" + expr + "}"); ELParserVisitor visitor = new JavaDialect(); node.jjtAccept(visitor, compilingContext);
??SimpleNode、ELParser.parser()。。。
Node.java如下
/* Generated By:JJTree: Do not edit this line. Node.java Version 4.3 */ /* JavaCCOptions:MULTI=true,NODE_USES_PARSER=false,VISITOR=true,TRACK_TOKENS=false,NODE_PREFIX=Ast,NODE_EXTENDS=,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */ package com.wxxr.el.parser; /* All AST nodes must implement this interface. It provides basic machinery for constructing the parent and child relationships between nodes. */ public interface Node { /** This method is called after the node has been made the current node. It indicates that child nodes can now be added to it. */ public void jjtOpen(); /** This method is called after all the child nodes have been added. */ public void jjtClose(); /** This pair of methods are used to inform the node of its parent. */ public void jjtSetParent(Node n); public Node jjtGetParent(); /** This method tells the node to add its argument to the node's list of children. */ public void jjtAddChild(Node n, int i); /** This method returns a child node. The children are numbered from zero, left to right. */ public Node jjtGetChild(int i); /** Return the number of children the node has. */ public int jjtGetNumChildren(); /** Accept the visitor. **/ public Object jjtAccept(ELParserVisitor visitor, Object data); } /* JavaCC - OriginalChecksum=fc35c6181f3c693be7a513484d1166bc (do not edit this line) */
》》》》研究Node、SimpleNode、Visitor、
访问者模式(Visitor design pattern)的应用
抽象节点角色:Node(提供accept(visitor)方法)
具体节点角色:SimpleNode(部分方法提供默认实现)、AstAnd等(具体节点)
抽象访问者角色:ELParserVisitor(提供visit(node)方法)
具体访问者角色:JavaDialect
??ValueExpresion里的javaStatement从哪儿来??
??ELParser.parse("#{" + expr + "}")生成的Node是什么类型??
JavaDialect里
public Object visit(SimpleNode node, Object data) {
return null;
}
visitor(访问者)visit(访问)node(节点),
node(节点)accept(接收)visitor(访问者)
visitor(访问者)里为每个node(节点)都准备一个visit(访问)操作
com.wxxr.common.descion.table.spi.IRuleApplication
子类:ZjhzApplication,MockRuleApplication
com.wxxr.common.descion.table.spi.IAppCompileContext
--Dependency[] getDependencies()获取某个应用(如ZjhzApplication)所依赖的jar文件的URL
com.wxxr.common.descion.table.spi.AbstractAppCompileContext
在ZjhzApplication中有具体子类
com.wxxr.common.descion.table.IRuleCompileContext
在DesicionTableRegistryImpl中有具体子类
注:以getNextVarName(获得下一个变量名)为例,体会JDK6RuleCompiler中如何通过CompilingContext获得值?
在CompilingContext中持有JavaDomainResolver引用。