defaulttypetransformation.java

来自「Groovy动态语言 运行在JVM中的动态语言 可以方便的处理业务逻辑变化大的业」· Java 代码 · 共 823 行 · 第 1/2 页

JAVA
823
字号
/*
 * AutoBoxing.java created on 13.09.2006
 *
 * To change this generated comment go to 
 * Window>Preferences>Java>Code Generation>Code and Comments
 */
package org.codehaus.groovy.runtime.typehandling;

import groovy.lang.GString;
import groovy.lang.GroovyRuntimeException;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;

import org.codehaus.groovy.runtime.DefaultGroovyMethods;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.codehaus.groovy.runtime.InvokerInvocationException;
import org.codehaus.groovy.runtime.IteratorClosureAdapter;
import org.codehaus.groovy.runtime.MethodClosure;
import org.codehaus.groovy.runtime.RegexSupport;

public class DefaultTypeTransformation {
    
    protected static final Object[] EMPTY_ARGUMENTS = {};
    protected static final BigInteger ONE_NEG = new BigInteger("-1");
    
    //  --------------------------------------------------------
    //                  unboxing methods
    //  --------------------------------------------------------       
    
    public static byte byteUnbox(Object value) {
        Number n = castToNumber(value);
        return n.byteValue();
    }

    public static char charUnbox(Object value) {
        return castToChar(value);
    }

    public static short shortUnbox(Object value) {
        Number n = castToNumber(value);
        return n.shortValue();
    }

    public static int intUnbox(Object value) {
        Number n = castToNumber(value);
        return n.intValue();
    }

    public static boolean booleanUnbox(Object value) {
        return castToBoolean(value);
    }

    public static long longUnbox(Object value) {
        Number n = castToNumber(value);
        return n.longValue();
    }

    public static float floatUnbox(Object value) {
        Number n = castToNumber(value);
        return n.floatValue();
    }

    public static double doubleUnbox(Object value) {
        Number n = castToNumber(value);
        return n.doubleValue();
    } 

    //  --------------------------------------------------------
    //                  boxing methods
    //  --------------------------------------------------------       
    
    public static Object box(boolean value) {
        return value ? Boolean.TRUE : Boolean.FALSE;
    }

    public static Object box(byte value) {
        return new Byte(value);
    }

    public static Object box(char value) {
        return new Character(value);
    }

    public static Object box(short value) {
        return new Short(value);
    }

    public static Object box(int value) {
        return IntegerCache.integerValue(value);
    }

    public static Object box(long value) {
        return new Long(value);
    }

    public static Object box(float value) {
        return new Float(value);
    }

    public static Object box(double value) {
        return new Double(value);
    }
    
    public static Number castToNumber(Object object) {
        if (object instanceof Number) return (Number) object;
        if (object instanceof Character) {
            return new Integer(((Character) object).charValue());
        } else if (object instanceof String) {
            String c = (String) object;
            if (c.length() == 1) {
                return new Integer(c.charAt(0));
            }
            else {
                throw new GroovyCastException(c,Integer.class);
            }
        }
        throw new GroovyCastException(object,Number.class);
    }
    
    public static boolean castToBoolean(Object object) {
        if (object instanceof Boolean) {
            Boolean booleanValue = (Boolean) object;
            return booleanValue.booleanValue();
        }
        else if (object instanceof Matcher) {
            Matcher matcher = (Matcher) object;
            RegexSupport.setLastMatcher(matcher);
            return matcher.find();
        }
        else if (object instanceof Collection) {
            Collection collection = (Collection) object;
            return !collection.isEmpty();
        }
        else if (object instanceof Map) {
            Map map = (Map) object;
            return !map.isEmpty();
        }
        else if (object instanceof String || object instanceof GString) {
            String string =  object.toString();
            return string.length() > 0;
        } 
        else if (object instanceof Character) {
            Character c = (Character) object;
            return c.charValue() != 0;
        }
        else if (object instanceof Number) {
            Number n = (Number) object;
            return n.doubleValue() != 0;
        }
        else {
            return object != null;
        }
    }
    
