1 package org.apache.commons.ognl;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.commons.ognl.enhance.UnsupportedCompilationException;
23
24 import java.lang.reflect.Array;
25 import java.math.BigDecimal;
26 import java.math.BigInteger;
27 import java.util.Enumeration;
28
29
30
31
32
33
34
35 public abstract class OgnlOps
36 implements NumericTypes
37 {
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 public static int compareWithConversion( Object v1, Object v2 )
55 {
56 int result;
57
58 if ( v1 == v2 )
59 {
60 result = 0;
61 }
62 else
63 {
64 int t1 = getNumericType( v1 ), t2 = getNumericType( v2 ), type = getNumericType( t1, t2, true );
65
66 switch ( type )
67 {
68 case BIGINT:
69 result = bigIntValue( v1 ).compareTo( bigIntValue( v2 ) );
70 break;
71
72 case BIGDEC:
73 result = bigDecValue( v1 ).compareTo( bigDecValue( v2 ) );
74 break;
75
76 case NONNUMERIC:
77 if ( ( t1 == NONNUMERIC ) && ( t2 == NONNUMERIC ) )
78 {
79 if ( ( v1 instanceof Comparable ) && v1.getClass().isAssignableFrom( v2.getClass() ) )
80 {
81 result = ( (Comparable) v1 ).compareTo( v2 );
82 break;
83 }
84 throw new IllegalArgumentException( "invalid comparison: " + v1.getClass().getName()
85 + " and " + v2.getClass().getName() );
86 }
87
88 case FLOAT:
89 case DOUBLE:
90 double dv1 = doubleValue( v1 ),
91 dv2 = doubleValue( v2 );
92
93 return ( dv1 == dv2 ) ? 0 : ( ( dv1 < dv2 ) ? -1 : 1 );
94
95 default:
96 long lv1 = longValue( v1 ),
97 lv2 = longValue( v2 );
98
99 return ( lv1 == lv2 ) ? 0 : ( ( lv1 < lv2 ) ? -1 : 1 );
100 }
101 }
102 return result;
103 }
104
105
106
107
108
109
110
111
112
113 public static boolean isEqual( Object object1, Object object2 )
114 {
115 boolean result = false;
116
117 if ( object1 == object2 )
118 {
119 result = true;
120 }
121 else
122 {
123 if ( ( object1 != null ) && object1.getClass().isArray() )
124 {
125 if ( ( object2 != null ) && object2.getClass().isArray() && ( object2.getClass()
126 == object1.getClass() ) )
127 {
128 result = ( Array.getLength( object1 ) == Array.getLength( object2 ) );
129 if ( result )
130 {
131 for ( int i = 0, icount = Array.getLength( object1 ); result && ( i < icount ); i++ )
132 {
133 result = isEqual( Array.get( object1, i ), Array.get( object2, i ) );
134 }
135 }
136 }
137 }
138 else
139 {
140
141 result =
142 ( object1 != null ) && ( object2 != null )
143 && ( object1.equals( object2 ) || ( compareWithConversion( object1, object2 ) == 0 ) );
144 }
145 }
146 return result;
147 }
148
149 public static boolean booleanValue( boolean value )
150 {
151 return value;
152 }
153
154 public static boolean booleanValue( int value )
155 {
156 return value > 0;
157 }
158
159 public static boolean booleanValue( float value )
160 {
161 return value > 0;
162 }
163
164 public static boolean booleanValue( long value )
165 {
166 return value > 0;
167 }
168
169 public static boolean booleanValue( double value )
170 {
171 return value > 0;
172 }
173
174
175
176
177
178
179
180
181 public static boolean booleanValue( Object value )
182 {
183 if ( value == null )
184 {
185 return false;
186 }
187 Class<?> c = value.getClass();
188
189 if ( c == Boolean.class )
190 {
191 return (Boolean) value;
192 }
193
194
195
196 if ( c == Character.class )
197 {
198 return (Character) value != 0;
199 }
200 return !( value instanceof Number ) || ( (Number) value ).doubleValue() != 0;
201
202 }
203
204
205
206
207
208
209
210
211 public static long longValue( Object value )
212 {
213 if ( value == null )
214 {
215 return 0L;
216 }
217 Class<?> c = value.getClass();
218 if ( c.getSuperclass() == Number.class )
219 {
220 return ( (Number) value ).longValue();
221 }
222 if ( c == Boolean.class )
223 {
224 return (Boolean) value ? 1 : 0;
225 }
226 if ( c == Character.class )
227 {
228 return (Character) value;
229 }
230 return Long.parseLong( stringValue( value, true ) );
231 }
232
233
234
235
236
237
238
239
240 public static double doubleValue( Object value )
241 {
242 if ( value == null )
243 {
244 return 0.0;
245 }
246 Class<?> c = value.getClass();
247 if ( c.getSuperclass() == Number.class )
248 {
249 return ( (Number) value ).doubleValue();
250 }
251 if ( c == Boolean.class )
252 {
253 return (Boolean) value ? 1 : 0;
254 }
255 if ( c == Character.class )
256 {
257 return (Character) value;
258 }
259 String s = stringValue( value, true );
260
261 return ( s.length() == 0 ) ? 0.0 : Double.parseDouble( s );
262 }
263
264
265
266
267
268
269
270
271 public static BigInteger bigIntValue( Object value )
272 {
273 if ( value == null )
274 {
275 return BigInteger.valueOf( 0L );
276 }
277 Class<?> c = value.getClass();
278 if ( c == BigInteger.class )
279 {
280 return (BigInteger) value;
281 }
282 if ( c == BigDecimal.class )
283 {
284 return ( (BigDecimal) value ).toBigInteger();
285 }
286 if ( c.getSuperclass() == Number.class )
287 {
288 return BigInteger.valueOf( ( (Number) value ).longValue() );
289 }
290 if ( c == Boolean.class )
291 {
292 return BigInteger.valueOf( (Boolean) value ? 1 : 0 );
293 }
294 if ( c == Character.class )
295 {
296 return BigInteger.valueOf( (Character) value );
297 }
298 return new BigInteger( stringValue( value, true ) );
299 }
300
301
302
303
304
305
306
307
308 public static BigDecimal bigDecValue( Object value )
309 {
310 if ( value == null )
311 {
312 return BigDecimal.valueOf( 0L );
313 }
314 Class<?> c = value.getClass();
315 if ( c == BigDecimal.class )
316 {
317 return (BigDecimal) value;
318 }
319 if ( c == BigInteger.class )
320 {
321 return new BigDecimal( (BigInteger) value );
322 }
323 if ( c == Boolean.class )
324 {
325 return BigDecimal.valueOf( (Boolean) value ? 1 : 0 );
326 }
327 if ( c == Character.class )
328 {
329 return BigDecimal.valueOf( ( (Character) value ).charValue() );
330 }
331 return new BigDecimal( stringValue( value, true ) );
332 }
333
334
335
336
337
338
339
340
341
342 public static String stringValue( Object value, boolean trim )
343 {
344 String result;
345
346 if ( value == null )
347 {
348 result = OgnlRuntime.NULL_STRING;
349 }
350 else
351 {
352 result = value.toString();
353 if ( trim )
354 {
355 result = result.trim();
356 }
357 }
358 return result;
359 }
360
361
362
363
364
365
366
367
368 public static String stringValue( Object value )
369 {
370 return stringValue( value, false );
371 }
372
373
374
375
376
377
378
379 public static int getNumericType( Object value )
380 {
381 if ( value != null )
382 {
383 Class<?> c = value.getClass();
384 if ( c == Integer.class )
385 {
386 return INT;
387 }
388 if ( c == Double.class )
389 {
390 return DOUBLE;
391 }
392 if ( c == Boolean.class )
393 {
394 return BOOL;
395 }
396 if ( c == Byte.class )
397 {
398 return BYTE;
399 }
400 if ( c == Character.class )
401 {
402 return CHAR;
403 }
404 if ( c == Short.class )
405 {
406 return SHORT;
407 }
408 if ( c == Long.class )
409 {
410 return LONG;
411 }
412 if ( c == Float.class )
413 {
414 return FLOAT;
415 }
416 if ( c == BigInteger.class )
417 {
418 return BIGINT;
419 }
420 if ( c == BigDecimal.class )
421 {
422 return BIGDEC;
423 }
424 }
425 return NONNUMERIC;
426 }
427
428 public static Object toArray( char value, Class<?> toType )
429 throws OgnlException
430 {
431 return toArray( Character.valueOf( value ), toType );
432 }
433
434 public static Object toArray( byte value, Class<?> toType )
435 throws OgnlException
436 {
437 return toArray( Byte.valueOf( value ), toType );
438 }
439
440 public static Object toArray( int value, Class<?> toType )
441 throws OgnlException
442 {
443 return toArray( Integer.valueOf( value ), toType );
444 }
445
446 public static Object toArray( long value, Class<?> toType )
447 throws OgnlException
448 {
449 return toArray( Long.valueOf( value ), toType );
450 }
451
452 public static Object toArray( float value, Class<?> toType )
453 throws OgnlException
454 {
455 return toArray( Float.valueOf( value ), toType );
456 }
457
458 public static Object toArray( double value, Class<?> toType )
459 throws OgnlException
460 {
461 return toArray( Double.valueOf( value ), toType );
462 }
463
464 public static Object toArray( boolean value, Class<?> toType )
465 throws OgnlException
466 {
467 return toArray( Boolean.valueOf( value ), toType );
468 }
469
470 public static <T> Object convertValue( char value, Class<T> toType )
471 throws OgnlException
472 {
473 return convertValue( Character.valueOf(value), toType );
474 }
475
476 public static <T> Object convertValue( byte value, Class<T> toType )
477 throws OgnlException
478 {
479 return convertValue( Byte.valueOf( value ), toType );
480 }
481
482 public static <T> Object convertValue( int value, Class<T> toType )
483 throws OgnlException
484 {
485 return convertValue( Integer.valueOf( value ), toType );
486 }
487
488 public static <T> Object convertValue( long value, Class<T> toType )
489 throws OgnlException
490 {
491 return convertValue( Long.valueOf( value ), toType );
492 }
493
494 public static <T> Object convertValue( float value, Class<T> toType )
495 throws OgnlException
496 {
497 return convertValue( Float.valueOf( value ), toType );
498 }
499
500 public static <T> Object convertValue( double value, Class<T> toType )
501 throws OgnlException
502 {
503 return convertValue( Double.valueOf( value ), toType );
504 }
505
506 public static <T> Object convertValue( boolean value, Class<T> toType )
507 throws OgnlException
508 {
509 return convertValue( Boolean.valueOf( value ), toType );
510 }
511
512
513
514 public static <T> Object convertValue( char value, Class<T> toType, boolean preventNull )
515 throws OgnlException
516 {
517 return convertValue( Character.valueOf( value ), toType, preventNull );
518 }
519
520 public static <T> Object convertValue( byte value, Class<T> toType, boolean preventNull )
521 throws OgnlException
522 {
523 return convertValue( Byte.valueOf( value ), toType, preventNull );
524 }
525
526 public static <T> Object convertValue( int value, Class<T> toType, boolean preventNull )
527 throws OgnlException
528 {
529 return convertValue( Integer.valueOf( value ), toType, preventNull );
530 }
531
532 public static <T> Object convertValue( long value, Class<T> toType, boolean preventNull )
533 throws OgnlException
534 {
535 return convertValue( Long.valueOf( value ), toType, preventNull );
536 }
537
538 public static <T> Object convertValue( float value, Class<T> toType, boolean preventNull )
539 throws OgnlException
540 {
541 return convertValue( new Float( value ), toType, preventNull );
542 }
543
544 public static <T> Object convertValue( double value, Class<T> toType, boolean preventNull )
545 throws OgnlException
546 {
547 return convertValue( new Double( value ), toType, preventNull );
548 }
549
550 public static <T> Object convertValue( boolean value, Class<T> toType, boolean preventNull )
551 throws OgnlException
552 {
553 return convertValue( Boolean.valueOf( value ), toType, preventNull );
554 }
555
556
557
558 public static Object toArray( char value, Class<?> toType, boolean preventNull )
559 throws OgnlException
560 {
561 return toArray( Character.valueOf( value ), toType, preventNull );
562 }
563
564 public static Object toArray( byte value, Class<?> toType, boolean preventNull )
565 throws OgnlException
566 {
567 return toArray( Byte.valueOf( value ), toType, preventNull );
568 }
569
570 public static Object toArray( int value, Class<?> toType, boolean preventNull )
571 throws OgnlException
572 {
573 return toArray( Integer.valueOf( value ), toType, preventNull );
574 }
575
576 public static Object toArray( long value, Class<?> toType, boolean preventNull )
577 throws OgnlException
578 {
579 return toArray( Long.valueOf(value), toType, preventNull );
580 }
581
582 public static Object toArray( float value, Class<?> toType, boolean preventNull )
583 throws OgnlException
584 {
585 return toArray( Float.valueOf( value ), toType, preventNull );
586 }
587
588 public static Object toArray( double value, Class<?> toType, boolean preventNull )
589 throws OgnlException
590 {
591 return toArray( Double.valueOf(value), toType, preventNull );
592 }
593
594 public static Object toArray( boolean value, Class<?> toType, boolean preventNull )
595 throws OgnlException
596 {
597 return toArray( Boolean.valueOf( value ), toType, preventNull );
598 }
599
600
601
602
603
604
605
606
607
608 public static Object convertValue( Object value, Class<?> toType )
609 {
610 return convertValue( value, toType, false );
611 }
612
613 public static Object toArray( Object value, Class<?> toType )
614 throws OgnlException
615 {
616 return toArray( value, toType, false );
617 }
618
619 public static Object toArray( Object value, Class<?> toType, boolean preventNulls )
620 throws OgnlException
621 {
622 if ( value == null )
623 {
624 return null;
625 }
626
627 Object result;
628
629 Class<?> aClass = value.getClass();
630 if ( aClass.isArray() && toType.isAssignableFrom( aClass.getComponentType() ) )
631 {
632 return value;
633 }
634
635 if ( !aClass.isArray() )
636 {
637
638 if ( toType == Character.TYPE )
639 {
640 return stringValue( value ).toCharArray();
641 }
642
643 Object arr = Array.newInstance( toType, 1 );
644 Array.set( arr, 0, convertValue( value, toType, preventNulls ) );
645
646 return arr;
647 }
648
649 result = Array.newInstance( toType, Array.getLength( value ) );
650 for ( int i = 0, icount = Array.getLength( value ); i < icount; i++ )
651 {
652 Array.set( result, i, convertValue( Array.get( value, i ), toType ) );
653 }
654
655 if ( result == null && preventNulls )
656 {
657 return value;
658 }
659
660 return result;
661 }
662
663 public static <T> Object convertValue( Object value, Class<T> toType, boolean preventNulls )
664 {
665 Object result = null;
666
667 if ( value != null && toType.isAssignableFrom( value.getClass() ) )
668 {
669 return value;
670 }
671
672 if ( value != null )
673 {
674
675 boolean classIsArray = value.getClass().isArray();
676 boolean toTypeIsArray = toType.isArray();
677 if ( classIsArray && toTypeIsArray)
678 {
679 Class<?> componentType = toType.getComponentType();
680
681 result = Array.newInstance( componentType, Array.getLength( value ) );
682 for ( int i = 0, icount = Array.getLength( value ); i < icount; i++ )
683 {
684 Array.set( result, i, convertValue( Array.get( value, i ), componentType ) );
685 }
686 }
687 else if ( classIsArray && !toTypeIsArray)
688 {
689
690 return convertValue( Array.get( value, 0 ), toType );
691 }
692 else if ( toTypeIsArray )
693 {
694
695 if ( toType.getComponentType() == Character.TYPE )
696 {
697
698 result = stringValue( value ).toCharArray();
699 }
700 else if ( toType.getComponentType() == Object.class )
701 {
702 return new Object[] { value };
703 }
704 }
705 else
706 {
707 if ( ( toType == Integer.class ) || ( toType == Integer.TYPE ) )
708 {
709 result = (int) longValue( value );
710 }
711 else if ( ( toType == Double.class ) || ( toType == Double.TYPE ) )
712 {
713 result = doubleValue( value );
714 }
715 else if ( ( toType == Boolean.class ) || ( toType == Boolean.TYPE ) )
716 {
717 result = booleanValue( value ) ? Boolean.TRUE : Boolean.FALSE;
718 }
719 else if ( ( toType == Byte.class ) || ( toType == Byte.TYPE ) )
720 {
721 result = (byte) longValue( value );
722 }
723 else if ( ( toType == Character.class ) || ( toType == Character.TYPE ) )
724 {
725 result = (char) longValue( value );
726 }
727 else if ( ( toType == Short.class ) || ( toType == Short.TYPE ) )
728 {
729 result = (short) longValue( value );
730 }
731 else if ( ( toType == Long.class ) || ( toType == Long.TYPE ) )
732 {
733 result = longValue( value );
734 }
735 else if ( ( toType == Float.class ) || ( toType == Float.TYPE ) )
736 {
737 result = new Float( doubleValue( value ) );
738 }
739 else if ( toType == BigInteger.class )
740 {
741 result = bigIntValue( value );
742 }
743 else if ( toType == BigDecimal.class )
744 {
745 result = bigDecValue( value );
746 }
747 else if ( toType == String.class )
748 {
749 result = stringValue( value );
750 }
751 }
752 }
753 else
754 {
755 if ( toType.isPrimitive() )
756 {
757 result = OgnlRuntime.getPrimitiveDefaultValue( toType );
758 }
759 else if ( preventNulls && toType == Boolean.class )
760 {
761 result = Boolean.FALSE;
762 }
763 else if ( preventNulls && Number.class.isAssignableFrom( toType ) )
764 {
765 result = OgnlRuntime.getNumericDefaultValue( toType );
766 }
767 }
768
769 if ( result == null && preventNulls )
770 {
771 return value;
772 }
773
774 if ( value != null && result == null )
775 {
776
777 throw new IllegalArgumentException( "Unable to convert type " + value.getClass().getName() + " of " + value
778 + " to type of " + toType.getName() );
779 }
780
781 return result;
782 }
783
784
785
786
787
788
789
790
791
792
793
794
795 public static int getIntValue( Object value )
796 {
797 try
798 {
799 if ( value == null )
800 {
801 return -1;
802 }
803
804 if ( Number.class.isInstance( value ) )
805 {
806
807 return ( (Number) value ).intValue();
808 }
809
810 String str = String.class.isInstance( value ) ? (String) value : value.toString();
811
812 return Integer.parseInt( str );
813 }
814 catch ( Throwable t )
815 {
816 throw new RuntimeException( "Error converting " + value + " to integer:", t );
817 }
818 }
819
820
821
822
823
824
825
826
827
828 public static int getNumericType( Object v1, Object v2 )
829 {
830 return getNumericType( v1, v2, false );
831 }
832
833
834
835
836
837
838
839
840
841
842 public static int getNumericType( int t1, int t2, boolean canBeNonNumeric )
843 {
844 if ( t1 == t2 )
845 {
846 return t1;
847 }
848
849 if ( canBeNonNumeric && ( t1 == NONNUMERIC || t2 == NONNUMERIC || t1 == CHAR || t2 == CHAR ) )
850 {
851 return NONNUMERIC;
852 }
853
854 if ( t1 == NONNUMERIC )
855 {
856 t1 = DOUBLE;
857 }
858 if ( t2 == NONNUMERIC )
859 {
860 t2 = DOUBLE;
861 }
862
863 if ( t1 >= MIN_REAL_TYPE )
864 {
865 if ( t2 >= MIN_REAL_TYPE )
866 {
867 return Math.max( t1, t2 );
868 }
869 if ( t2 < INT )
870 {
871 return t1;
872 }
873 if ( t2 == BIGINT )
874 {
875 return BIGDEC;
876 }
877 return Math.max( DOUBLE, t1 );
878 }
879 else if ( t2 >= MIN_REAL_TYPE )
880 {
881 if ( t1 < INT )
882 {
883 return t2;
884 }
885 if ( t1 == BIGINT )
886 {
887 return BIGDEC;
888 }
889 return Math.max( DOUBLE, t2 );
890 }
891 else
892 {
893 return Math.max( t1, t2 );
894 }
895 }
896
897
898
899
900
901
902
903
904
905
906 public static int getNumericType( Object v1, Object v2, boolean canBeNonNumeric )
907 {
908 return getNumericType( getNumericType( v1 ), getNumericType( v2 ), canBeNonNumeric );
909 }
910
911
912
913
914
915
916
917
918
919 public static Number newInteger( int type, long value )
920 {
921 switch ( type )
922 {
923 case BOOL:
924 case CHAR:
925 case INT:
926 return (int) value;
927
928 case FLOAT:
929 if ( (long) (float) value == value )
930 {
931 return (float) value;
932 }
933
934 case DOUBLE:
935 if ( (long) (double) value == value )
936 {
937 return (double) value;
938 }
939
940 case LONG:
941 return value;
942
943 case BYTE:
944 return (byte) value;
945
946 case SHORT:
947 return (short) value;
948
949 default:
950 return BigInteger.valueOf( value );
951 }
952 }
953
954
955
956
957
958
959
960
961
962
963 public static Number newReal( int type, double value )
964 {
965 if ( type == FLOAT )
966 {
967 return (float) value;
968 }
969 return value;
970 }
971
972 public static Object binaryOr( Object v1, Object v2 )
973 {
974 int type = getNumericType( v1, v2 );
975 if ( type == BIGINT || type == BIGDEC )
976 {
977 return bigIntValue( v1 ).or( bigIntValue( v2 ) );
978 }
979 return newInteger( type, longValue( v1 ) | longValue( v2 ) );
980 }
981
982 public static Object binaryXor( Object v1, Object v2 )
983 {
984 int type = getNumericType( v1, v2 );
985 if ( type == BIGINT || type == BIGDEC )
986 {
987 return bigIntValue( v1 ).xor( bigIntValue( v2 ) );
988 }
989 return newInteger( type, longValue( v1 ) ^ longValue( v2 ) );
990 }
991
992 public static Object binaryAnd( Object v1, Object v2 )
993 {
994 int type = getNumericType( v1, v2 );
995 if ( type == BIGINT || type == BIGDEC )
996 {
997 return bigIntValue( v1 ).and( bigIntValue( v2 ) );
998 }
999 return newInteger( type, longValue( v1 ) & longValue( v2 ) );
1000 }
1001
1002 public static boolean equal( Object v1, Object v2 )
1003 {
1004 if ( v1 == null )
1005 {
1006 return v2 == null;
1007 }
1008 if ( v1 == v2 || isEqual( v1, v2 ) )
1009 {
1010 return true;
1011 }
1012 if ( v1 instanceof Number && v2 instanceof Number )
1013 {
1014 return ( (Number) v1 ).doubleValue() == ( (Number) v2 ).doubleValue();
1015 }
1016 return false;
1017 }
1018
1019 public static boolean less( Object v1, Object v2 )
1020 {
1021 return compareWithConversion( v1, v2 ) < 0;
1022 }
1023
1024 public static boolean greater( Object v1, Object v2 )
1025 {
1026 return compareWithConversion( v1, v2 ) > 0;
1027 }
1028
1029 public static boolean in( Object v1, Object v2 )
1030 throws OgnlException
1031 {
1032 if ( v2 == null )
1033 {
1034 return false;
1035 }
1036
1037 ElementsAccessor elementsAccessor = OgnlRuntime.getElementsAccessor( OgnlRuntime.getTargetClass( v2 ) );
1038
1039
1040 for ( Enumeration<?> e = elementsAccessor.getElements( v2 ); e.hasMoreElements(); )
1041 {
1042 Object o = e.nextElement();
1043
1044 if ( equal( v1, o ) )
1045 {
1046 return true;
1047 }
1048 }
1049
1050 return false;
1051 }
1052
1053 public static Object shiftLeft( Object v1, Object v2 )
1054 {
1055 int type = getNumericType( v1 );
1056 if ( type == BIGINT || type == BIGDEC )
1057 {
1058 return bigIntValue( v1 ).shiftLeft( (int) longValue( v2 ) );
1059 }
1060 return newInteger( type, longValue( v1 ) << (int) longValue( v2 ) );
1061 }
1062
1063 public static Object shiftRight( Object v1, Object v2 )
1064 {
1065 int type = getNumericType( v1 );
1066 if ( type == BIGINT || type == BIGDEC )
1067 {
1068 return bigIntValue( v1 ).shiftRight( (int) longValue( v2 ) );
1069 }
1070 return newInteger( type, longValue( v1 ) >> (int) longValue( v2 ) );
1071 }
1072
1073 public static Object unsignedShiftRight( Object v1, Object v2 )
1074 {
1075 int type = getNumericType( v1 );
1076 if ( type == BIGINT || type == BIGDEC )
1077 {
1078 return bigIntValue( v1 ).shiftRight( (int) longValue( v2 ) );
1079 }
1080 if ( type <= INT )
1081 {
1082 return newInteger( INT, ( (int) longValue( v1 ) ) >>> (int) longValue( v2 ) );
1083 }
1084 return newInteger( type, longValue( v1 ) >>> (int) longValue( v2 ) );
1085 }
1086
1087 public static Object add( Object v1, Object v2 )
1088 {
1089 int type = getNumericType( v1, v2, true );
1090 switch ( type )
1091 {
1092 case BIGINT:
1093 return bigIntValue( v1 ).add( bigIntValue( v2 ) );
1094 case BIGDEC:
1095 return bigDecValue( v1 ).add( bigDecValue( v2 ) );
1096 case FLOAT:
1097 case DOUBLE:
1098 return newReal( type, doubleValue( v1 ) + doubleValue( v2 ) );
1099 case NONNUMERIC:
1100 int t1 = getNumericType( v1 ),
1101 t2 = getNumericType( v2 );
1102
1103 if ( ( ( t1 != NONNUMERIC ) && ( v2 == null ) ) || ( ( t2 != NONNUMERIC ) && ( v1 == null ) ) )
1104 {
1105 throw new NullPointerException( "Can't add values " + v1 + " , " + v2 );
1106 }
1107
1108 return stringValue( v1 ) + stringValue( v2 );
1109 default:
1110 return newInteger( type, longValue( v1 ) + longValue( v2 ) );
1111 }
1112 }
1113
1114 public static Object subtract( Object v1, Object v2 )
1115 {
1116 int type = getNumericType( v1, v2 );
1117 switch ( type )
1118 {
1119 case BIGINT:
1120 return bigIntValue( v1 ).subtract( bigIntValue( v2 ) );
1121 case BIGDEC:
1122 return bigDecValue( v1 ).subtract( bigDecValue( v2 ) );
1123 case FLOAT:
1124 case DOUBLE:
1125 return newReal( type, doubleValue( v1 ) - doubleValue( v2 ) );
1126 default:
1127 return newInteger( type, longValue( v1 ) - longValue( v2 ) );
1128 }
1129 }
1130
1131 public static Object multiply( Object v1, Object v2 )
1132 {
1133 int type = getNumericType( v1, v2 );
1134 switch ( type )
1135 {
1136 case BIGINT:
1137 return bigIntValue( v1 ).multiply( bigIntValue( v2 ) );
1138 case BIGDEC:
1139 return bigDecValue( v1 ).multiply( bigDecValue( v2 ) );
1140 case FLOAT:
1141 case DOUBLE:
1142 return newReal( type, doubleValue( v1 ) * doubleValue( v2 ) );
1143 default:
1144 return newInteger( type, longValue( v1 ) * longValue( v2 ) );
1145 }
1146 }
1147
1148 public static Object divide( Object v1, Object v2 )
1149 {
1150 int type = getNumericType( v1, v2 );
1151 switch ( type )
1152 {
1153 case BIGINT:
1154 return bigIntValue( v1 ).divide( bigIntValue( v2 ) );
1155 case BIGDEC:
1156 return bigDecValue( v1 ).divide( bigDecValue( v2 ), BigDecimal.ROUND_HALF_EVEN );
1157 case FLOAT:
1158 case DOUBLE:
1159 return newReal( type, doubleValue( v1 ) / doubleValue( v2 ) );
1160 default:
1161 return newInteger( type, longValue( v1 ) / longValue( v2 ) );
1162 }
1163 }
1164
1165 public static Object remainder( Object v1, Object v2 )
1166 {
1167 int type = getNumericType( v1, v2 );
1168 switch ( type )
1169 {
1170 case BIGDEC:
1171 case BIGINT:
1172 return bigIntValue( v1 ).remainder( bigIntValue( v2 ) );
1173 default:
1174 return newInteger( type, longValue( v1 ) % longValue( v2 ) );
1175 }
1176 }
1177
1178 public static Object negate( Object value )
1179 {
1180 int type = getNumericType( value );
1181 switch ( type )
1182 {
1183 case BIGINT:
1184 return bigIntValue( value ).negate();
1185 case BIGDEC:
1186 return bigDecValue( value ).negate();
1187 case FLOAT:
1188 case DOUBLE:
1189 return newReal( type, -doubleValue( value ) );
1190 default:
1191 return newInteger( type, -longValue( value ) );
1192 }
1193 }
1194
1195 public static Object bitNegate( Object value )
1196 {
1197 int type = getNumericType( value );
1198 switch ( type )
1199 {
1200 case BIGDEC:
1201 case BIGINT:
1202 return bigIntValue( value ).not();
1203 default:
1204 return newInteger( type, ~longValue( value ) );
1205 }
1206 }
1207
1208 public static String getEscapeString( String value )
1209 {
1210 StringBuilder result = new StringBuilder();
1211
1212 int length = value.length();
1213 for ( int i = 0; i < length; i++ )
1214 {
1215 result.append( getEscapedChar( value.charAt( i ) ) );
1216 }
1217 return result.toString();
1218 }
1219
1220 public static String getEscapedChar( char ch )
1221 {
1222 String result;
1223
1224 switch ( ch )
1225 {
1226 case '\b':
1227 result = "\b";
1228 break;
1229 case '\t':
1230 result = "\\t";
1231 break;
1232 case '\n':
1233 result = "\\n";
1234 break;
1235 case '\f':
1236 result = "\\f";
1237 break;
1238 case '\r':
1239 result = "\\r";
1240 break;
1241 case '\"':
1242 result = "\\\"";
1243 break;
1244 case '\'':
1245 result = "\\\'";
1246 break;
1247 case '\\':
1248 result = "\\\\";
1249 break;
1250 default:
1251 if ( Character.isISOControl( ch ) )
1252 {
1253
1254 String hc = Integer.toString( (int) ch, 16 );
1255 int hcl = hc.length();
1256
1257 result = "\\u";
1258 if ( hcl < 4 )
1259 {
1260 if ( hcl == 3 )
1261 {
1262 result = result + "0";
1263 }
1264 else
1265 {
1266 if ( hcl == 2 )
1267 {
1268 result = result + "00";
1269 }
1270 else
1271 {
1272 result = result + "000";
1273 }
1274 }
1275 }
1276
1277 result = result + hc;
1278 }
1279 else
1280 {
1281 result = ch + "";
1282 }
1283 break;
1284 }
1285 return result;
1286 }
1287
1288 public static Object returnValue( Object ignore, Object returnValue )
1289 {
1290 return returnValue;
1291 }
1292
1293
1294
1295
1296
1297
1298
1299
1300 public static RuntimeException castToRuntime( Throwable t )
1301 {
1302 if ( RuntimeException.class.isInstance( t ) )
1303 {
1304 return (RuntimeException) t;
1305 }
1306
1307 if ( OgnlException.class.isInstance( t ) )
1308 {
1309 throw new UnsupportedCompilationException( "Error evluating expression: " + t.getMessage(), t );
1310 }
1311
1312 return new RuntimeException( t );
1313 }
1314 }