package de.zalando.sprocwrapper.proxy; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.sql.Connection; import java.util.Collection; import java.util.List; import com.google.common.collect.Lists; import de.zalando.sprocwrapper.globalvaluetransformer.ValueTransformerUtils; import de.zalando.typemapper.core.ValueTransformer; import de.zalando.typemapper.core.fieldMapper.ObjectMapper; import de.zalando.typemapper.postgres.PgTypeHelper; public class GlobalValueTransformedParameter extends StoredProcedureParameter { private StoredProcedureParameter forwardingStoredProcedureParameter; @SuppressWarnings("rawtypes") private ValueTransformer valueTransformerForClass; @SuppressWarnings("rawtypes") private ObjectMapper globalObjectMapper; public GlobalValueTransformedParameter(final ValueTransformer<?, ?> valueTransformerForClass, final Class<?> clazz, final Type genericType, final Method m, final String typeName, final int sqlType, final int javaPosition, final boolean sensitive, final ObjectMapper<?> globalObjectMapper) throws InstantiationException, IllegalAccessException { super(getValueTransformedClazz(clazz, valueTransformerForClass), m, typeName, getValueTransformedTypeId(clazz), javaPosition, sensitive); this.valueTransformerForClass = valueTransformerForClass; this.globalObjectMapper = globalObjectMapper; forwardingStoredProcedureParameter = StoredProcedureParameter.createParameter(getValueTransformedClazz(clazz, valueTransformerForClass), getValueTransformedGenericClass(clazz), m, getValueTransformedTypeName(clazz, valueTransformerForClass), getValueTransformedTypeId(clazz), javaPosition, sensitive); } @Override public Object mapParam(final Object value, final Connection connection) { if (value == null) { return forwardingStoredProcedureParameter.mapParam(value, connection); } if (forwardingStoredProcedureParameter instanceof ArrayStoredProcedureParameter) { final List<Object> transformedValues = Lists.newArrayList(); if (value.getClass().isArray()) { for (final Object o : ((Object[]) value)) { transformedValues.add(getMarshaledObject(o)); } } else { for (final Object o : ((Collection<?>) value)) { transformedValues.add(String.valueOf(getMarshaledObject(o))); } } return forwardingStoredProcedureParameter.mapParam(transformedValues, connection); } else { return forwardingStoredProcedureParameter.mapParam(getMarshaledObject(value), connection); } } private Object getMarshaledObject(final Object o) { if (globalObjectMapper != null) { return globalObjectMapper.marshalToDb(o); } else { return valueTransformerForClass.marshalToDb(o); } } @Override public int getJavaPos() { return forwardingStoredProcedureParameter.getJavaPos(); } @Override public boolean isSensitive() { return forwardingStoredProcedureParameter.isSensitive(); } @Override public int getType() { return forwardingStoredProcedureParameter.getType(); } @Override public String getTypeName() { return forwardingStoredProcedureParameter.getTypeName(); } private static int getValueTransformedTypeId(final Class<?> clazz) { // start type detection for transformed class return -1; } private String getValueTransformedTypeName(final Class<?> clazz, final ValueTransformer<?, ?> valueTransformerForClass) { final Class<?> valueTransformedGenericClass = getValueTransformedGenericClass( valueTransformerForClass.getClass()); String sqlNameForClass = PgTypeHelper.getSQLNameForClass(valueTransformedGenericClass); if (sqlNameForClass != null && clazz.isArray() || Collection.class.isAssignableFrom(clazz)) { sqlNameForClass += "[]"; } return sqlNameForClass; } private static Class<?> getValueTransformedClazz(final Class<?> clazz, final ValueTransformer<?, ?> valueTransformerForClass) { if (clazz.isArray() || Collection.class.isAssignableFrom(clazz)) { return List.class; } return ValueTransformerUtils.getMarshalToDbClass(valueTransformerForClass); } private Class<?> getValueTransformedGenericClass(final Class<?> clazz) { return ValueTransformerUtils.getMarshalToDbClass(valueTransformerForClass); } }