EMMA Coverage Report (generated Sat Aug 20 11:00:51 CDT 2011)
[all classes][tuffy.ra]

COVERAGE SUMMARY FOR SOURCE FILE [Expression.java]

nameclass, %method, %block, %line, %
Expression.java100% (1/1)73%  (16/22)59%  (698/1182)73%  (128.8/177)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class Expression100% (1/1)73%  (16/22)59%  (698/1182)73%  (128.8/177)
and (Expression, Expression): Expression 0%   (0/1)0%   (0/13)0%   (0/4)
exprConstString (String): Expression 0%   (0/1)0%   (0/10)0%   (0/3)
isBoolean (): boolean 0%   (0/1)0%   (0/9)0%   (0/1)
isNumeric (): boolean 0%   (0/1)0%   (0/14)0%   (0/2)
isString (): boolean 0%   (0/1)0%   (0/9)0%   (0/1)
or (Expression, Expression): Expression 0%   (0/1)0%   (0/13)0%   (0/4)
addArgument (Expression): void 100% (1/1)38%  (13/34)50%  (3/6)
getStringForm (boolean): String 100% (1/1)54%  (433/807)71%  (64.8/91)
not (Expression): Expression 100% (1/1)71%  (15/21)80%  (4/5)
bindVariables (Map): void 100% (1/1)76%  (32/42)88%  (7/8)
renameVariables (Map): String 100% (1/1)88%  (38/43)82%  (9/11)
Expression (Function): void 100% (1/1)100% (23/23)100% (8/8)
clone (): Expression 100% (1/1)100% (61/61)100% (13/13)
exprConstInteger (int): Expression 100% (1/1)100% (11/11)100% (3/3)
exprConstNum (double): Expression 100% (1/1)100% (11/11)100% (3/3)
exprVariableBinding (String): Expression 100% (1/1)100% (10/10)100% (3/3)
getArgs (): ArrayList 100% (1/1)100% (3/3)100% (1/1)
getFunction (): Function 100% (1/1)100% (3/3)100% (1/1)
getVars (): HashSet 100% (1/1)100% (33/33)100% (6/6)
needEnclosure (): boolean 100% (1/1)100% (4/4)100% (1/1)
toSQL (): String 100% (1/1)100% (4/4)100% (1/1)
toString (): String 100% (1/1)100% (4/4)100% (1/1)