    public static char castToChar(Object object) {
        if (object instanceof Character) {
            return ((Character) object).charValue();            
        } else if (object instanceof Number) {
            Number value = (Number) object;
            return (char) value.intValue();
        } else {
            String text = object.toString();
            if (text.length() == 1) {
                return text.charAt(0);
            }
            else {
                throw new GroovyCastException(text,char.class);
            }
        }
    }
    
    public static Object castToType(Object object, Class type) {
        if (object == null) {
            return null;
        }
        
        if (type == object.getClass()) return object;
        
        // TODO we should move these methods to groovy method, like g$asType() so that
        // we can use operator overloading to customize on a per-type basis
        if (type.isArray()) {
            return asArray(object, type);

        }
        if (type.isInstance(object)) {
            return object;
        }
        if (Collection.class.isAssignableFrom(type)) {
            if (object.getClass().isArray()) {
                Collection answer;
                int modifiers = type.getModifiers();
                if (type.isAssignableFrom(ArrayList.class) && (Modifier.isAbstract(modifiers) || Modifier.isInterface(modifiers))) {
                    answer = new ArrayList();
                } else {
                    // lets call the collections constructor
                    // passing in the list wrapper
                    try {
                        answer = (Collection) type.newInstance();
                    }
                    catch (Exception e) {
                        throw new GroovyCastException("Could not instantiate instance of: " + type.getName() + ". Reason: " + e);
                    }
                }

                // we cannot just wrap in a List as we support primitive type arrays
                int length = Array.getLength(object);
                for (int i = 0; i < length; i++) {
                    Object element = Array.get(object, i);
                    answer.add(element);
                }
                return answer;
            }
        }
        if (type == String.class) {
            return object.toString();
        } else if (type == Character.class) {
            return box(castToChar(object));
        } else if (type == Boolean.class) {
            return box(castToBoolean(object));
        } else if (Number.class.isAssignableFrom(type)) {
            Number n = castToNumber(object);
            if (type == Byte.class) {
                return new Byte(n.byteValue());
            } else if (type == Character.class) {
                return new Character((char) n.intValue());
            } else if (type == Short.class) {
                return new Short(n.shortValue());
            } else if (type == Integer.class) {
                return new Integer(n.intValue());
            } else if (type == Long.class) {
                return new Long(n.longValue());
            } else if (type == Float.class) {
                return new Float(n.floatValue());
            } else if (type == Double.class) {
                Double answer = new Double(n.doubleValue());
                //throw a runtime exception if conversion would be out-of-range for the type.
                if (!(n instanceof Double) && (answer.doubleValue() == Double.NEGATIVE_INFINITY
                        || answer.doubleValue() == Double.POSITIVE_INFINITY)) {
                    throw new GroovyRuntimeException("Automatic coercion of " + n.getClass().getName()
                            + " value " + n + " to double failed.  Value is out of range.");
                }
                return answer;
            } else if (type == BigDecimal.class) {
                return new BigDecimal(n.toString());
            } else if (type == BigInteger.class) {
                if (object instanceof Float || object instanceof Double) {
                    BigDecimal bd = new BigDecimal(n.doubleValue());
                    return bd.toBigInteger();
                } else if (object instanceof BigDecimal) {
                    return ((BigDecimal) object).toBigInteger();
                } else {
                    return new BigInteger(n.toString());
                }
            }
        } else if (type.isPrimitive()) {
            if (type == boolean.class) {
               return box(booleanUnbox(object)); 
            } else if (type == byte.class) {
                return box(byteUnbox(object));
            } else if (type == char.class) {
                return box(charUnbox(object));
            } else if (type == short.class) {
                return box(shortUnbox(object));
            } else if (type == int.class) {
                return box(intUnbox(object));
            } else if (type == long.class) {
                return box(longUnbox(object));
            } else if (type == float.class) {
                return box(floatUnbox(object));
            } else if (type == double.class) {
                Double answer = new Double(doubleUnbox(object));
                //throw a runtime exception if conversion would be out-of-range for the type.
                if (!(object instanceof Double) && (answer.doubleValue() == Double.NEGATIVE_INFINITY
                        || answer.doubleValue() == Double.POSITIVE_INFINITY)) {
                    throw new GroovyRuntimeException("Automatic coercion of " + object.getClass().getName()
                            + " value " + object + " to double failed.  Value is out of range.");
                }
                return answer;
            }
        }
        Object[] args = null;
        if (object instanceof Collection) {
            Collection list = (Collection) object;
            args = list.toArray();
        } else if (object instanceof Object[]) {
            args = (Object[]) object;
        } else if (object instanceof Map) {
            // emulate named params constructor
            args = new Object[1];
            args[0] = object;
        }
        if (args != null) {
            // lets try invoke the constructor with the list as arguments
            // such as for creating a Dimension, Point, Color etc.
            try {
                return InvokerHelper.invokeConstructorOf(type, args);
            } catch (InvokerInvocationException iie){
                throw iie;
            } catch (Exception e) {
                // lets ignore exception and return the original object
                // as the caller has more context to be able to throw a more
                // meaningful exception
            }
        }
        throw new GroovyCastException(object,type);
    }
    
