View Javadoc

    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 }