/* *************************************************************************************** * Copyright (C) 2006 EsperTech, Inc. All rights reserved. * * http://www.espertech.com/esper * * http://www.espertech.com * * ---------------------------------------------------------------------------------- * * The software in this package is published under the terms of the GPL license * * a copy of which has been included with this distribution in the license.txt file. * *************************************************************************************** */ package com.espertech.esper.util; import com.espertech.esper.epl.expression.core.ExprValidationException; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.Collection; /** * Factory for type widening. */ public class TypeWidenerFactory { private static final TypeWidenerStringToCharCoercer STRING_TO_CHAR_COERCER = new TypeWidenerStringToCharCoercer(); public static final TypeWidenerObjectArrayToCollectionCoercer OBJECT_ARRAY_TO_COLLECTION_COERCER = new TypeWidenerObjectArrayToCollectionCoercer(); private static final TypeWidenerByteArrayToCollectionCoercer BYTE_ARRAY_TO_COLLECTION_COERCER = new TypeWidenerByteArrayToCollectionCoercer(); private static final TypeWidenerShortArrayToCollectionCoercer SHORT_ARRAY_TO_COLLECTION_COERCER = new TypeWidenerShortArrayToCollectionCoercer(); private static final TypeWidenerIntArrayToCollectionCoercer INT_ARRAY_TO_COLLECTION_COERCER = new TypeWidenerIntArrayToCollectionCoercer(); private static final TypeWidenerLongArrayToCollectionCoercer LONG_ARRAY_TO_COLLECTION_COERCER = new TypeWidenerLongArrayToCollectionCoercer(); private static final TypeWidenerFloatArrayToCollectionCoercer FLOAT_ARRAY_TO_COLLECTION_COERCER = new TypeWidenerFloatArrayToCollectionCoercer(); private static final TypeWidenerDoubleArrayToCollectionCoercer DOUBLE_ARRAY_TO_COLLECTION_COERCER = new TypeWidenerDoubleArrayToCollectionCoercer(); private static final TypeWidenerBooleanArrayToCollectionCoercer BOOLEAN_ARRAY_TO_COLLECTION_COERCER = new TypeWidenerBooleanArrayToCollectionCoercer(); private static final TypeWidenerCharArrayToCollectionCoercer CHAR_ARRAY_TO_COLLECTION_COERCER = new TypeWidenerCharArrayToCollectionCoercer(); public static final TypeWidenerByteArrayToByteBufferCoercer BYTE_ARRAY_TO_BYTE_BUFFER_COERCER = new TypeWidenerByteArrayToByteBufferCoercer(); /** * Returns the widener. * * @param columnName name of column * @param columnType type of column * @param writeablePropertyType property type * @param writeablePropertyName propery name * @param allowObjectArrayToCollectionConversion whether we widen object-array to collection * @param customizer customization if any * @param engineURI engine URI * @param statementName statement name * @return type widender * @throws ExprValidationException if type validation fails */ public static TypeWidener getCheckPropertyAssignType(String columnName, Class columnType, Class writeablePropertyType, String writeablePropertyName, boolean allowObjectArrayToCollectionConversion, TypeWidenerCustomizer customizer, String statementName, String engineURI) throws ExprValidationException { Class columnClassBoxed = JavaClassHelper.getBoxedType(columnType); Class targetClassBoxed = JavaClassHelper.getBoxedType(writeablePropertyType); if (customizer != null) { TypeWidener custom = customizer.widenerFor(columnName, columnType, writeablePropertyType, writeablePropertyName, statementName, engineURI); if (custom != null) { return custom; } } if (columnType == null) { if (writeablePropertyType.isPrimitive()) { String message = "Invalid assignment of column '" + columnName + "' of null type to event property '" + writeablePropertyName + "' typed as '" + writeablePropertyType.getName() + "', nullable type mismatch"; throw new ExprValidationException(message); } } else if (columnClassBoxed != targetClassBoxed) { if (columnClassBoxed == String.class && targetClassBoxed == Character.class) { return STRING_TO_CHAR_COERCER; } else if (allowObjectArrayToCollectionConversion && columnClassBoxed.isArray() && !columnClassBoxed.getComponentType().isPrimitive() && JavaClassHelper.isImplementsInterface(targetClassBoxed, Collection.class)) { return OBJECT_ARRAY_TO_COLLECTION_COERCER; } else if (!JavaClassHelper.isAssignmentCompatible(columnClassBoxed, targetClassBoxed)) { String writablePropName = writeablePropertyType.getName(); if (writeablePropertyType.isArray()) { writablePropName = writeablePropertyType.getComponentType().getName() + "[]"; } String columnTypeName = columnType.getName(); if (columnType.isArray()) { columnTypeName = columnType.getComponentType().getName() + "[]"; } String message = "Invalid assignment of column '" + columnName + "' of type '" + columnTypeName + "' to event property '" + writeablePropertyName + "' typed as '" + writablePropName + "', column and parameter types mismatch"; throw new ExprValidationException(message); } if (JavaClassHelper.isNumeric(writeablePropertyType)) { return new TypeWidenerBoxedNumeric(SimpleNumberCoercerFactory.getCoercer(columnClassBoxed, targetClassBoxed)); } } return null; } public static TypeWidener getArrayToCollectionCoercer(Class componentType) { if (!componentType.isPrimitive()) { return OBJECT_ARRAY_TO_COLLECTION_COERCER; } else if (componentType == byte.class) { return BYTE_ARRAY_TO_COLLECTION_COERCER; } else if (componentType == short.class) { return SHORT_ARRAY_TO_COLLECTION_COERCER; } else if (componentType == int.class) { return INT_ARRAY_TO_COLLECTION_COERCER; } else if (componentType == long.class) { return LONG_ARRAY_TO_COLLECTION_COERCER; } else if (componentType == float.class) { return FLOAT_ARRAY_TO_COLLECTION_COERCER; } else if (componentType == double.class) { return DOUBLE_ARRAY_TO_COLLECTION_COERCER; } else if (componentType == boolean.class) { return BOOLEAN_ARRAY_TO_COLLECTION_COERCER; } else if (componentType == char.class) { return CHAR_ARRAY_TO_COLLECTION_COERCER; } throw new IllegalStateException("Unrecognized class " + componentType); } private static class TypeWidenerByteArrayToCollectionCoercer implements TypeWidener { public Object widen(Object input) { return input == null ? null : Arrays.asList((byte[]) input); } } private static class TypeWidenerShortArrayToCollectionCoercer implements TypeWidener { public Object widen(Object input) { return input == null ? null : Arrays.asList((short[]) input); } } private static class TypeWidenerIntArrayToCollectionCoercer implements TypeWidener { public Object widen(Object input) { return input == null ? null : Arrays.asList((int[]) input); } } private static class TypeWidenerLongArrayToCollectionCoercer implements TypeWidener { public Object widen(Object input) { return input == null ? null : Arrays.asList((long[]) input); } } private static class TypeWidenerFloatArrayToCollectionCoercer implements TypeWidener { public Object widen(Object input) { return input == null ? null : Arrays.asList((float[]) input); } } private static class TypeWidenerDoubleArrayToCollectionCoercer implements TypeWidener { public Object widen(Object input) { return input == null ? null : Arrays.asList((double[]) input); } } private static class TypeWidenerBooleanArrayToCollectionCoercer implements TypeWidener { public Object widen(Object input) { return input == null ? null : Arrays.asList((boolean[]) input); } } private static class TypeWidenerCharArrayToCollectionCoercer implements TypeWidener { public Object widen(Object input) { return input == null ? null : Arrays.asList((char[]) input); } } private static class TypeWidenerByteArrayToByteBufferCoercer implements TypeWidener { public Object widen(Object input) { return input == null ? null : ByteBuffer.wrap((byte[]) input); } } }