1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.myfaces.shared_orchestra.util;
20
21 import java.beans.PropertyEditor;
22 import java.beans.PropertyEditorManager;
23 import java.math.BigDecimal;
24 import java.math.BigInteger;
25
26 import javax.servlet.jsp.el.ELException;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30
31 /**
32 *
33 * <p>This class contains the logic for coercing data types before
34 * operators are applied to them.
35 *
36 * <p>The following is the list of rules applied for various type
37 * conversions.
38 *
39 * <ul><pre>
40 * Applying arithmetic operator
41 * Binary operator - A {+,-,*} B
42 * if A and B are null
43 * return 0
44 * if A or B is BigDecimal, coerce both to BigDecimal and then:
45 * if operator is +, return <code>A.add(B)</code>
46 * if operator is -, return <code>A.subtract(B)</code>
47 * if operator is *, return <code>A.multiply(B)</code>
48 * if A or B is Float, Double, or String containing ".", "e", or "E"
49 * if A or B is BigInteger, coerce both A and B to BigDecimal and apply operator
50 * coerce both A and B to Double and apply operator
51 * if A or B is BigInteger, coerce both to BigInteger and then:
52 * if operator is +, return <code>A.add(B)</code>
53 * if operator is -, return <code>A.subtract(B)</code>
54 * if operator is *, return <code>A.multiply(B)</code>
55 * otherwise
56 * coerce both A and B to Long
57 * apply operator
58 * if operator results in exception (such as divide by 0), error
59 *
60 * Binary operator - A {/,div} B
61 * if A and B are null
62 * return 0
63 * if A or B is a BigDecimal or BigInteger, coerce both to BigDecimal and
64 * return <code>A.divide(B, BigDecimal.ROUND_HALF_UP)</code>
65 * otherwise
66 * coerce both A and B to Double
67 * apply operator
68 * if operator results in exception (such as divide by 0), error
69 *
70 * Binary operator - A {%,mod} B
71 * if A and B are null
72 * return 0
73 * if A or B is BigDecimal, Float, Double, or String containing ".", "e" or "E"
74 * coerce both to Double
75 * apply operator
76 * if A or B is BigInteger, coerce both to BigInteger and return
77 * <code>A.remainder(B)</code>
78 * otherwise
79 * coerce both A and B to Long
80 * apply operator
81 * if operator results in exception (such as divide by 0), error
82 *
83 * Unary minus operator - -A
84 * if A is null
85 * return 0
86 * if A is BigInteger or BigDecimal, return <code>A.negate()</code>
87 * if A is String
88 * if A contains ".", "e", or "E"
89 * coerce to Double, apply operator
90 * otherwise
91 * coerce to a Long and apply operator
92 * if A is Byte,Short,Integer,Long,Float,Double
93 * retain type, apply operator
94 * if operator results in exception, error
95 * otherwise
96 * error
97 *
98 * Applying "empty" operator - empty A
99 * if A is null
100 * return true
101 * if A is zero-length String
102 * return true
103 * if A is zero-length array
104 * return true
105 * if A is List and ((List) A).isEmpty()
106 * return true
107 * if A is Map and ((Map) A).isEmpty()
108 * return true
109 * if A is Collection an ((Collection) A).isEmpty()
110 * return true
111 * otherwise
112 * return false
113 *
114 * Applying logical operators
115 * Binary operator - A {and,or} B
116 * coerce both A and B to Boolean, apply operator
117 * NOTE - operator stops as soon as expression can be determined, i.e.,
118 * A and B and C and D - if B is false, then only A and B is evaluated
119 * Unary not operator - not A
120 * coerce A to Boolean, apply operator
121 *
122 * Applying relational operator
123 * A {<,>,<=,>=,lt,gt,lte,gte} B
124 * if A==B
125 * if operator is >= or <=
126 * return true
127 * otherwise
128 * return false
129 * if A or B is null
130 * return false
131 * if A or B is BigDecimal, coerce both A and B to BigDecimal and use the
132 * return value of <code>A.compareTo(B)</code>
133 * if A or B is Float or Double
134 * coerce both A and B to Double
135 * apply operator
136 * if A or B is BigInteger, coerce both A and B to BigInteger and use the
137 * return value of <code>A.compareTo(B)</code>
138 * if A or B is Byte,Short,Character,Integer,Long
139 * coerce both A and B to Long
140 * apply operator
141 * if A or B is String
142 * coerce both A and B to String, compare lexically
143 * if A is Comparable
144 * if A.compareTo (B) throws exception
145 * error
146 * otherwise
147 * use result of A.compareTo(B)
148 * if B is Comparable
149 * if B.compareTo (A) throws exception
150 * error
151 * otherwise
152 * use result of B.compareTo(A)
153 * otherwise
154 * error
155 *
156 * Applying equality operator
157 * A {==,!=} B
158 * if A==B
159 * apply operator
160 * if A or B is null
161 * return false for ==, true for !=
162 * if A or B is BigDecimal, coerce both A and B to BigDecimal and then:
163 * if operator is == or eq, return <code>A.equals(B)</code>
164 * if operator is != or ne, return <code>!A.equals(B)</code>
165 * if A or B is Float or Double
166 * coerce both A and B to Double
167 * apply operator
168 * if A or B is BigInteger, coerce both A and B to BigInteger and then:
169 * if operator is == or eq, return <code>A.equals(B)</code>
170 * if operator is != or ne, return <code>!A.equals(B)</code>
171 * if A or B is Byte,Short,Character,Integer,Long
172 * coerce both A and B to Long
173 * apply operator
174 * if A or B is Boolean
175 * coerce both A and B to Boolean
176 * apply operator
177 * if A or B is String
178 * coerce both A and B to String, compare lexically
179 * otherwise
180 * if an error occurs while calling A.equals(B)
181 * error
182 * apply operator to result of A.equals(B)
183 *
184 * coercions
185 *
186 * coerce A to String
187 * A is String
188 * return A
189 * A is null
190 * return ""
191 * A.toString throws exception
192 * error
193 * otherwise
194 * return A.toString
195 *
196 * coerce A to Number type N
197 * A is null or ""
198 * return 0
199 * A is Character
200 * convert to short, apply following rules
201 * A is Boolean
202 * error
203 * A is Number type N
204 * return A
205 * A is Number, coerce quietly to type N using the following algorithm
206 * If N is BigInteger
207 * If A is BigDecimal, return <code>A.toBigInteger()</code>
208 * Otherwise, return <code>BigInteger.valueOf(A.longValue())</code>
209 * if N is BigDecimal
210 * If A is a BigInteger, return <code>new BigDecimal(A)</code>
211 * Otherwise, return <code>new BigDecimal(A.doubleValue())</code>
212 * If N is Byte, return <code>new Byte(A.byteValue())</code>
213 * If N is Short, return <code>new Short(A.shortValue())</code>
214 * If N is Integer, return <code>new Integer(A.integerValue())</code>
215 * If N is Long, return <code>new Long(A.longValue())</code>
216 * If N is Float, return <code>new Float(A.floatValue())</code>
217 * If N is Double, return <code>new Double(A.doubleValue())</code>
218 * otherwise ERROR
219 * A is String
220 * If N is BigDecimal then:
221 * If <code>new BigDecimal(A)</code> throws an exception then ERROR
222 * Otherwise, return <code>new BigDecimal(A)</code>
223 * If N is BigInteger then:
224 * If <code>new BigInteger(A)</code> throws an exception, then ERROR
225 * Otherwise, return <code>new BigInteger(A)</code>
226 * new <code>N.valueOf(A)</code> throws exception
227 * error
228 * return <code>N.valueOf(A)</code>
229 * otherwise
230 * error
231 *
232 * coerce A to Character should be
233 * A is null or ""
234 * return (char) 0
235 * A is Character
236 * return A
237 * A is Boolean
238 * error
239 * A is Number with less precision than short
240 * coerce quietly - return (char) A
241 * A is Number with greater precision than short
242 * coerce quietly - return (char) A
243 * A is String
244 * return A.charAt (0)
245 * otherwise
246 * error
247 *
248 * coerce A to Boolean
249 * A is null or ""
250 * return false
251 * A is Boolean
252 * return A
253 * A is String
254 * Boolean.valueOf(A) throws exception
255 * error
256 * return Boolean.valueOf(A)
257 * otherwise
258 * error
259 *
260 * coerce A to any other type T
261 * A is null
262 * return null
263 * A is assignable to T
264 * coerce quietly
265 * A is String
266 * T has no PropertyEditor
267 * if A is "", return null
268 * otherwise error
269 * T's PropertyEditor throws exception
270 * if A is "", return null
271 * otherwise error
272 * otherwise
273 * apply T's PropertyEditor
274 * otherwise
275 * error
276 * </pre></ul>
277 *
278 * This is a copy from commons-el Coercions class.
279 *
280 * @author Nathan Abramson - Art Technology Group
281 * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author$
282 **/
283
284 class _Coercions
285 {
286 //-------------------------------------
287 // Constants
288 //-------------------------------------
289 private static final Number ZERO = new Integer(0);
290 private static Log log = LogFactory.getLog(_Coercions.class);
291
292 //-------------------------------------
293 /**
294 *
295 * Coerces the given value to the specified class.
296 **/
297 public static Object coerce (Object pValue,
298 Class pClass)
299 throws ELException
300 {
301 if (pClass == String.class) {
302 return coerceToString (pValue);
303 }
304 else if (isNumberClass (pClass)) {
305 return coerceToPrimitiveNumber (pValue, pClass);
306 }
307 else if (pClass == Character.class ||
308 pClass == Character.TYPE) {
309 return coerceToCharacter (pValue);
310 }
311 else if (pClass == Boolean.class ||
312 pClass == Boolean.TYPE) {
313 return coerceToBoolean (pValue);
314 }
315 else {
316 return coerceToObject (pValue, pClass);
317 }
318 }
319
320 //-------------------------------------
321 /**
322 *
323 * Returns true if the given class is Byte, Short, Integer, Long,
324 * Float, Double, BigInteger, or BigDecimal
325 **/
326 static boolean isNumberClass (Class pClass)
327 {
328 return
329 pClass == Byte.class ||
330 pClass == Byte.TYPE ||
331 pClass == Short.class ||
332 pClass == Short.TYPE ||
333 pClass == Integer.class ||
334 pClass == Integer.TYPE ||
335 pClass == Long.class ||
336 pClass == Long.TYPE ||
337 pClass == Float.class ||
338 pClass == Float.TYPE ||
339 pClass == Double.class ||
340 pClass == Double.TYPE ||
341 pClass == BigInteger.class ||
342 pClass == BigDecimal.class;
343 }
344
345 //-------------------------------------
346 /**
347 *
348 * Coerces the specified value to a String
349 **/
350 public static String coerceToString (Object pValue)
351 throws ELException
352 {
353 if (pValue == null) {
354 return "";
355 }
356 else if (pValue instanceof String) {
357 return (String) pValue;
358 }
359 else {
360 try {
361 return pValue.toString ();
362 }
363 catch (Exception exc) {
364 if (log.isErrorEnabled()) {
365 String message = _MessageUtil.getMessageWithArgs(
366 _Constants.TOSTRING_EXCEPTION,
367 pValue.getClass().getName());
368 log.error(message, exc);
369 throw new ELException(exc);
370 }
371 return "";
372 }
373 }
374 }
375
376 //-------------------------------------
377 /**
378 *
379 * Coerces a value to the given primitive number class
380 **/
381 public static Number coerceToPrimitiveNumber (Object pValue,
382 Class pClass)
383 throws ELException
384 {
385 if (pValue == null ||
386 "".equals (pValue)) {
387 return coerceToPrimitiveNumber (ZERO, pClass);
388 }
389 else if (pValue instanceof Character) {
390 char val = ((Character) pValue).charValue ();
391 return coerceToPrimitiveNumber (new Short((short) val), pClass);
392 }
393 else if (pValue instanceof Boolean) {
394 if (log.isErrorEnabled()) {
395 String message = _MessageUtil.getMessageWithArgs(
396 _Constants.BOOLEAN_TO_NUMBER, pValue, pClass.getName());
397 log.error(message);
398 throw new ELException(message);
399 }
400 return coerceToPrimitiveNumber(ZERO, pClass);
401 }
402 else if (pValue.getClass () == pClass) {
403 return (Number) pValue;
404 }
405 else if (pValue instanceof Number) {
406 return coerceToPrimitiveNumber ((Number) pValue, pClass);
407 }
408 else if (pValue instanceof String) {
409 try {
410 return coerceToPrimitiveNumber ((String) pValue, pClass);
411 }
412 catch (Exception exc) {
413 if (log.isErrorEnabled()) {
414 String message = _MessageUtil.getMessageWithArgs(
415 _Constants.STRING_TO_NUMBER_EXCEPTION,
416 (String) pValue, pClass.getName());
417 log.error(message);
418 throw new ELException(message);
419 }
420 return coerceToPrimitiveNumber (ZERO, pClass);
421 }
422 }
423 else {
424 if (log.isErrorEnabled()) {
425 String message = _MessageUtil.getMessageWithArgs(
426 _Constants.COERCE_TO_NUMBER,
427 pValue.getClass().getName(),
428 pClass.getName());
429 log.error(message);
430 throw new ELException(message);
431 }
432 return coerceToPrimitiveNumber (0, pClass);
433 }
434 }
435
436 //-------------------------------------
437 /**
438 *
439 * Coerces a value to an Integer, returning null if the coercion
440 * isn't possible.
441 **/
442 public static Integer coerceToInteger (Object pValue)
443 throws ELException
444 {
445 if (pValue == null) {
446 return null;
447 }
448 else if (pValue instanceof Character) {
449 return _PrimitiveObjects.getInteger
450 ((int) (((Character) pValue).charValue ()));
451 }
452 else if (pValue instanceof Boolean) {
453 if (log.isWarnEnabled()) {
454 log.warn(
455 _MessageUtil.getMessageWithArgs(
456 _Constants.BOOLEAN_TO_NUMBER, pValue, Integer.class.getName()));
457 }
458 return _PrimitiveObjects.getInteger
459 (((Boolean) pValue).booleanValue () ? 1 : 0);
460 }
461 else if (pValue instanceof Integer) {
462 return (Integer) pValue;
463 }
464 else if (pValue instanceof Number) {
465 return _PrimitiveObjects.getInteger (((Number) pValue).intValue ());
466 }
467 else if (pValue instanceof String) {
468 try {
469 return Integer.valueOf ((String) pValue);
470 }
471 catch (Exception exc) {
472 if (log.isWarnEnabled()) {
473 log.warn(
474 _MessageUtil.getMessageWithArgs(
475 _Constants.STRING_TO_NUMBER_EXCEPTION,
476 (String) pValue,
477 Integer.class.getName()));
478 }
479 return null;
480 }
481 }
482 else {
483 if (log.isWarnEnabled()) {
484 log.warn(
485 _MessageUtil.getMessageWithArgs(
486 _Constants.COERCE_TO_NUMBER,
487 pValue.getClass().getName(),
488 Integer.class.getName()));
489 }
490 return null;
491 }
492 }
493
494 //-------------------------------------
495 /**
496 *
497 * Coerces a long to the given primitive number class
498 **/
499 static Number coerceToPrimitiveNumber (long pValue,
500 Class pClass)
501 throws ELException
502 {
503 if (pClass == Byte.class || pClass == Byte.TYPE) {
504 return _PrimitiveObjects.getByte ((byte) pValue);
505 }
506 else if (pClass == Short.class || pClass == Short.TYPE) {
507 return _PrimitiveObjects.getShort ((short) pValue);
508 }
509 else if (pClass == Integer.class || pClass == Integer.TYPE) {
510 return _PrimitiveObjects.getInteger ((int) pValue);
511 }
512 else if (pClass == Long.class || pClass == Long.TYPE) {
513 return _PrimitiveObjects.getLong (pValue);
514 }
515 else if (pClass == Float.class || pClass == Float.TYPE) {
516 return _PrimitiveObjects.getFloat ((float) pValue);
517 }
518 else if (pClass == Double.class || pClass == Double.TYPE) {
519 return _PrimitiveObjects.getDouble ((double) pValue);
520 }
521 else {
522 return _PrimitiveObjects.getInteger (0);
523 }
524 }
525
526 //-------------------------------------
527 /**
528 *
529 * Coerces a double to the given primitive number class
530 **/
531 static Number coerceToPrimitiveNumber (double pValue,
532 Class pClass)
533 throws ELException
534 {
535 if (pClass == Byte.class || pClass == Byte.TYPE) {
536 return _PrimitiveObjects.getByte ((byte) pValue);
537 }
538 else if (pClass == Short.class || pClass == Short.TYPE) {
539 return _PrimitiveObjects.getShort ((short) pValue);
540 }
541 else if (pClass == Integer.class || pClass == Integer.TYPE) {
542 return _PrimitiveObjects.getInteger ((int) pValue);
543 }
544 else if (pClass == Long.class || pClass == Long.TYPE) {
545 return _PrimitiveObjects.getLong ((long) pValue);
546 }
547 else if (pClass == Float.class || pClass == Float.TYPE) {
548 return _PrimitiveObjects.getFloat ((float) pValue);
549 }
550 else if (pClass == Double.class || pClass == Double.TYPE) {
551 return _PrimitiveObjects.getDouble (pValue);
552 }
553 else {
554 return _PrimitiveObjects.getInteger (0);
555 }
556 }
557
558 //-------------------------------------
559 /**
560 *
561 * Coerces a Number to the given primitive number class
562 **/
563 static Number coerceToPrimitiveNumber (Number pValue, Class pClass)
564 throws ELException
565 {
566 if (pClass == Byte.class || pClass == Byte.TYPE) {
567 return _PrimitiveObjects.getByte (pValue.byteValue ());
568 }
569 else if (pClass == Short.class || pClass == Short.TYPE) {
570 return _PrimitiveObjects.getShort (pValue.shortValue ());
571 }
572 else if (pClass == Integer.class || pClass == Integer.TYPE) {
573 return _PrimitiveObjects.getInteger (pValue.intValue ());
574 }
575 else if (pClass == Long.class || pClass == Long.TYPE) {
576 return _PrimitiveObjects.getLong (pValue.longValue ());
577 }
578 else if (pClass == Float.class || pClass == Float.TYPE) {
579 return _PrimitiveObjects.getFloat (pValue.floatValue ());
580 }
581 else if (pClass == Double.class || pClass == Double.TYPE) {
582 return _PrimitiveObjects.getDouble (pValue.doubleValue ());
583 }
584 else if (pClass == BigInteger.class) {
585 if (pValue instanceof BigDecimal)
586 return ((BigDecimal) pValue).toBigInteger();
587 else
588 return BigInteger.valueOf(pValue.longValue());
589 }
590 else if (pClass == BigDecimal.class) {
591 if (pValue instanceof BigInteger)
592 return new BigDecimal((BigInteger) pValue);
593 else
594 return new BigDecimal(pValue.doubleValue());
595 }
596 else {
597 return _PrimitiveObjects.getInteger (0);
598 }
599 }
600
601 //-------------------------------------
602 /**
603 *
604 * Coerces a String to the given primitive number class
605 **/
606 static Number coerceToPrimitiveNumber (String pValue, Class pClass)
607 throws ELException
608 {
609 if (pClass == Byte.class || pClass == Byte.TYPE) {
610 return Byte.valueOf (pValue);
611 }
612 else if (pClass == Short.class || pClass == Short.TYPE) {
613 return Short.valueOf (pValue);
614 }
615 else if (pClass == Integer.class || pClass == Integer.TYPE) {
616 return Integer.valueOf (pValue);
617 }
618 else if (pClass == Long.class || pClass == Long.TYPE) {
619 return Long.valueOf (pValue);
620 }
621 else if (pClass == Float.class || pClass == Float.TYPE) {
622 return Float.valueOf (pValue);
623 }
624 else if (pClass == Double.class || pClass == Double.TYPE) {
625 return Double.valueOf (pValue);
626 }
627 else if (pClass == BigInteger.class) {
628 return new BigInteger(pValue);
629 }
630 else if (pClass == BigDecimal.class) {
631 return new BigDecimal(pValue);
632 }
633 else {
634 return _PrimitiveObjects.getInteger (0);
635 }
636 }
637
638 //-------------------------------------
639 /**
640 *
641 * Coerces a value to a Character
642 **/
643 public static Character coerceToCharacter (Object pValue)
644 throws ELException
645 {
646 if (pValue == null ||
647 "".equals (pValue)) {
648 return _PrimitiveObjects.getCharacter ((char) 0);
649 }
650 else if (pValue instanceof Character) {
651 return (Character) pValue;
652 }
653 else if (pValue instanceof Boolean) {
654 if (log.isErrorEnabled()) {
655 String message = _MessageUtil.getMessageWithArgs(
656 _Constants.BOOLEAN_TO_CHARACTER, pValue);
657 log.error(message);
658 throw new ELException(message);
659 }
660 return _PrimitiveObjects.getCharacter ((char) 0);
661 }
662 else if (pValue instanceof Number) {
663 return _PrimitiveObjects.getCharacter
664 ((char) ((Number) pValue).shortValue ());
665 }
666 else if (pValue instanceof String) {
667 String str = (String) pValue;
668 return _PrimitiveObjects.getCharacter (str.charAt (0));
669 }
670 else {
671 if (log.isErrorEnabled()) {
672 String message = _MessageUtil.getMessageWithArgs(
673 _Constants.COERCE_TO_CHARACTER,
674 pValue.getClass().getName());
675 log.error(message);
676 throw new ELException(message);
677 }
678 return _PrimitiveObjects.getCharacter ((char) 0);
679 }
680 }
681
682 //-------------------------------------
683 /**
684 *
685 * Coerces a value to a Boolean
686 **/
687 public static Boolean coerceToBoolean (Object pValue)
688 throws ELException
689 {
690 if (pValue == null ||
691 "".equals (pValue)) {
692 return Boolean.FALSE;
693 }
694 else if (pValue instanceof Boolean) {
695 return (Boolean) pValue;
696 }
697 else if (pValue instanceof String) {
698 String str = (String) pValue;
699 try {
700 return Boolean.valueOf (str);
701 }
702 catch (Exception exc) {
703 if (log.isErrorEnabled()) {
704 String message = _MessageUtil.getMessageWithArgs(
705 _Constants.STRING_TO_BOOLEAN, (String) pValue);
706 log.error(message, exc);
707 throw new ELException(message, exc);
708 }
709 return Boolean.FALSE;
710 }
711 }
712 else {
713 if (log.isErrorEnabled()) {
714 String message = _MessageUtil.getMessageWithArgs(
715 _Constants.COERCE_TO_BOOLEAN,
716 pValue.getClass().getName());
717 log.error(message);
718 throw new ELException(message);
719 }
720 return Boolean.TRUE;
721 }
722 }
723
724 //-------------------------------------
725 /**
726 *
727 * Coerces a value to the specified Class that is not covered by any
728 * of the above cases
729 **/
730 public static Object coerceToObject (Object pValue, Class pClass)
731 throws ELException
732 {
733 if (pValue == null) {
734 return null;
735 }
736 else if (pClass.isAssignableFrom (pValue.getClass ())) {
737 return pValue;
738 }
739 else if (pValue instanceof String) {
740 String str = (String) pValue;
741 PropertyEditor pe = PropertyEditorManager.findEditor (pClass);
742 if (pe == null) {
743 if ("".equals (str)) {
744 return null;
745 }
746 else {
747 if (log.isErrorEnabled()) {
748 String message = _MessageUtil.getMessageWithArgs(
749 _Constants.NO_PROPERTY_EDITOR,
750 str, pClass.getName());
751 log.error(message);
752 throw new ELException(message);
753 }
754 return null;
755 }
756 }
757 try {
758 pe.setAsText (str);
759 return pe.getValue ();
760 }
761 catch (IllegalArgumentException exc) {
762 if ("".equals (str)) {
763 return null;
764 }
765 else {
766 if (log.isErrorEnabled()) {
767 String message = _MessageUtil.getMessageWithArgs(
768 _Constants.PROPERTY_EDITOR_ERROR,
769 pValue,
770 pClass.getName());
771 log.error(message, exc);
772 throw new ELException(message, exc);
773 }
774 return null;
775 }
776 }
777 }
778 else {
779 if (log.isErrorEnabled()) {
780 String message = _MessageUtil.getMessageWithArgs(
781 _Constants.COERCE_TO_OBJECT,
782 pValue.getClass().getName(),
783 pClass.getName());
784 log.error(message);
785 throw new ELException(message);
786 }
787 return null;
788 }
789 }
790
791 //-------------------------------------
792 // Applying operators
793 //-------------------------------------
794 /**
795 *
796 * Performs all of the necessary type conversions, then calls on the
797 * appropriate operator.
798 **/
799 /*
800 public static Object applyArithmeticOperator
801 (Object pLeft,
802 Object pRight,
803 ArithmeticOperator pOperator)
804 throws ELException
805 {
806 if (pLeft == null &&
807 pRight == null) {
808 if (log.isWarnEnabled()) {
809 log.warn(
810 MessageUtil.getMessageWithArgs(
811 Constants.ARITH_OP_NULL,
812 pOperator.getOperatorSymbol()));
813 }
814 return PrimitiveObjects.getInteger (0);
815 }
816
817 else if (isBigDecimal(pLeft) || isBigDecimal(pRight)) {
818 BigDecimal left = (BigDecimal)
819 coerceToPrimitiveNumber(pLeft, BigDecimal.class);
820 BigDecimal right = (BigDecimal)
821 coerceToPrimitiveNumber(pRight, BigDecimal.class);
822 return pOperator.apply(left, right);
823 }
824
825 else if (isFloatingPointType(pLeft) ||
826 isFloatingPointType(pRight) ||
827 isFloatingPointString(pLeft) ||
828 isFloatingPointString(pRight)) {
829 if (isBigInteger(pLeft) || isBigInteger(pRight)) {
830 BigDecimal left = (BigDecimal)
831 coerceToPrimitiveNumber(pLeft, BigDecimal.class);
832 BigDecimal right = (BigDecimal)
833 coerceToPrimitiveNumber(pRight, BigDecimal.class);
834 return pOperator.apply(left, right);
835 } else {
836 double left =
837 coerceToPrimitiveNumber(pLeft, Double.class).
838 doubleValue();
839 double right =
840 coerceToPrimitiveNumber(pRight, Double.class).
841 doubleValue();
842 return
843 PrimitiveObjects.getDouble(pOperator.apply(left, right));
844 }
845 }
846
847 else if (isBigInteger(pLeft) || isBigInteger(pRight)) {
848 BigInteger left = (BigInteger)
849 coerceToPrimitiveNumber(pLeft, BigInteger.class);
850 BigInteger right = (BigInteger)
851 coerceToPrimitiveNumber(pRight, BigInteger.class);
852 return pOperator.apply(left, right);
853 }
854
855 else {
856 long left =
857 coerceToPrimitiveNumber (pLeft, Long.class).
858 longValue ();
859 long right =
860 coerceToPrimitiveNumber (pRight, Long.class).
861 longValue ();
862 return
863 PrimitiveObjects.getLong (pOperator.apply (left, right));
864 }
865 }*/
866
867 //-------------------------------------
868 /**
869 *
870 * Performs all of the necessary type conversions, then calls on the
871 * appropriate operator.
872 **/
873 /*
874 public static Object applyRelationalOperator
875 (Object pLeft,
876 Object pRight,
877 RelationalOperator pOperator)
878 throws ELException
879 {
880 if (isBigDecimal(pLeft) || isBigDecimal(pRight)) {
881 BigDecimal left = (BigDecimal)
882 coerceToPrimitiveNumber(pLeft, BigDecimal.class);
883 BigDecimal right = (BigDecimal)
884 coerceToPrimitiveNumber(pRight, BigDecimal.class);
885 return PrimitiveObjects.getBoolean(pOperator.apply(left, right));
886 }
887
888 else if (isFloatingPointType (pLeft) ||
889 isFloatingPointType (pRight)) {
890 double left =
891 coerceToPrimitiveNumber (pLeft, Double.class).
892 doubleValue ();
893 double right =
894 coerceToPrimitiveNumber (pRight, Double.class).
895 doubleValue ();
896 return
897 PrimitiveObjects.getBoolean (pOperator.apply (left, right));
898 }
899
900 else if (isBigInteger(pLeft) || isBigInteger(pRight)) {
901 BigInteger left = (BigInteger)
902 coerceToPrimitiveNumber(pLeft, BigInteger.class);
903 BigInteger right = (BigInteger)
904 coerceToPrimitiveNumber(pRight, BigInteger.class);
905 return PrimitiveObjects.getBoolean(pOperator.apply(left, right));
906 }
907
908 else if (isIntegerType (pLeft) ||
909 isIntegerType (pRight)) {
910 long left =
911 coerceToPrimitiveNumber (pLeft, Long.class).
912 longValue ();
913 long right =
914 coerceToPrimitiveNumber (pRight, Long.class).
915 longValue ();
916 return
917 PrimitiveObjects.getBoolean (pOperator.apply (left, right));
918 }
919
920 else if (pLeft instanceof String ||
921 pRight instanceof String) {
922 String left = coerceToString (pLeft);
923 String right = coerceToString (pRight);
924 return
925 PrimitiveObjects.getBoolean (pOperator.apply (left, right));
926 }
927
928 else if (pLeft instanceof Comparable) {
929 try {
930 int result = ((Comparable) pLeft).compareTo (pRight);
931 return
932 PrimitiveObjects.getBoolean
933 (pOperator.apply (result, -result));
934 }
935 catch (Exception exc) {
936 if (log.isErrorEnabled()) {
937 String message = MessageUtil.getMessageWithArgs(
938 Constants.COMPARABLE_ERROR,
939 pLeft.getClass().getName(),
940 (pRight == null) ? "null" : pRight.getClass().getName(),
941 pOperator.getOperatorSymbol());
942 log.error(message, exc);
943 throw new ELException(message, exc);
944 }
945 return Boolean.FALSE;
946 }
947 }
948
949 else if (pRight instanceof Comparable) {
950 try {
951 int result = ((Comparable) pRight).compareTo (pLeft);
952 return
953 PrimitiveObjects.getBoolean
954 (pOperator.apply (-result, result));
955 }
956 catch (Exception exc) {
957 if (log.isErrorEnabled()) {
958 String message = MessageUtil.getMessageWithArgs(
959 Constants.COMPARABLE_ERROR,
960 pRight.getClass().getName(),
961 (pLeft == null) ? "null" : pLeft.getClass().getName(),
962 pOperator.getOperatorSymbol());
963 log.error(message, exc);
964 throw new ELException(message, exc);
965 }
966 return Boolean.FALSE;
967 }
968 }
969
970 else {
971 if (log.isErrorEnabled()) {
972 String message = MessageUtil.getMessageWithArgs(
973 Constants.ARITH_OP_BAD_TYPE,
974 pOperator.getOperatorSymbol(),
975 pLeft.getClass().getName(),
976 pRight.getClass().getName());
977 log.error(message);
978 throw new ELException(message);
979 }
980 return Boolean.FALSE;
981 }
982 }*/
983
984 //-------------------------------------
985 /**
986 *
987 * Performs all of the necessary type conversions, then calls on the
988 * appropriate operator.
989 **/
990 /*
991 public static Object applyEqualityOperator
992 (Object pLeft,
993 Object pRight,
994 EqualityOperator pOperator)
995 throws ELException
996 {
997 if (pLeft == pRight) {
998 return PrimitiveObjects.getBoolean (pOperator.apply (true));
999 }
1000
1001 else if (pLeft == null ||
1002 pRight == null) {
1003 return PrimitiveObjects.getBoolean (pOperator.apply (false));
1004 }
1005
1006 else if (isBigDecimal(pLeft) || isBigDecimal(pRight)) {
1007 BigDecimal left = (BigDecimal)
1008 coerceToPrimitiveNumber(pLeft, BigDecimal.class);
1009 BigDecimal right = (BigDecimal)
1010 coerceToPrimitiveNumber(pRight, BigDecimal.class);
1011 return PrimitiveObjects.getBoolean(pOperator.apply(left.equals(right)));
1012 }
1013
1014 else if (isFloatingPointType (pLeft) ||
1015 isFloatingPointType (pRight)) {
1016 double left =
1017 coerceToPrimitiveNumber (pLeft, Double.class).
1018 doubleValue ();
1019 double right =
1020 coerceToPrimitiveNumber (pRight, Double.class).
1021 doubleValue ();
1022 return
1023 PrimitiveObjects.getBoolean
1024 (pOperator.apply (left == right));
1025 }
1026
1027 else if (isBigInteger(pLeft) || isBigInteger(pRight)) {
1028 BigInteger left = (BigInteger)
1029 coerceToPrimitiveNumber(pLeft, BigInteger.class);
1030 BigInteger right = (BigInteger)
1031 coerceToPrimitiveNumber(pRight, BigInteger.class);
1032 return PrimitiveObjects.getBoolean(pOperator.apply(left.equals(right)));
1033 }
1034
1035 else if (isIntegerType (pLeft) ||
1036 isIntegerType (pRight)) {
1037 long left =
1038 coerceToPrimitiveNumber (pLeft, Long.class).
1039 longValue ();
1040 long right =
1041 coerceToPrimitiveNumber (pRight, Long.class).
1042 longValue ();
1043 return
1044 PrimitiveObjects.getBoolean
1045 (pOperator.apply (left == right));
1046 }
1047
1048 else if (pLeft instanceof Boolean ||
1049 pRight instanceof Boolean) {
1050 boolean left = coerceToBoolean (pLeft).booleanValue ();
1051 boolean right = coerceToBoolean (pRight).booleanValue ();
1052 return
1053 PrimitiveObjects.getBoolean
1054 (pOperator.apply (left == right));
1055 }
1056
1057 else if (pLeft instanceof String ||
1058 pRight instanceof String) {
1059 String left = coerceToString (pLeft);
1060 String right = coerceToString (pRight);
1061 return
1062 PrimitiveObjects.getBoolean
1063 (pOperator.apply (left.equals (right)));
1064 }
1065
1066 else {
1067 try {
1068 return
1069 PrimitiveObjects.getBoolean
1070 (pOperator.apply (pLeft.equals (pRight)));
1071 }
1072 catch (Exception exc) {
1073 if (log.isErrorEnabled()) {
1074 String message = MessageUtil.getMessageWithArgs(
1075 Constants.ERROR_IN_EQUALS,
1076 pLeft.getClass().getName(),
1077 pRight.getClass().getName(),
1078 pOperator.getOperatorSymbol());
1079 log.error(message, exc);
1080 throw new ELException(message, exc);
1081 }
1082 return Boolean.FALSE;
1083 }
1084 }
1085 }*/
1086
1087 //-------------------------------------
1088 /**
1089 *
1090 * Returns true if the given Object is of a floating point type
1091 **/
1092 public static boolean isFloatingPointType (Object pObject)
1093 {
1094 return
1095 pObject != null &&
1096 isFloatingPointType (pObject.getClass ());
1097 }
1098
1099 //-------------------------------------
1100 /**
1101 *
1102 * Returns true if the given class is of a floating point type
1103 **/
1104 public static boolean isFloatingPointType (Class pClass)
1105 {
1106 return
1107 pClass == Float.class ||
1108 pClass == Float.TYPE ||
1109 pClass == Double.class ||
1110 pClass == Double.TYPE;
1111 }
1112
1113 //-------------------------------------
1114 /**
1115 *
1116 * Returns true if the given string might contain a floating point
1117 * number - i.e., it contains ".", "e", or "E"
1118 **/
1119 public static boolean isFloatingPointString (Object pObject)
1120 {
1121 if (pObject instanceof String) {
1122 String str = (String) pObject;
1123 int len = str.length ();
1124 for (int i = 0; i < len; i++) {
1125 char ch = str.charAt (i);
1126 if (ch == '.' ||
1127 ch == 'e' ||
1128 ch == 'E') {
1129 return true;
1130 }
1131 }
1132 return false;
1133 }
1134 else {
1135 return false;
1136 }
1137 }
1138
1139 //-------------------------------------
1140 /**
1141 *
1142 * Returns true if the given Object is of an integer type
1143 **/
1144 public static boolean isIntegerType (Object pObject)
1145 {
1146 return
1147 pObject != null &&
1148 isIntegerType (pObject.getClass ());
1149 }
1150
1151 //-------------------------------------
1152 /**
1153 *
1154 * Returns true if the given class is of an integer type
1155 **/
1156 public static boolean isIntegerType (Class pClass)
1157 {
1158 return
1159 pClass == Byte.class ||
1160 pClass == Byte.TYPE ||
1161 pClass == Short.class ||
1162 pClass == Short.TYPE ||
1163 pClass == Character.class ||
1164 pClass == Character.TYPE ||
1165 pClass == Integer.class ||
1166 pClass == Integer.TYPE ||
1167 pClass == Long.class ||
1168 pClass == Long.TYPE;
1169 }
1170
1171 //-------------------------------------
1172
1173 /**
1174 * Returns true if the given object is BigInteger.
1175 * @param pObject - Object to evaluate
1176 * @return - true if the given object is BigInteger
1177 */
1178 public static boolean isBigInteger(Object pObject) {
1179 return
1180 pObject != null && pObject instanceof BigInteger;
1181 }
1182
1183 /**
1184 * Returns true if the given object is BigDecimal.
1185 * @param pObject - Object to evaluate
1186 * @return - true if the given object is BigDecimal
1187 */
1188 public static boolean isBigDecimal(Object pObject) {
1189 return
1190 pObject != null && pObject instanceof BigDecimal;
1191 }
1192 }