001    package railo.runtime.op;
002    
003    import java.io.IOException;
004    import java.math.BigDecimal;
005    import java.util.Calendar;
006    import java.util.Date;
007    import java.util.Locale;
008    
009    import railo.commons.date.DateTimeUtil;
010    import railo.runtime.exp.ExpressionException;
011    import railo.runtime.exp.PageException;
012    import railo.runtime.i18n.LocaleFactory;
013    import railo.runtime.op.date.DateCaster;
014    import railo.runtime.type.Collection;
015    import railo.runtime.type.dt.DateTime;
016    import railo.runtime.type.dt.DateTimeImpl;
017    import railo.runtime.type.util.CollectionUtil;
018    
019    /**
020     * class to compare objects and primitive value types
021     * 
022     * 
023     */
024    public final class Operator {
025    
026    
027            /** 
028             * compares two Objects 
029             * @param left 
030             * @param right 
031             * @return different of objects as int
032             * @throws PageException
033             */ 
034            public static int compare(Object left, Object right) throws PageException { 
035                    //print.dumpStack();
036                    if(left instanceof String)                      return compare((String)left,right);
037                    else if(left instanceof Number)         return compare(((Number)left).doubleValue(),right);
038                    else if(left instanceof Boolean)        return compare(((Boolean)left).booleanValue(),right);
039                    else if(left instanceof Date)           return compare((Date)left ,right);
040                    else if(left instanceof Castable)       return compare(((Castable)left) ,right); 
041                    else if(left instanceof Locale)         return compare(((Locale)left) ,right); 
042                    else if(left==null)                             return compare("",right);
043                    /*/NICE disabled at the moment left Comparable 
044                    else if(left instanceof Comparable) { 
045                            return ((Comparable)left).compareTo(right);
046                    } */
047                    else if(left instanceof Character)      return compare( ((Character)left).toString() , right ); 
048                    else if(left instanceof Calendar)       return compare( ((Calendar)left).getTime() , right ); 
049                    else {
050                            return error(false,true); 
051                    }
052            } 
053            
054            public static int compare(Locale left, Object right) throws PageException { 
055                    if(right instanceof String)                     return compare(left,(String)right); 
056                    else if(right instanceof Number)        return compare(left,Caster.toString(right)); 
057                    else if(right instanceof Boolean)       return compare(left,Caster.toString(right)); 
058                    else if(right instanceof Date)          return compare(left,Caster.toString(right)); 
059                    else if(right instanceof Castable)      return compare(left,((Castable)right).castToString()); 
060                    else if(right instanceof Locale)        return left.toString().compareTo(right.toString()); 
061                    else if(right==null)                            return compare( left, "" ); 
062                    else if(right instanceof Character)     return compare(left,((Character)right).toString()); 
063                    else if(right instanceof Calendar)      return compare(left, Caster.toString(((Calendar)right).getTime())  ); 
064                    else return error(false,true); 
065            } 
066            
067            public static int compare(Object left, Locale right) throws PageException { 
068                    return -compare(right,left); 
069            }
070            
071            public static int compare(Locale left, String right) { 
072                    Locale rightLocale = LocaleFactory.getLocale(right, null);
073                    if(rightLocale==null) return LocaleFactory.toString(left).compareTo(right);
074                    return left.toString().compareTo(rightLocale.toString());
075            }
076            
077            public static int compare(String left, Locale right) { 
078                    return -compare(right,left);
079            }
080            
081            /** 
082             * compares a Object with a String 
083             * @param left 
084             * @param right 
085             * @return difference as int
086             * @throws PageException
087             */ 
088            public static int compare(Object left, String right) throws PageException { 
089                    if(left instanceof String)                      return compare((String)left, right ); 
090                    else if(left instanceof Number)         return compare( ((Number)left).doubleValue() , right ); 
091                    else if(left instanceof Boolean)        return compare( ((Boolean)left).booleanValue(), right ); 
092                    else if(left instanceof Date)           return compare( (Date)left , right ); 
093                    else if(left instanceof Castable)       return ((Castable)left).compareTo(right ); 
094                    else if(left instanceof Locale)         return compare( (Locale)left , right ); 
095                    else if(left==null)                             return "".compareToIgnoreCase(right);
096                    else if(left instanceof Character)      return compare( ((Character)left).toString() , right ); 
097                    else if(left instanceof Calendar)       return compare( ((Calendar)left).getTime() , right ); 
098                    
099                    else return error(false,true);
100            } 
101    
102            /** 
103             * compares a String with a Object 
104             * @param left 
105             * @param right 
106             * @return difference as int
107             * @throws PageException
108             */ 
109            public static int compare(String left, Object right) throws PageException { 
110                    if(right instanceof String)                     return compare(left,(String)right); 
111                    else if(right instanceof Number)        return compare(left,((Number)right).doubleValue()); 
112                    else if(right instanceof Boolean)       return compare(left,((Boolean)right).booleanValue()?1:0); 
113                    else if(right instanceof Date)          return compare(left,(Date)right); 
114                    else if(right instanceof Castable)      return -((Castable)right).compareTo(left);//compare(left ,((Castable)right).castToString());
115                    else if(right instanceof Locale)        return compare(left ,(Locale)right);
116                    else if(right==null)                            return left.compareToIgnoreCase("");
117                    else if(right instanceof Character)     return compare(left ,((Character)right).toString());
118                    else if(right instanceof Calendar)      return compare(left, ((Calendar)right).getTime()  ); 
119                    else return error(false,true);  
120            } 
121    
122            /** 
123             * compares a Object with a double 
124             * @param left 
125             * @param right 
126             * @return difference as int
127             * @throws PageException
128             */ 
129            public static int compare(Object left, double right) throws PageException { 
130                    if(left instanceof Number)                      return compare( ((Number)left).doubleValue() ,right ); 
131                    else if(left instanceof String)         return compare( (String)left, right ); 
132                    else if(left instanceof Boolean)        return compare( ((Boolean)left).booleanValue()?1D:0D , right ); 
133                    else if(left instanceof Date)           return compare( ((Date)left) ,right); 
134                    else if(left instanceof Castable)       return ((Castable)left).compareTo(right); 
135                    //else if(left instanceof Castable)     return compare(((Castable)left).castToDoubleValue() , right ); 
136                    else if(left instanceof Locale)         return compare( ((Locale)left), Caster.toString(right)); 
137                    else if(left==null)                             return -1;
138                    else if(left instanceof Character)      return compare(((Character)left).toString(),right);
139                    else if(left instanceof Calendar)       return compare( ((Calendar)left).getTime() , right ); 
140                    else {
141                            return error(false,true); 
142                    }
143            } 
144    
145            /** 
146             * compares a double with a Object 
147             * @param left 
148             * @param right 
149             * @return difference as int
150             * @throws PageException
151             */ 
152            public static int compare(double left, Object right) throws PageException { 
153                    if(right instanceof Number)                     return compare(left,((Number)right).doubleValue()); 
154                    else if(right instanceof String)        return compare(left,(String)right); 
155                    else if(right instanceof Boolean)       return compare(left,((Boolean)right).booleanValue()?1D:0D); 
156                    else if(right instanceof Date)          return compare(left,((Date)right)); 
157                    else if(right instanceof Castable)      return -((Castable)right).compareTo(left);//compare(left ,((Castable)right).castToDoubleValue());
158                    else if(right instanceof Locale)        return compare(Caster.toString(left) ,((Locale)right));
159                    else if(right==null)                            return 1;
160                    else if(right instanceof Character)     return compare(left ,((Character)right).toString());
161                    else if(right instanceof Calendar)      return compare(left, ((Calendar)right).getTime() ); 
162                    else return error(true,false);  
163            } 
164    
165            
166            /** 
167             * compares a Object with a boolean 
168             * @param left 
169             * @param right 
170             * @return difference as int
171             * @throws PageException
172             */ 
173            public static int compare(Object left, boolean right) throws PageException { 
174                    if(left instanceof Boolean)                     return compare(((Boolean)left).booleanValue(),right); 
175                    else if(left instanceof String)         return compare((String)left,right); 
176                    else if(left instanceof Number)         return compare(((Number)left).doubleValue(),right?1D:0D); 
177                    else if(left instanceof Date)           return compare(((Date)left),right?1:0); 
178                    else if(left instanceof Castable)       return ((Castable)left).compareTo(right );
179                    else if(left instanceof Locale)         return compare(((Locale)left),Caster.toString(right)); 
180                    else if(left==null)                             return -1;
181                    else if(left instanceof Character)      return compare(((Character)left).toString(),right);
182                    else if(left instanceof Calendar)       return compare( ((Calendar)left).getTime() , right?1:0 ); 
183                    else return error(false,true);  
184            } 
185    
186            /** 
187             * compares a boolean with a Object 
188             * @param left 
189             * @param right 
190             * @return difference as int
191             * @throws PageException
192             */ 
193            public static int compare(boolean left, Object right) throws PageException { 
194                    if(right instanceof Boolean)            return compare(left,((Boolean)right).booleanValue()); 
195                    else if(right instanceof String)        return compare(left?1:0,(String)right); 
196                    else if(right instanceof Number)        return compare(left?1D:0D,((Number)right).doubleValue()); 
197                    else if(right instanceof Date)          return compare(left?1:0,((Date)right)); 
198                    else if(right instanceof Castable)      return -((Castable)right).compareTo(left);//compare(left ,((Castable)right).castToBooleanValue());
199                    else if(right instanceof Locale)        return compare(Caster.toString(left),((Locale)right)); 
200                    else if(right==null)                            return 1;
201                    else if(right instanceof Character)     return compare(left ,((Character)right).toString());
202                    else if(right instanceof Calendar)      return compare(left?1:0, ((Calendar)right).getTime()  ); 
203                    else return error(true,false);  
204            }
205            
206            /** 
207             * compares a Object with a Date 
208             * @param left 
209             * @param right 
210             * @return difference as int
211             * @throws PageException
212             */ 
213            public static int compare(Object left, Date right) throws PageException { 
214                    if(left instanceof String)                      return compare((String)left,right); 
215                    else if(left instanceof Number)         return compare(((Number)left).doubleValue() ,right.getTime()/1000 ); 
216                    else if(left instanceof Boolean)        return compare( ((Boolean)left).booleanValue()?1D:0D , right.getTime()/1000 ); 
217                    else if(left instanceof Date)           return compare( ((Date)left) , right ); 
218                    else if(left instanceof Castable)       return ((Castable)left).compareTo(Caster.toDatetime(right,null) );
219                    else if(left instanceof Locale)         return compare( ((Locale)left) , Caster.toString(right)); 
220                    else if(left==null)                             return compare("", right);
221                    else if(left instanceof Character)      return compare(((Character)left).toString(),right);
222                    else if(left instanceof Calendar)       return compare( ((Calendar)left).getTime() , right ); 
223                    else return error(false,true);  
224            }  
225    
226            /** 
227             * compares a Date with a Object 
228             * @param left 
229             * @param right 
230             * @return difference as int
231             * @throws PageException
232             */ 
233            public static int compare(Date left, Object right) throws PageException { 
234                    if(right instanceof String)                     return compare(left,(String)right); 
235                    else if(right instanceof Number)        return compare(left.getTime()/1000,((Number)right).doubleValue()); 
236                    else if(right instanceof Boolean)       return compare(left.getTime()/1000,((Boolean)right).booleanValue()?1D:0D); 
237                    else if(right instanceof Date)          return compare(left.getTime()/1000,((Date)right).getTime()/1000); 
238                    else if(right instanceof Castable)      return -((Castable)right).compareTo(Caster.toDate(left,null));//compare(left ,(Date)((Castable)right).castToDateTime());
239                    else if(right instanceof Locale)        return compare(Caster.toString(left),(Locale)right); 
240                    else if(right==null)                            return compare(left,"");
241                    else if(right instanceof Character)     return compare(left ,((Character)right).toString());
242                    else if(right instanceof Calendar)      return compare(left.getTime()/1000, ((Calendar)right).getTime().getTime()/1000  ); 
243                    else return error(true,false);  
244            }
245            
246            public static int compare(Castable left, Object right) throws PageException { 
247                    if(right instanceof String)                     return left.compareTo((String)right); 
248                    else if(right instanceof Number)        return left.compareTo(((Number)right).doubleValue()); 
249                    else if(right instanceof Boolean)       return left.compareTo(((Boolean)right).booleanValue()?1d:0d);
250                    else if(right instanceof Date)          return left.compareTo(Caster.toDate(right,null));
251                    else if(right instanceof Castable)      return compare(left.castToString() , ((Castable)right).castToString() ); 
252                    else if(right instanceof Locale)        return compare(left.castToString() , (Locale)right);
253                    else if(right == null)                          return compare(left.castToString(), "" ); 
254                    else if(right instanceof Character)     return left.compareTo(((Character)right).toString());
255                    else if(right instanceof Calendar)      return left.compareTo(new DateTimeImpl(((Calendar)right).getTime()) ); 
256                    else return error(true,false); 
257            }
258            
259            public static int compare(Object left, Castable right) throws PageException { 
260                    return -compare(right,left); 
261            }
262                    
263    
264            /** 
265             * compares a String with a String 
266             * @param left 
267             * @param right 
268             * @return difference as int
269             */ 
270            public static int compare(String left, String right) { 
271                    if(Decision.isNumeric(left)) {
272                            if(Decision.isNumeric(right)){
273                                    // long numbers
274                                    if(left.length()>9 || right.length()>9) {
275                                            try{
276                                                    return new BigDecimal(left).compareTo(new BigDecimal(right));
277                                            }
278                                            catch(Throwable t){}
279                                    }
280                                    return compare(Caster.toDoubleValue(left,Double.NaN),Caster.toDoubleValue(right,Double.NaN));
281                            }
282                    }
283                    else if(Decision.isBoolean(left)) {
284                            return compare(Caster.toBooleanValue(left,false)?1D:0D,right);
285                    }
286    //               NICE Date compare, perhaps datetime to double
287                    return left.compareToIgnoreCase(right); 
288            } 
289    
290        /** 
291         * compares a String with a double 
292         * @param left 
293         * @param right 
294         * @return difference as int
295         */ 
296        public static int compare(String left, double right) { 
297            if(Decision.isNumeric(left)) {
298                if(left.length()>9) {
299                    try{
300                            return new BigDecimal(left).compareTo(new BigDecimal(right));
301                    }
302                    catch(Throwable t){}
303                }
304                    return compare(Caster.toDoubleValue(left,Double.NaN),right); 
305            }
306            if(Decision.isBoolean(left))
307                return compare(Caster.toBooleanValue(left,false),right); 
308            
309            if(left.length()==0) return -1;
310            char leftFirst=left.charAt(0);
311            if(leftFirst>='0' && leftFirst<='9')
312                return left.compareToIgnoreCase(Caster.toString(right));
313            return leftFirst-'0';
314        }
315    
316        /** 
317             * compares a String with a boolean 
318             * @param left 
319             * @param right 
320             * @return difference as int
321             */ 
322            public static int compare(String left, boolean right) { 
323                    if(Decision.isBoolean(left))
324                return compare(Caster.toBooleanValue(left,false),right); 
325                    if(Decision.isNumeric(left))
326                return compare(Caster.toDoubleValue(left,Double.NaN),right?1d:0d); 
327            
328            if(left.length()==0) return -1;
329            char leftFirst=left.charAt(0);
330            //print.ln(left+".compareTo("+Caster.toString(right)+")");
331            //p(left);
332            if(leftFirst>='0' && leftFirst<='9')
333                return left.compareToIgnoreCase(Caster.toString(right?1D:0D));
334            return leftFirst-'0';
335            } 
336    
337            /** 
338             * compares a String with a Date 
339             * @param left 
340             * @param right 
341             * @return difference as int
342             * @throws PageException
343             */ 
344            public static int compare(String left, Date right) throws PageException { 
345                    return -compare(right,left);
346            } 
347    
348            /** 
349             * compares a double with a String 
350             * @param left 
351             * @param right 
352             * @return difference as int
353             */ 
354        public static int compare(double left, String right) { 
355            return -compare(right,left);
356        }
357        
358            /** 
359             * compares a double with a double 
360             * @param left 
361             * @param right 
362             * @return difference as int
363             */ 
364        public static int compare(double left, double right) { 
365            if((left)<(right))return -1; 
366            else if((left)>(right))return 1; 
367            else return 0;
368        }
369    
370            /** 
371             * compares a double with a boolean 
372             * @param left 
373             * @param right 
374             * @return difference as int
375             */ 
376            public static int compare(double left, boolean right) { 
377                            return compare(left,right?1d:0d); 
378            } 
379    
380            /** 
381             * compares a double with a Date 
382             * @param left 
383             * @param right 
384             * @return difference as int
385             */ 
386            public static int compare(double left, Date right) { 
387                            return compare(DateTimeUtil.getInstance().toDateTime(left).getTime()/1000,right.getTime()/1000); 
388            } 
389    
390            /** 
391             * compares a boolean with a double 
392             * @param left 
393             * @param right 
394             * @return difference as int
395             */ 
396            public static int compare(boolean left, double right) { 
397                            return compare(left?1d:0d, right); 
398            } 
399    
400            /** 
401             * compares a boolean with a double 
402             * @param left 
403             * @param right 
404             * @return difference as int
405             */ 
406            public static int compare(boolean left, String right) { 
407                            return -compare(right,left); 
408            } 
409    
410            /** 
411             * compares a boolean with a boolean 
412             * @param left 
413             * @param right 
414             * @return difference as int
415             */ 
416            public static int compare(boolean left, boolean right) { 
417                            if(left)return right?0:1; 
418                            return right?-1:0; 
419            } 
420    
421            /** 
422             * compares a boolean with a Date 
423             * @param left 
424             * @param right 
425             * @return difference as int
426             */ 
427            public static int compare(boolean left, Date right) { 
428                            return compare(left?1D:0D,right); 
429            } 
430    
431            /** 
432             * compares a Date with a String 
433             * @param left 
434             * @param right 
435             * @return difference as int
436             * @throws PageException
437             */ 
438            public static int compare(Date left, String right) throws PageException { 
439                    if(Decision.isNumeric(right)) return compare(left.getTime()/1000,Caster.toDoubleValue(right));
440                    DateTime dt=DateCaster.toDateAdvanced(right,true,null,null);
441                    if(dt!=null) {
442                            return compare(left.getTime()/1000,dt.getTime()/1000);          
443                    }
444                    return Caster.toString(left).compareToIgnoreCase(right);
445            } 
446    
447            /** 
448             * compares a Date with a double 
449             * @param left 
450             * @param right 
451             * @return difference as int
452             */ 
453            public static int compare(Date left, double right) { 
454                            return compare(left.getTime()/1000, DateTimeUtil.getInstance().toDateTime(right).getTime()/1000); 
455            } 
456    
457            /** 
458             * compares a Date with a boolean 
459             * @param left 
460             * @param right 
461             * @return difference as int
462             */ 
463            public static int compare(Date left, boolean right) { 
464                            return compare(left,right?1D:0D); 
465            } 
466    
467            /** 
468             * compares a Date with a Date 
469             * @param left 
470             * @param right 
471             * @return difference as int
472             */ 
473            public static int compare(Date left, Date right) { 
474                            return compare(left.getTime()/1000,right.getTime()/1000); 
475            }        
476    
477            private static int error(boolean leftIsOk, boolean rightIsOk, Object left, Object right) throws ExpressionException { 
478                    throw new ExpressionException("can't compare complex object types ("+Caster.toClassName(left)+" - "+Caster.toClassName(right)+") as simple value");
479            }
480            private static int error(boolean leftIsOk, boolean rightIsOk) throws ExpressionException { 
481                    // TODO remove this method
482                    throw new ExpressionException("can't compare complex object types as simple value");
483            }
484    
485            /**
486             * Method to compare to different values, return true of objects are same otherwise false
487             * @param left left value to compare
488             * @param right right value to compare
489             * @param caseSensitive check case sensitive  or not
490             * @return is same or not
491             * @throws PageException
492             */
493            public static boolean equals(Object left, Object right, boolean caseSensitive) throws PageException {
494                    if(caseSensitive) {
495                            try {
496                                    return Caster.toString(left).equals(Caster.toString(right));
497                            } catch (ExpressionException e) {
498                                    return compare(left,right)==0;
499                            }
500                    }
501                    return compare(left,right)==0;
502            }
503    
504            public static boolean equals(Object left, Object right, boolean caseSensitive, boolean allowComplexValues) throws PageException {
505                    if(!allowComplexValues || (Decision.isSimpleValue(left) && Decision.isSimpleValue(right)))
506                            return equals(left, right, caseSensitive);
507                    return left.equals(right);
508            }
509            public static boolean equalsEL(Object left, Object right, boolean caseSensitive, boolean allowComplexValues) {
510                    if(!allowComplexValues || (Decision.isSimpleValue(left) && Decision.isSimpleValue(right))){
511                            try {
512                                    return equals(left, right, caseSensitive);
513                            } catch (PageException e) {
514                                    return false;
515                            }
516                    }
517                    if(left instanceof Collection && right instanceof Collection)
518                            return CollectionUtil.equals((Collection)left, (Collection)right);
519                    
520                    if(left==null) return right==null;
521                    return left.equals(right);
522            }
523            
524            
525    
526            /**
527             * check if left is inside right (String-> ignore case)
528             * @param left string to check
529             * @param right substring to find in string
530             * @return return if substring has been found
531             * @throws PageException
532             */
533            public static boolean ct(Object left, Object right) throws PageException {
534                    return Caster.toString(left).toLowerCase().indexOf(Caster.toString(right).toLowerCase())!=-1;           
535            } 
536    
537            /**
538             * Equivalence: Return True if both operands are True or both are False. The EQV operator is the opposite of the XOR operator. For example, True EQV True is True, but True EQV False is False.
539             * @param left value to check
540             * @param right value to check
541             * @return result of operation
542             * @throws PageException
543             */
544            public static boolean eqv(Object left, Object right) throws PageException {
545                    return eqv(Caster.toBooleanValue(left),Caster.toBooleanValue(right));   
546            }
547    
548            /**
549             * Equivalence: Return True if both operands are True or both are False. The EQV operator is the opposite of the XOR operator. For example, True EQV True is True, but True EQV False is False.
550             * @param left value to check
551             * @param right value to check
552             * @return result of operation
553             */
554            public static boolean eqv(boolean left, boolean right) {
555                    return (left==true && right==true) || (left==false && right==false);    
556            }
557    
558            /**
559             * Implication: The statement A IMP B is the equivalent of the logical statement 
560             * "If A Then B." A IMP B is False only if A is True and B is False. It is True in all other cases.
561             * @param left value to check
562             * @param right value to check
563             * @return result
564             * @throws PageException
565             */
566            public static boolean imp(Object left, Object right) throws PageException {
567                    return imp(Caster.toBooleanValue(left),Caster.toBooleanValue(right));   
568            } 
569    
570            /**
571             * Implication: The statement A IMP B is the equivalent of the logical statement 
572             * "If A Then B." A IMP B is False only if A is True and B is False. It is True in all other cases.
573             * @param left value to check
574             * @param right value to check
575             * @return result
576             */
577            public static boolean imp(boolean left, boolean right) {
578                    return !(left==true && right==false);   
579            } 
580    
581            /**
582             * check if left is not inside right (String-> ignore case)
583             * @param left string to check
584             * @param right substring to find in string
585             * @return return if substring NOT has been found
586             * @throws PageException
587             */
588            public static boolean nct(Object left, Object right) throws PageException {
589                    return !ct(left,right);         
590            }
591    
592    
593            /**
594             * simple reference compersion
595             * @param left
596             * @param right
597             * @return
598             * @throws PageException
599             */
600            public static boolean eeq(Object left, Object right) throws PageException {
601                    return left==right;             
602            }
603    
604    
605            /**
606             * simple reference compersion
607             * @param left
608             * @param right
609             * @return
610             * @throws PageException
611             */
612            public static boolean neeq(Object left, Object right) throws PageException {
613                    return left!=right;             
614            }
615            
616            /**
617             * calculate the exponent of the left value 
618             * @param left value to get exponent from
619             * @param right exponent count
620             * @return return expoinended value
621             * @throws PageException
622             */
623            public static double exponent(Object left, Object right) throws PageException {
624                    return StrictMath.pow(Caster.toDoubleValue(left),Caster.toDoubleValue(right));
625            } 
626            
627            public static double exponent(double left, double right) {
628                    return StrictMath.pow(left,right);
629            } 
630            
631            public static double intdiv(double left, double right) {
632                    return ((int)left)/((int)right);
633            } 
634            
635            public static double div(double left, double right) {
636                    if(right==0d)
637                            throw new ArithmeticException("Division by zero is not possible");
638                    return left/right;
639            } 
640            
641            public static float exponent(float left, float right) {
642                    return (float) StrictMath.pow(left,right);
643            } 
644        
645    
646        /**
647         * concat 2 CharSequences
648         * @param left
649         * @param right
650         * @return concated String
651         */
652            public static CharSequence concat(CharSequence left, CharSequence right) {
653                    if(left instanceof Appendable) {
654                            try {
655                                    ((Appendable)left).append(right);
656                                    return left;
657                            } catch (IOException e) {}
658                    }
659                    return new StringBuilder(left).append(right);
660            }
661    
662        /**
663         * plus operation
664         * @param left
665         * @param right
666         * @return result of the opertions
667         */
668        public final static double plus(double left, double right) {
669            return left+right;
670        }
671        
672        /**
673         * minus operation
674         * @param left
675         * @param right
676         * @return result of the opertions
677         */
678        public static double minus(double left, double right) {
679            return left-right;
680        }
681        
682        /**
683         * modulus operation
684         * @param left
685         * @param right
686         * @return result of the opertions
687         */
688        public static double modulus(double left, double right) {
689            return left%right;
690        }
691        
692        /**
693         * divide operation
694         * @param left
695         * @param right
696         * @return result of the opertions
697         */
698        public static double divide(double left, double right) {
699            return left/right;
700        }
701        
702        /**
703         * multiply operation
704         * @param left
705         * @param right
706         * @return result of the opertions
707         */
708        public static double multiply(double left, double right) {
709            return left*right;
710        }
711    
712        /**
713         * bitand operation
714         * @param left
715         * @param right
716         * @return result of the opertions
717         */
718        public static double bitand(double left, double right) {
719            return (int)left&(int)right;
720        }
721    
722        /**
723         * bitand operation
724         * @param left
725         * @param right
726         * @return result of the opertions
727         */
728        public static double bitor(double left, double right) {
729            return (int)left|(int)right;
730        }
731        
732    
733        public static Double divRef(Object left, Object right) throws PageException {
734                    double r = Caster.toDoubleValue(right);
735            if(r==0d)
736                            throw new ArithmeticException("Division by zero is not possible");
737                    return Caster.toDouble(Caster.toDoubleValue(left)/r);
738            }
739        
740        public static Double exponentRef(Object left, Object right) throws PageException {
741                    return Caster.toDouble(StrictMath.pow(Caster.toDoubleValue(left),Caster.toDoubleValue(right)));
742            }
743        
744        public static Double intdivRef(Object left, Object right) throws PageException {
745                    return Caster.toDouble(Caster.toIntValue(left)/Caster.toIntValue(right));
746            }
747        
748        public static Double plusRef(Object left, Object right) throws PageException {
749                    return Caster.toDouble(Caster.toDoubleValue(left)+Caster.toDoubleValue(right));
750            }
751        
752        public static Double minusRef(Object left, Object right) throws PageException {
753                    return Caster.toDouble(Caster.toDoubleValue(left)-Caster.toDoubleValue(right));
754            }
755        
756        public static Double modulusRef(Object left, Object right) throws PageException {
757                    return Caster.toDouble(Caster.toDoubleValue(left)%Caster.toDoubleValue(right));
758            }
759        
760        public static Double divideRef(Object left, Object right) throws PageException {
761                    return Caster.toDouble(Caster.toDoubleValue(left)/Caster.toDoubleValue(right));
762            }
763        
764        public static Double multiplyRef(Object left, Object right) throws PageException {
765                    return Caster.toDouble(Caster.toDoubleValue(left)*Caster.toDoubleValue(right));
766            }
767    }