1package tuffy.ra;
2 
3import java.util.ArrayList;
4import java.util.HashSet;
5import java.util.Map;
6 
7 
8 
9import tuffy.db.SQLMan;
10import tuffy.mln.Type;
11import tuffy.util.ExceptionMan;
12import tuffy.util.StringMan;
13 
14/**
15 * An expression to a function is like a literal to a predicate.
16 * The interesting part is that expressions can be nested.
17 * The value of an expression can be numeric/string/boolean.
18 * 
19 * @author Feng Niu
20 *
21 */
22final public class Expression implements Cloneable{
23        private Function func_ = null;
24        private ArrayList<Expression> args_ = new ArrayList<Expression>();
25        private String val = null;
26        private String valBinding = null;
27        
28        public boolean changeName = true;
29        
30        public ArrayList<Expression> getArgs(){
31                return args_;
32        }
33        
34        public Function getFunction(){
35                return func_;
36        }
37        
38        /**
39         * Get the variables referenced by this expression.
40         * 
41         */
42        public HashSet<String> getVars(){
43                HashSet<String> set = new HashSet<String>();
44                if(func_ == Function.VariableBinding){
45                        set.add(val);
46                }else{
47                        for(Expression e : args_){
48                                set.addAll(e.getVars());
49                        }
50                }
51                return set;
52        }
53        
54        /**
55         * For aesthetics, check if we need a pair of parenthses for this experession.
56         * 
57         */
58        private boolean needEnclosure(){
59                return func_.isOperator();
60        }
61        
62        /**
63         * Construct a new expression based on the function {@link #func_}
64         * 
65         * @param func the underlying function
66         */
67        public Expression(Function func){
68                func_ = func;
69        }
70        
71        /**
72         * Boolean negation
73         * @param e
74         * 
75         */
76        public static Expression not(Expression e){
77                if(e.func_.equals(Function.NOT)){
78                        return e.args_.get(0);
79                }
80                Expression ne = new Expression(Function.NOT);
81                ne.addArgument(e);
82                return ne;
83        }
84 
85        /**
86         * Boolean AND
87         * @param e1
88         * @param e2
89         * 
90         */
91        public static Expression and(Expression e1, Expression e2){
92                Expression ne = new Expression(Function.AND);
93                ne.addArgument(e1);
94                ne.addArgument(e2);
95                return ne;
96        }
97 
98        /**
99         * Boolean OR
100         * @param e1
101         * @param e2
102         * 
103         */
104        public static Expression or(Expression e1, Expression e2){
105                Expression ne = new Expression(Function.OR);
106                ne.addArgument(e1);
107                ne.addArgument(e2);
108                return ne;
109        }
110        
111        /**
112         * Test if this expression returns a boolean value
113         * 
114         */
115        public boolean isBoolean(){
116                return func_.getRetType() == Type.Bool;
117        }
118 
119        /**
120         * Test if this expression returns a string value
121         * 
122         */
123        public boolean isString(){
124                return func_.getRetType() == Type.String;
125        }
126        
127 
128        /**
129         * Test if this expression returns a numeric value
130         * 
131         */
132        public boolean isNumeric(){
133                return func_.getRetType() == Type.Integer
134                || func_.getRetType() == Type.Float;
135        }
136        
137        /**
138         * Append an argument to the underlying function
139         * @param expr the new argument
140         */
141        public void addArgument(Expression expr){
142                if(args_.size() >= func_.arity()){
143                        ExceptionMan.die("Function " + func_.getName() + 
144                                        " expected " + func_.arity() + " arguments, but " +
145                                        "received more");
146                }else{
147                        args_.add(expr);
148                }
149        }
150        
151        /**
152         * Atomic expression representing a constant integer
153         * @param n
154         * 
155         */
156        public static Expression exprConstInteger(int n){
157                Expression ex = new Expression(Function.ConstantNumber);
158                ex.val = Integer.toString(n);
159                return ex;
160        }
161 
162        /**
163         * Atomic expression representing a constant number
164         * 
165         */
166        public static Expression exprConstNum(double num){
167                Expression ex = new Expression(Function.ConstantNumber);
168                ex.val = Double.toString(num);
169                return ex;
170        }
171 
172        /**
173         * Atomic expression representing a constant string
174         * 
175         */
176        public static Expression exprConstString(String str){
177                Expression ex = new Expression(Function.ConstantString);
178                ex.val = str;
179                return ex;
180        }
181 
182        /**
183         * Atomic expression representing a variable binding
184         * 
185         */
186        public static Expression exprVariableBinding(String var){
187                Expression ex = new Expression(Function.VariableBinding);
188                ex.val = var;
189                return ex;
190        }
191 
192        
193        @SuppressWarnings("unchecked")
194        public Expression clone(){
195                Expression ret;
196                
197                if(this.val != null){
198                        ret = new Expression(this.func_);
199                        ret.val = this.val;
200                        ret.valBinding = this.valBinding;
201                        ret.args_ = (ArrayList<Expression>) this.args_.clone();
202                        return ret;
203                }
204                
205                ret = new Expression(this.func_);
206                for(Expression sub : this.args_){
207                        ret.addArgument(sub.clone());
208                }
209                ret.val = this.val;
210                ret.valBinding = this.valBinding;
211                ret.changeName = this.changeName;
212                
213                return ret;
214        }
215        
216        /**
217         * Bind variable references to their values in the symbol table.
218         * Variable name in the clause -> attribute name in SQL representing
219         * the value column of the symbol table.
220         * 
221         * @param mapVarVar
222         */
223        public String renameVariables(Map<String, String> mapVarVar){
224                String es = null;
225                if(func_ == Function.VariableBinding){
226                        String nvar = mapVarVar.get(val);
227                        if(nvar == null){
228                                return val;
229                        }else{
230                                val = nvar;
231                        }
232                }else{
233                        for(Expression e : args_){
234                                String aaa = e.renameVariables(mapVarVar);
235                                if(aaa != null){
236                                        return aaa;
237                                }
238                        }
239                }
240                return es;
241        }
242        
243        
244        /**
245         * Bind variable references to their values in the symbol table.
246         * Variable name in the clause -> attribute name in SQL representing
247         * the value column of the symbol table.
248         * 
249         * @param mapVarVal
250         */
251        public void bindVariables(Map<String, String> mapVarVal){
252                if(func_ == Function.VariableBinding){
253                        String attr = mapVarVal.get(val);
254                        if(attr == null){
255                                ExceptionMan.die("Encountered a dangling variable: " + val);
256                        }else{
257                                valBinding = attr;
258                        }
259                }else{
260                        for(Expression e : args_){
261                                e.bindVariables(mapVarVal);
262                        }
263                }
264        }
265        
266        /**
267         * Get the SQL snippet for this expression
268         * 
269         */
270        public String toSQL(){
271                return getStringForm(true);
272        }
273        
274        /**
275         * Compute the SQL representation of this expression.
276         * Call {@link #bindVariables(Map)} first.
277         * 
278         */
279        private String getStringForm(boolean inSQL){
280                // atomic
281                if(func_ == Function.ConstantNumber){
282                        return val;
283                }
284                if(func_ == Function.VariableBinding){
285                        return inSQL ? valBinding : val;
286                }
287                if(func_ == Function.ConstantString){
288                        return inSQL ? SQLMan.escapeString(val) : 
289                                "\"" + StringMan.escapeJavaString(val) + "\"";
290                }
291                
292                // cast argument into correct types
293                ArrayList<String> sterms = new ArrayList<String>();
294                
295                if(inSQL){
296                        for(int i=0; i < func_.arity(); i++){
297                                Type t = func_.getArgTypes().get(i);
298                                String s = args_.get(i).toSQL();
299                                if(t == Type.Integer){
300                                        s = "(CASE WHEN (" + s + ") IS NULL THEN NULL " +
301                                                        "ELSE (" + s + ")::INT END)";
302                                }else if(t == Type.Float){
303                                        s = "(CASE WHEN (" + s + ") IS NULL THEN NULL " +
304                                        "ELSE (" + s + ")::FLOAT END)";
305                                }else if(t == Type.String){
306                                        s = "CAST(" + s + " AS TEXT)";
307                                }else if(t == Type.Bool){
308                                        s = "(CASE WHEN (" + s + ") IS NULL THEN NULL " +
309                                        "ELSE (" + s + ")::BOOL END)";
310                                }else{
311                                        s= "(" + s + ")";
312                                }
313                                
314                                if(func_ == Function.Eq || func_ == Function.Neq){
315                                        
316                                        //TODO: NEQ'S BUG!!!! ENRON680_TUFFY
317                                //        if(func_.getArgTypes().get(0) != func_.getArgTypes().get(1)){
318                                                sterms.add(" CAST(" + s + " AS TEXT) ");
319                                //        }else{
320                                //                sterms.add(s);
321                                //        }
322                                        
323                                }else{
324                                        sterms.add(s);
325                                }
326                        }
327                }else{
328                        for(int i=0; i < func_.arity(); i++){
329                                String s = args_.get(i).toString();
330                                if(args_.get(i).needEnclosure()){
331                                        s = "(" + s + ")";
332                                }
333                                sterms.add(s);
334                        }
335                }
336                
337                // map to operators
338                if(func_ == Function.BitNeg){
339                        return "~" + sterms.get(0);
340                }
341 
342                if(func_ == Function.Factorial){
343                        return sterms.get(0) + "!";
344                }
345                
346                if(func_ == Function.NOT){
347                        return "NOT " + sterms.get(0) + "";
348                }
349 
350                if(func_ == Function.AND){
351                        return sterms.get(0) + " AND " + sterms.get(1);
352                }
353 
354                if(func_ == Function.OR){
355                        return sterms.get(0) + " OR " + sterms.get(1);
356                }
357                
358                if(func_ == Function.Add){
359                        return sterms.get(0) + " + " + sterms.get(1);
360                }
361                
362                if(func_ == Function.Subtract){
363                        return sterms.get(0) + " - " + sterms.get(1);
364                }
365 
366                if(func_ == Function.Multiply){
367                        return sterms.get(0) + " * " + sterms.get(1);
368                }
369 
370                if(func_ == Function.Divide){
371                        return sterms.get(0) + " / " + sterms.get(1);
372                }
373                
374                if(func_ == Function.Modulo){
375                        return sterms.get(0) + " % " + sterms.get(1);
376                }
377 
378                if(func_ == Function.BitAnd){
379                        return sterms.get(0) + " & " + sterms.get(1);
380                }
381 
382                if(func_ == Function.BitOr){
383                        return sterms.get(0) + " | " + sterms.get(1);
384                }
385 
386                if(func_ == Function.BitXor){
387                        return sterms.get(0) + (inSQL ? " # " : " ^ ") + sterms.get(1);
388                }
389 
390                if(func_ == Function.BitShiftLeft){
391                        return sterms.get(0) + " << " + sterms.get(1);
392                }
393 
394                if(func_ == Function.BitShiftRight){
395                        return sterms.get(0) + " >> " + sterms.get(1);
396                }
397 
398                if(func_ == Function.Concat){
399                        return sterms.get(0) + " || " + sterms.get(1);
400                }
401                
402                if(func_ == Function.Eq){
403                        //System.err.println(sterms.get(0) + " = " + sterms.get(1));
404                        return sterms.get(0) + " = " + sterms.get(1);
405                }
406                
407                if(func_ == Function.Neq){
408                        return sterms.get(0) + " <> " + sterms.get(1);
409                }
410                
411                if(func_ == Function.GreaterThan){
412                        return sterms.get(0) + " > " + sterms.get(1);
413                }
414                
415                if(func_ == Function.GreaterThanEq){
416                        return sterms.get(0) + " >= " + sterms.get(1);
417                }
418                
419                if(func_ == Function.LessThan){
420                        return sterms.get(0) + " < " + sterms.get(1);
421                }
422                
423                if(func_ == Function.LessThanEq){
424                        return sterms.get(0) + " <= " + sterms.get(1);
425                }
426                
427                // map to complex expressions
428                if(func_ == Function.StrContains){
429                        return "strpos(" + sterms.get(0) + ", " + sterms.get(1) + ") > 0";
430                }
431 
432                if(func_ == Function.StrStartsWith){
433                        return "strpos(" + sterms.get(0) + ", " + sterms.get(1) + ") = 1";
434                }
435 
436                if(func_ == Function.StrEndsWith){
437                        return "substr(" + sterms.get(0) + ", length(" + sterms.get(0) + 
438                                ") - length(" + sterms.get(1) + ") + 1) = " + sterms.get(1);
439                }
440                
441                // map to direct functions
442                StringBuilder sb = new StringBuilder();
443                sb.append((inSQL ? func_.getPgFunction() : func_.getName()) + "(");
444                for(int i=0; i<func_.arity(); i++){
445                        sb.append(sterms.get(i));
446                        if(i != func_.arity() - 1){
447                                sb.append(", ");
448                        }
449                }
450                sb.append(")");
451                
452                
453                return sb.toString();
454        }
455        
456        public String toString(){
457                return getStringForm(false);
458        }
459}

[all classes][tuffy.ra]
EMMA 2.0.5312 EclEmma Fix 2 (C) Vladimir Roubtsov