|
Groovy example source code file (DefaultTypeTransformation.java)
The Groovy DefaultTypeTransformation.java source code/* * Copyright 2003-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.codehaus.groovy.runtime.typehandling; import groovy.lang.GString; import groovy.lang.GroovyRuntimeException; import org.codehaus.groovy.reflection.ReflectionCache; import org.codehaus.groovy.runtime.*; 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.*; /** * Class providing various type conversions, coercions and boxing/unboxing operations. * * @author Guillaume Laforge */ 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, byte.class); return n.byteValue(); } public static char charUnbox(Object value) { return castToChar(value); } public static short shortUnbox(Object value) { Number n = castToNumber(value, short.class); return n.shortValue(); } public static int intUnbox(Object value) { Number n = castToNumber(value, int.class); return n.intValue(); } public static boolean booleanUnbox(Object value) { return castToBoolean(value); } public static long longUnbox(Object value) { Number n = castToNumber(value, long.class); return n.longValue(); } public static float floatUnbox(Object value) { Number n = castToNumber(value, float.class); return n.floatValue(); } public static double doubleUnbox(Object value) { Number n = castToNumber(value, double.class); return n.doubleValue(); } // -------------------------------------------------------- // boxing methods // -------------------------------------------------------- public static Object box(boolean value) { return value ? Boolean.TRUE : Boolean.FALSE; } public static Object box(byte value) { return Byte.valueOf(value); } public static Object box(char value) { return Character.valueOf(value); } public static Object box(short value) { return Short.valueOf(value); } public static Object box(int value) { return Integer.valueOf(value); } public static Object box(long value) { return Long.valueOf(value); } public static Object box(float value) { return Float.valueOf(value); } public static Object box(double value) { return Double.valueOf(value); } public static Number castToNumber(Object object) { // default to Number class in exception details, else use the specified Number subtype. return castToNumber(object, Number.class); } public static Number castToNumber(Object object, Class type) { if (object instanceof Number) return (Number) object; if (object instanceof Character) { return Integer.valueOf(((Character) object).charValue()); } if (object instanceof GString) { String c = ((GString) object).toString(); if (c.length() == 1) { return Integer.valueOf(c.charAt(0)); } else { throw new GroovyCastException(c, type); } } if (object instanceof String) { String c = (String) object; if (c.length() == 1) { return Integer.valueOf(c.charAt(0)); } else { throw new GroovyCastException(c, type); } } throw new GroovyCastException(object, type); } /** * Method used for coercing an object to a boolean value, * thanks to an <code>asBoolean() method added on types. * * @param object to coerce to a boolean value * @return a boolean value */ public static boolean castToBoolean(Object object) { // null is always false if (object == null) { return false; } // if the object is not null, try to call an asBoolean() method on the object return (Boolean)InvokerHelper.invokeMethod(object, "asBoolean", InvokerHelper.EMPTY_ARGS); } 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.class) return object; final Class aClass = object.getClass(); if (type == aClass) 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 (ReflectionCache.isArray(type)) { return asArray(object, type); } if (ReflectionCache.isAssignableFrom(type, aClass)) { return object; } if (Collection.class.isAssignableFrom(type)) { int modifiers = type.getModifiers(); Collection answer; if (object instanceof Collection && type.isAssignableFrom(HashSet.class) && (type == HashSet.class || Modifier.isAbstract(modifiers) || Modifier.isInterface(modifiers))) { return new HashSet((Collection)object); } if (aClass.isArray()) { if (type.isAssignableFrom(ArrayList.class) && (Modifier.isAbstract(modifiers) || Modifier.isInterface(modifiers))) { answer = new ArrayList(); } else { // let's 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 (type == Class.class) { return castToClass(object); } else if (Number.class.isAssignableFrom(type)) { Number n = castToNumber(object, type); 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 Integer.valueOf(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) { if (n instanceof Float || n instanceof Double) { return new BigDecimal(n.doubleValue()); } 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 " + aClass.getName() + " value " + object + " to double failed. Value is out of range."); } return answer; } } else if (object instanceof String && type.isEnum()) { return Enum.valueOf(type, (String) object); } else if (object instanceof GString && type.isEnum()) { return Enum.valueOf(type, object.toString()); } Object[] args = null; if (object instanceof Collection) { // let's try invoke the constructor with the list as arguments // such as for creating a Dimension, Point, Color etc. Collection collection = (Collection) object; args = collection.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; } Exception nested = null; if (args != null) { try { return InvokerHelper.invokeConstructorOf(type, args); } catch (InvokerInvocationException iie){ throw iie; } catch (Exception e) { // let's ignore exception and return the original object // as the caller has more context to be able to throw a more // meaningful exception (but stash to get message later) nested = e; } } GroovyCastException gce; if (nested != null) { gce = new GroovyCastException(object, type, nested); } else { gce = new GroovyCastException(object, type); } throw gce; } private static Class castToClass(Object object) { try { return Class.forName(object.toString()); } catch (Exception e) { throw new GroovyCastException(object, Class.class, e); } } public static Object asArray(Object object, Class type) { if (type.isAssignableFrom(object.getClass())) { return object; } 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 <T> Collection Other Groovy examples (source code examples)Here is a short list of links related to this Groovy DefaultTypeTransformation.java source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.