    public static Object asArray(Object object, Class type) {
        Collection list = asCollection(object);
        int size = list.size();
        Class elementType = type.getComponentType();
        Object array = Array.newInstance(elementType, size);
        int idx = 0;

        if (boolean.class.equals(elementType)) {
            for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
                Object element = iter.next();
                Array.setBoolean(array, idx, booleanUnbox(element));
            }
        }
        else if (byte.class.equals(elementType)) {
            for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
                Object element = iter.next();
                Array.setByte(array, idx, byteUnbox(element));
            }
        }
        else if (char.class.equals(elementType)) {
            for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
                Object element = iter.next();
                Array.setChar(array, idx, charUnbox(element));
            }
        }
        else if (double.class.equals(elementType)) {
            for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
                Object element = iter.next();
                Array.setDouble(array, idx, doubleUnbox(element));
            }
        }
        else if (float.class.equals(elementType)) {
            for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
                Object element = iter.next();
                Array.setFloat(array, idx, floatUnbox(element));
            }
        }
        else if (int.class.equals(elementType)) {
            for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
                Object element = iter.next();
                Array.setInt(array, idx, intUnbox(element));
            }
        }
        else if (long.class.equals(elementType)) {
            for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
                Object element = iter.next();
                Array.setLong(array, idx, longUnbox(element));
            }
        }
        else if (short.class.equals(elementType)) {
            for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
                Object element = iter.next();
                Array.setShort(array, idx, shortUnbox(element));
            }
        }
        else {
            for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
                Object element = iter.next();
                Object coercedElement = castToType(element, elementType);
                Array.set(array, idx, coercedElement);
            }
        }
        return array;
    }
    
    public static Collection asCollection(Object value) {
        if (value == null) {
            return Collections.EMPTY_LIST;
        }
        else if (value instanceof Collection) {
            return (Collection) value;
        }
        else if (value instanceof Map) {
            Map map = (Map) value;
            return map.entrySet();
        }
        else if (value.getClass().isArray()) {
            if (value.getClass().getComponentType().isPrimitive()) {
                return primitiveArrayToList(value);
            }
            return Arrays.asList((Object[]) value);
        }
        else if (value instanceof MethodClosure) {
            MethodClosure method = (MethodClosure) value;
            IteratorClosureAdapter adapter = new IteratorClosureAdapter(method.getDelegate());
            method.call(adapter);
            return adapter.asList();
        }
        else if (value instanceof String) {
            return DefaultGroovyMethods.toList((String) value);
        }
        else if (value instanceof File) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?