📄 coercions.java
字号:
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.jbpm.jpdl.el.impl;
import java.beans.PropertyEditor;
import java.beans.PropertyEditorManager;
import java.math.BigInteger;
import java.math.BigDecimal;
import org.jbpm.jpdl.el.ELException;
/**
*
* <p>This class contains the logic for coercing data types before
* operators are applied to them.
*
* <p>The following is the list of rules applied for various type
* conversions.
*
* <ul><pre>
* Applying arithmetic operator
* Binary operator - A {+,-,*} B
* if A and B are null
* return 0
* if A or B is BigDecimal, coerce both to BigDecimal and then:
* if operator is +, return <code>A.add(B)</code>
* if operator is -, return <code>A.subtract(B)</code>
* if operator is *, return <code>A.multiply(B)</code>
* if A or B is Float, Double, or String containing ".", "e", or "E"
* if A or B is BigInteger, coerce both A and B to BigDecimal and apply operator
* coerce both A and B to Double and apply operator
* if A or B is BigInteger, coerce both to BigInteger and then:
* if operator is +, return <code>A.add(B)</code>
* if operator is -, return <code>A.subtract(B)</code>
* if operator is *, return <code>A.multiply(B)</code>
* otherwise
* coerce both A and B to Long
* apply operator
* if operator results in exception (such as divide by 0), error
*
* Binary operator - A {/,div} B
* if A and B are null
* return 0
* if A or B is a BigDecimal or BigInteger, coerce both to BigDecimal and
* return <code>A.divide(B, BigDecimal.ROUND_HALF_UP)</code>
* otherwise
* coerce both A and B to Double
* apply operator
* if operator results in exception (such as divide by 0), error
*
* Binary operator - A {%,mod} B
* if A and B are null
* return 0
* if A or B is BigDecimal, Float, Double, or String containing ".", "e" or "E"
* coerce both to Double
* apply operator
* if A or B is BigInteger, coerce both to BigInteger and return
* <code>A.remainder(B)</code>
* otherwise
* coerce both A and B to Long
* apply operator
* if operator results in exception (such as divide by 0), error
*
* Unary minus operator - -A
* if A is null
* return 0
* if A is BigInteger or BigDecimal, return <code>A.negate()</code>
* if A is String
* if A contains ".", "e", or "E"
* coerce to Double, apply operator
* otherwise
* coerce to a Long and apply operator
* if A is Byte,Short,Integer,Long,Float,Double
* retain type, apply operator
* if operator results in exception, error
* otherwise
* error
*
* Applying "empty" operator - empty A
* if A is null
* return true
* if A is zero-length String
* return true
* if A is zero-length array
* return true
* if A is List and ((List) A).isEmpty()
* return true
* if A is Map and ((Map) A).isEmpty()
* return true
* if A is Collection an ((Collection) A).isEmpty()
* return true
* otherwise
* return false
*
* Applying logical operators
* Binary operator - A {and,or} B
* coerce both A and B to Boolean, apply operator
* NOTE - operator stops as soon as expression can be determined, i.e.,
* A and B and C and D - if B is false, then only A and B is evaluated
* Unary not operator - not A
* coerce A to Boolean, apply operator
*
* Applying relational operator
* A {<,>,<=,>=,lt,gt,lte,gte} B
* if A==B
* if operator is >= or <=
* return true
* otherwise
* return false
* if A or B is null
* return false
* if A or B is BigDecimal, coerce both A and B to BigDecimal and use the
* return value of <code>A.compareTo(B)</code>
* if A or B is Float or Double
* coerce both A and B to Double
* apply operator
* if A or B is BigInteger, coerce both A and B to BigInteger and use the
* return value of <code>A.compareTo(B)</code>
* if A or B is Byte,Short,Character,Integer,Long
* coerce both A and B to Long
* apply operator
* if A or B is String
* coerce both A and B to String, compare lexically
* if A is Comparable
* if A.compareTo (B) throws exception
* error
* otherwise
* use result of A.compareTo(B)
* if B is Comparable
* if B.compareTo (A) throws exception
* error
* otherwise
* use result of B.compareTo(A)
* otherwise
* error
*
* Applying equality operator
* A {==,!=} B
* if A==B
* apply operator
* if A or B is null
* return false for ==, true for !=
* if A or B is BigDecimal, coerce both A and B to BigDecimal and then:
* if operator is == or eq, return <code>A.equals(B)</code>
* if operator is != or ne, return <code>!A.equals(B)</code>
* if A or B is Float or Double
* coerce both A and B to Double
* apply operator
* if A or B is BigInteger, coerce both A and B to BigInteger and then:
* if operator is == or eq, return <code>A.equals(B)</code>
* if operator is != or ne, return <code>!A.equals(B)</code>
* if A or B is Byte,Short,Character,Integer,Long
* coerce both A and B to Long
* apply operator
* if A or B is Boolean
* coerce both A and B to Boolean
* apply operator
* if A or B is String
* coerce both A and B to String, compare lexically
* otherwise
* if an error occurs while calling A.equals(B)
* error
* apply operator to result of A.equals(B)
*
* coercions
*
* coerce A to String
* A is String
* return A
* A is null
* return ""
* A.toString throws exception
* error
* otherwise
* return A.toString
*
* coerce A to Number type N
* A is null or ""
* return 0
* A is Character
* convert to short, apply following rules
* A is Boolean
* error
* A is Number type N
* return A
* A is Number, coerce quietly to type N using the following algorithm
* If N is BigInteger
* If A is BigDecimal, return <code>A.toBigInteger()</code>
* Otherwise, return <code>BigInteger.valueOf(A.longValue())</code>
* if N is BigDecimal
* If A is a BigInteger, return <code>new BigDecimal(A)</code>
* Otherwise, return <code>new BigDecimal(A.doubleValue())</code>
* If N is Byte, return <code>new Byte(A.byteValue())</code>
* If N is Short, return <code>new Short(A.shortValue())</code>
* If N is Integer, return <code>new Integer(A.integerValue())</code>
* If N is Long, return <code>new Long(A.longValue())</code>
* If N is Float, return <code>new Float(A.floatValue())</code>
* If N is Double, return <code>new Double(A.doubleValue())</code>
* otherwise ERROR
* A is String
* If N is BigDecimal then:
* If <code>new BigDecimal(A)</code> throws an exception then ERROR
* Otherwise, return <code>new BigDecimal(A)</code>
* If N is BigInteger then:
* If <code>new BigInteger(A)</code> throws an exception, then ERROR
* Otherwise, return <code>new BigInteger(A)</code>
* new <code>N.valueOf(A)</code> throws exception
* error
* return <code>N.valueOf(A)</code>
* otherwise
* error
*
* coerce A to Character should be
* A is null or ""
* return (char) 0
* A is Character
* return A
* A is Boolean
* error
* A is Number with less precision than short
* coerce quietly - return (char) A
* A is Number with greater precision than short
* coerce quietly - return (char) A
* A is String
* return A.charAt (0)
* otherwise
* error
*
* coerce A to Boolean
* A is null or ""
* return false
* A is Boolean
* return A
* A is String
* Boolean.valueOf(A) throws exception
* error
* return Boolean.valueOf(A)
* otherwise
* error
*
* coerce A to any other type T
* A is null
* return null
* A is assignable to T
* coerce quietly
* A is String
* T has no PropertyEditor
* if A is "", return null
* otherwise error
* T's PropertyEditor throws exception
* if A is "", return null
* otherwise error
* otherwise
* apply T's PropertyEditor
* otherwise
* error
* </pre></ul>
*
* @author Nathan Abramson - Art Technology Group
* @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: tombaeyens $
**/
public class Coercions
{
private static final Number ZERO = new Integer(0);
//-------------------------------------
/**
*
* Coerces the given value to the specified class.
**/
public static Object coerce (Object pValue,
Class pClass,
Logger pLogger)
throws ELException
{
if (pClass == String.class) {
return coerceToString (pValue, pLogger);
}
else if (isNumberClass (pClass)) {
return coerceToPrimitiveNumber (pValue, pClass, pLogger);
}
else if (pClass == Character.class ||
pClass == Character.TYPE) {
return coerceToCharacter (pValue, pLogger);
}
else if (pClass == Boolean.class ||
pClass == Boolean.TYPE) {
return coerceToBoolean (pValue, pLogger);
}
else {
return coerceToObject (pValue, pClass, pLogger);
}
}
//-------------------------------------
/**
*
* Returns true if the given class is Byte, Short, Integer, Long,
* Float, Double, BigInteger, or BigDecimal
**/
static boolean isNumberClass (Class pClass)
{
return
pClass == Byte.class ||
pClass == Byte.TYPE ||
pClass == Short.class ||
pClass == Short.TYPE ||
pClass == Integer.class ||
pClass == Integer.TYPE ||
pClass == Long.class ||
pClass == Long.TYPE ||
pClass == Float.class ||
pClass == Float.TYPE ||
pClass == Double.class ||
pClass == Double.TYPE ||
pClass == BigInteger.class ||
pClass == BigDecimal.class;
}
//-------------------------------------
/**
*
* Coerces the specified value to a String
**/
public static String coerceToString (Object pValue,
Logger pLogger)
throws ELException
{
if (pValue == null) {
return "";
}
else if (pValue instanceof String) {
return (String) pValue;
}
else {
try {
return pValue.toString ();
}
catch (Exception exc) {
if (pLogger.isLoggingError ()) {
pLogger.logError (Constants.TOSTRING_EXCEPTION,
exc,
pValue.getClass ().getName ());
}
return "";
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -