Operand是MOQL语法结构的重要组成部分,语法结构中那些需要被分析处理的数据列或数据值都被称之为Operand。如select后跟的数据列,where条件中描述的条件字段以及需要匹配的常数值等都被称之为Operand。如下面语句中的红色字体部分,均表示是一个Operand。通过对其计算,我们可以获得数据结果,并形成最终我们求解的数据结果集。
select count(a.id) cnt, sum(a.num) sum, a.num%500 mod from BeanA a group by 3 having mod > 10 order by 1 |
在MOQL中,Operand不仅能在完整的语法结构中使用,还可以单独使用。MOQL提供了方法可以直接创建一个操作数,并利用此操作数完成数据的求解。如下:
EntityMap entityMap = new EntityMapImpl(); entityMap.putEntity("num", 12); entityMap.putEntity("num1", 3); entityMap.putEntity("num2", 4); try { Operand arithmetic = MoqlUtils.createOperand("(num * num1) / num2 * 2.2 + 2 - 1"); System.out.println(arithmetic.operate(entityMap)); } catch (MoqlException e) { e.printStackTrace(); } |
该例中为表达式"(num * num1) / num2 * 2.2 + 2 -1"创建了一个操作数,该操作数利用传入的实体Map对表达式进行了求解,并输出了执行结果,结果为20.8。MoqlUtils的createOperand方法可以创建一个操作数,传给该方法的参数为一个操作数表达式字符串,返回的对象为一个Operand接口,该接口位于org.moql的包路径下,定义如下:
publicinterface Operand { /*获得操作数的类型*/ OperandType getOperandType(); /*返回操作数的名字*/ String getName(); /*返回操作数在文本串中的位置,返回对象类型为org.antlr.runtime.Token */ Object getSource(); /*根据给定的实体Map传入的值,计算操作数的值*/ Object operate(EntityMap entityMap); /*根据给定的实体Map传入的值,计算操作数的布尔值。*/ boolean booleanOperate(EntityMap entityMap); /*操作数的返回值是否为一固定常量。*/ boolean isConstantReturn(); /*重置操作数,将操作数状态置为初始状态。*/ void reset(); } |
getOperandType()方法用于返回Operand的类型OperandType。OperandType为枚举类型,也位于org.moql的包路径下,定义格式如下:
publicenum OperandType { UNKNOWN, CONSTANT, VARIABLE, FUNCTION, EXPRESSION, COLUMNSELECTOR } |
其包括的Operand类型有常量(CONSTANT)、变量(VARIABLE)、函数(FUNCTION)、表达式(EXPRESSION)及列筛选器(COLUMNSELECTOR)五类(注:Operand的类型将在后面详细介绍),当Operand不属于以上任何一类时用UNKNOWN未知表示。
getName()方法用于获得Operand的名字。除了函数类型的Operand的名字为函数名外,其它类型的Operand的名字就是生成Operand的字符串本身。如:“sum(a.num)”整体被解析为一个函数Operand,其名字为“sum”,其内嵌了一个由“a.num”解析而成的表达式Operand作为参数,该Operand名字为“a.num”;再如:“123”被解析为常量Operand,其名字为“123”等。
getSource()方法用于返回操作数在文本串中的位置。如:“sum(a.num)”会被解析为多个操作数,对每个操作数调用该方法就可以定位操作数在文本串中的位置了。
operate(EntityMapentityMap)方法是Operand提供的主要方法,利用该方法操作数可以对给定的参数进行求值。EntityMap是一个装有实体对象的Map,其实体名若与变量Operand的名字一致,那么实体对象便会被变量Operand绑定用来求解。
booleanOperate(EntityMapentityMap)方法是operate(EntityMap entityMap)方法的扩展。用于将Operand的计算结果以布尔值的形式返回。若operate方法返回值的类型是java.lang.Boolean,则该方法返回调用Boolean.booleanValue()所得的值;若operate方法返回值的类型不是java.lang.Boolean,返回值为null时,返回false,否则返回true;
isConstantReturn()方法用于告诉调用者在调用Operand的operate方法后是否总能返回一个不变得常量值。若该Operand是一个常量类型的Operand,则该调用总是返回true,表示调用常量类型Operand的operate方法总是返回同一个常量值。而对于该方法更有意义的用途是在函数类型Operand以及表达式类型Operand中的调用。这两种类型的Operand在初始化时会判断所有其相关的Operand的该方法调用,返回是否都是true。若都是true,则表示该操作数的执行结果与operate调用时传入的EntityMap参数无关,那么就可以预先对该操作数进行求解,而不用等到每次调用operate方法时现去求解了。这样可以在一定程度上提升Operand的执行效率。若对该方法的调用感兴趣,可以查看源代码中
org.moql.operand.function.AbstractFunction类以及org.moql.operand.expression.arithmetic.AbstractArithmeticExpression类的相关初始化实现。
reset()方法用于重置Operand,将Operand的状态恢复为初始状态。Operand在计算时分为有状态和无状态两种情况。有状态是指当对Operand的operate方法进行多次调用时,其计算结果受以前调用结果的影响;而无状态是指多次调用不会受以前调用结果的影响。对于有状态的Operand需要通过调用reset方法将其状态恢复为初始状态。如:“sum(a.num)”对应的Operand,会累计每次调用operate方法的结果,对每次调用的值求和。若需要重新开始计数,需要调用reset方法将该Operand恢复为初始值。类似的Operand还有count、avg、max、min等聚合函数。
项目地址:http://sourceforge.net/projects/moql/
代码路径:svn://svn.code.sf.net/p/moql/code/trunk