Re-factor TypeMappingsFactory with proper support for Enums

This commit is contained in:
Travis Burtrum 2017-06-13 21:42:32 -04:00
parent 9c22b36267
commit 6fe563f25a
10 changed files with 233 additions and 374 deletions

View File

@ -272,10 +272,11 @@ public class CompileTimeRowToObjectMapper {
java.append("final ").append(tType).append("<String, Object> ret = new ").append(tType).append("<String, Object>();\n");
final int columnLength = _columnCount + 1;
int typeId = getTypeId(componentType);
final String enumName = componentType.toString();
if (componentType != null && typeId != TypeMappingsFactory.TYPE_UNKNOWN) { // we want a specific value type
for (int x = 1; x < columnLength; ++x) {
java.append("ret.put(").append(escapeMapKeyString(keys[x]).toLowerCase()).append(", ");
extractColumnValueString(java, x, typeId);
extractColumnValueString(java, x, typeId, enumName);
java.append(");\n");
}
} else // we want a generic object type
@ -291,9 +292,10 @@ public class CompileTimeRowToObjectMapper {
try {
java.append("final ").append(tType).append(" ret = new ").append(tType.substring(0, tType.length() - 1)).append(String.valueOf(_columnCount)).append("];\n");
final int typeId = getTypeId(componentType);
final String enumName = componentType.toString();
for (int x = 0; x < _columnCount; ) {
java.append("ret[").append(String.valueOf(x)).append("] = ");
extractColumnValueString(java, ++x, typeId);
extractColumnValueString(java, ++x, typeId, enumName);
java.append(";\n");
}
return;
@ -312,7 +314,7 @@ public class CompileTimeRowToObjectMapper {
final int typeId = getTypeId(_returnTypeClass);
if (typeId != TypeMappingsFactory.TYPE_UNKNOWN) {
java.append("final ").append(tType).append(" ret = ");
extractColumnValueString(java, 1, typeId);
extractColumnValueString(java, 1, typeId, _returnTypeClass.toString());
java.append(";\n");
return;
} else {
@ -325,7 +327,7 @@ public class CompileTimeRowToObjectMapper {
*/
// we could actually pull from first row like above and test it first and fail now, but maybe just failing during compilation is enough?
java.append("final ").append(tType).append(" ret = (").append(tType).append(") ");
extractColumnValueString(java, 1, typeId);
extractColumnValueString(java, 1, typeId, _returnTypeClass.toString());
java.append(";\n");
return;
}
@ -343,36 +345,22 @@ public class CompileTimeRowToObjectMapper {
final Element f = _fields[i];
final boolean isField = f.getKind() == ElementKind.FIELD;
//_args[0] = extractColumnValue(i, _fieldTypes[i]);
//System.out.printf("field: '%s' obj: '%s' fieldType: '%s'\n", _fields[i], _args[0], _fieldTypes[i]);
// custom hacked-in support for enums, can do better when we scrap org.apache.beehive.controls.system.jdbc.TypeMappingsFactory
if (_fieldTypes[i] == 0) {
/*
final Class<?> fieldType = isField ? ((Field) f).getType() : ((Method) f).getParameterTypes()[0];
if (Enum.class.isAssignableFrom(fieldType)) {
_args[0] = Enum.valueOf((Class<? extends Enum>) fieldType, (String) _args[0]);
if (f instanceof Field) {
// if f not accessible (but super.getFieldMappings() sets it), throw exception during compilation is fine
java.append("ret.").append(((Field) f).getName()).append(" = ").append(typeFromName(fieldType)).append(".valueOf(");
extractColumnValueString(java, i, _fieldTypes[i]);
java.append(");\n");
} else {
java.append("ret.").append(((Method) f).getName()).append("(").append(typeFromName(fieldType)).append(".valueOf(");
extractColumnValueString(java, i, _fieldTypes[i]);
java.append("));\n");
}
String enumName = null;
if (_fieldTypes[i] == TypeMappingsFactory.TYPE_ENUM) {
if (f.getKind() == ElementKind.FIELD) {
enumName = ((VariableElement) f).asType().toString();
} else {
enumName = ((ExecutableElement) f).getParameters().get(0).asType().toString();
}
*/
// no for now...
}
if (isField) {
// if f not accessible (but super.getFieldMappings() sets it), throw exception during compilation is fine
java.append("ret.").append(f.getSimpleName().toString()).append(" = ");
extractColumnValueString(java, i, _fieldTypes[i]);
extractColumnValueString(java, i, _fieldTypes[i], enumName);
java.append(";\n");
} else {
java.append("ret.").append(f.getSimpleName().toString()).append("(");
extractColumnValueString(java, i, _fieldTypes[i]);
extractColumnValueString(java, i, _fieldTypes[i], enumName);
java.append(");\n");
}
}
@ -385,15 +373,16 @@ public class CompileTimeRowToObjectMapper {
try {
return _tmf.getTypeId(typeMirrorToClass(classType));
} catch (ClassNotFoundException e) {
// todo: what about enums?
return TypeMappingsFactory.TYPE_UNKNOWN;
}
}
public void extractColumnValueString(final Appendable java, final int index, final int resultType) throws IOException, ClassNotFoundException {
CompilingRowToObjectMapper.extractColumnValueString(java, index, resultType, _resultSetName, _calendarName);
public void extractColumnValueString(final Appendable java, final int index, final int resultType, final String enumName) throws IOException, ClassNotFoundException {
CompilingRowToObjectMapper.extractColumnValueString(java, index, resultType, enumName, _resultSetName, _calendarName);
}
public void extractColumnValueString(final Appendable java, final int index, final TypeMirror resultType) throws IOException, ClassNotFoundException {
CompilingRowToObjectMapper.extractColumnValueString(java, index, typeMirrorToClass(resultType), _resultSetName, _calendarName);
CompilingRowToObjectMapper.extractColumnValueString(java, index, getTypeId(resultType), resultType.toString(), _resultSetName, _calendarName);
}
}

View File

@ -1,6 +1,8 @@
package com.moparisthebest.jdbc.codegen;
import com.moparisthebest.jdbc.dto.EnumPerson;
import com.moparisthebest.jdbc.dto.FieldPerson;
import com.moparisthebest.jdbc.dto.FirstName;
import com.moparisthebest.jdbc.util.ResultSetIterable;
import org.junit.AfterClass;
import org.junit.BeforeClass;
@ -91,4 +93,14 @@ public class JdbcMapperTest {
}
//IFJAVA8_END
@Test
public void testEnumPerson() throws SQLException {
assertEquals(new EnumPerson(FirstName.First), dao.getEnumPerson(fieldPerson1.getPersonNo()));
}
@Test
public void testEnum() throws SQLException {
assertEquals(FirstName.First, dao.getFirstNameEnum(fieldPerson1.getPersonNo()));
}
}

View File

@ -1,7 +1,9 @@
package com.moparisthebest.jdbc.codegen;
import com.moparisthebest.jdbc.Cleaner;
import com.moparisthebest.jdbc.dto.EnumPerson;
import com.moparisthebest.jdbc.dto.FieldPerson;
import com.moparisthebest.jdbc.dto.FirstName;
import com.moparisthebest.jdbc.dto.Person;
import com.moparisthebest.jdbc.util.ResultSetIterable;
@ -157,4 +159,10 @@ public interface PersonDAO extends Closeable {
Stream<FieldPerson> getPeopleStreamCachedPreparedStatement(long personNo1, long personNo2, long personNo3) throws SQLException;
//IFJAVA8_END
@JdbcMapper.SQL("SELECT first_name, last_name FROM person WHERE person_no = {personNo}")
EnumPerson getEnumPerson(long personNo) throws SQLException;
@JdbcMapper.SQL("SELECT first_name FROM person WHERE person_no = {personNo}")
FirstName getFirstNameEnum(long personNo) throws SQLException;
}

View File

@ -1,7 +1,9 @@
package com.moparisthebest.jdbc.codegen;
import com.moparisthebest.jdbc.Cleaner;
import com.moparisthebest.jdbc.dto.EnumPerson;
import com.moparisthebest.jdbc.dto.FieldPerson;
import com.moparisthebest.jdbc.dto.FirstName;
import com.moparisthebest.jdbc.dto.Person;
import com.moparisthebest.jdbc.util.ResultSetIterable;
@ -157,4 +159,10 @@ public interface PrestoPersonDAO extends PersonDAO {
Stream<FieldPerson> getPeopleStreamCachedPreparedStatement(long personNo1, long personNo2, long personNo3) throws SQLException;
//IFJAVA8_END
@JdbcMapper.SQL("SELECT first_name, last_name FROM person WHERE person_no = {personNo}")
EnumPerson getEnumPerson(long personNo) throws SQLException;
@JdbcMapper.SQL("SELECT first_name FROM person WHERE person_no = {personNo}")
FirstName getFirstNameEnum(long personNo) throws SQLException;
}

View File

@ -194,7 +194,7 @@ public class CompilingRowToObjectMapper<K, T> extends RowToObjectMapper<K, T> {
if(mapOnlySecondColumn){
java.append("final ").append(tType).append(" ret = ");
extractColumnValueString(java, 2, _tmf.getTypeId(_returnTypeClass));
extractColumnValueString(java, 2, _returnTypeClass);
java.append(";\n");
return;
}
@ -212,9 +212,10 @@ public class CompilingRowToObjectMapper<K, T> extends RowToObjectMapper<K, T> {
final int columnLength = _columnCount + 1;
if (componentType != null && componentType != Object.class) { // we want a specific value type
int typeId = _tmf.getTypeId(componentType);
final String enumName = componentType.getCanonicalName();
for (int x = 1; x < columnLength; ++x) {
java.append("ret.put(").append(escapeMapKeyString(keys[x]).toLowerCase()).append(", ");
extractColumnValueString(java, x, typeId);
extractColumnValueString(java, x, typeId, enumName);
java.append(");\n");
}
} else // we want a generic object type
@ -230,9 +231,10 @@ public class CompilingRowToObjectMapper<K, T> extends RowToObjectMapper<K, T> {
try {
java.append("final ").append(tType).append(" ret = new ").append(tType.substring(0, tType.length() - 1)).append(String.valueOf(_columnCount)).append("];\n");
final int typeId = _tmf.getTypeId(componentType);
final String enumName = componentType.getCanonicalName();
for (int x = 0; x < _columnCount; ) {
java.append("ret[").append(String.valueOf(x)).append("] = ");
extractColumnValueString(java, ++x, typeId);
extractColumnValueString(java, ++x, typeId, enumName);
java.append(";\n");
}
return;
@ -251,7 +253,7 @@ public class CompilingRowToObjectMapper<K, T> extends RowToObjectMapper<K, T> {
try {
if (typeId != TypeMappingsFactory.TYPE_UNKNOWN) {
java.append("final ").append(tType).append(" ret = ");
extractColumnValueString(java, 1, typeId);
extractColumnValueString(java, 1, typeId, _returnTypeClass.getCanonicalName());
java.append(";\n");
return;
} else {
@ -264,7 +266,7 @@ public class CompilingRowToObjectMapper<K, T> extends RowToObjectMapper<K, T> {
*/
// we could actually pull from first row like above and test it first and fail now, but maybe just failing during compilation is enough?
java.append("final ").append(tType).append(" ret = (").append(tType).append(") ");
extractColumnValueString(java, 1, typeId);
extractColumnValueString(java, 1, typeId, _returnTypeClass.getCanonicalName());
java.append(";\n");
return;
}
@ -286,33 +288,18 @@ public class CompilingRowToObjectMapper<K, T> extends RowToObjectMapper<K, T> {
for (int i = 1; i < _fields.length; i++) {
AccessibleObject f = _fields[i];
//_args[0] = extractColumnValue(i, _fieldTypes[i]);
//System.out.printf("field: '%s' obj: '%s' fieldType: '%s'\n", _fields[i], _args[0], _fieldTypes[i]);
// custom hacked-in support for enums, can do better when we scrap org.apache.beehive.controls.system.jdbc.TypeMappingsFactory
if (_fieldTypes[i] == 0) {
final Class<?> fieldType = f instanceof Field ? ((Field) f).getType() : ((Method) f).getParameterTypes()[0];
if (Enum.class.isAssignableFrom(fieldType)) {
_args[0] = Enum.valueOf((Class<? extends Enum>) fieldType, (String) _args[0]);
if (f instanceof Field) {
// if f not accessible (but super.getFieldMappings() sets it), throw exception during compilation is fine
java.append("ret.").append(((Field) f).getName()).append(" = ").append(typeFromName(fieldType)).append(".valueOf(");
extractColumnValueString(java, i, _fieldTypes[i]);
java.append(");\n");
} else {
java.append("ret.").append(((Method) f).getName()).append("(").append(typeFromName(fieldType)).append(".valueOf(");
extractColumnValueString(java, i, _fieldTypes[i]);
java.append("));\n");
}
}
String enumName = null;
if (_fieldTypes[i] == TypeMappingsFactory.TYPE_ENUM) {
enumName = (f instanceof Field ? ((Field) f).getType() : ((Method) f).getParameterTypes()[0]).getCanonicalName();
}
if (f instanceof Field) {
// if f not accessible (but super.getFieldMappings() sets it), throw exception during compilation is fine
java.append("ret.").append(((Field) f).getName()).append(" = ");
extractColumnValueString(java, i, _fieldTypes[i]);
extractColumnValueString(java, i, _fieldTypes[i], enumName);
java.append(";\n");
} else {
java.append("ret.").append(((Method) f).getName()).append("(");
extractColumnValueString(java, i, _fieldTypes[i]);
extractColumnValueString(java, i, _fieldTypes[i], enumName);
java.append(");\n");
}
}
@ -321,8 +308,8 @@ public class CompilingRowToObjectMapper<K, T> extends RowToObjectMapper<K, T> {
java.append("ret.finish(rs);\n");
}
public void extractColumnValueString(final Appendable java, final int index, final int resultType) throws IOException {
extractColumnValueString(java, index, resultType, _calendarName);
public void extractColumnValueString(final Appendable java, final int index, final int resultType, final String enumName) throws IOException {
extractColumnValueString(java, index, resultType, enumName, _calendarName);
}
public void extractColumnValueString(final Appendable java, final int index, final Class resultType) throws IOException {
@ -354,16 +341,11 @@ public class CompilingRowToObjectMapper<K, T> extends RowToObjectMapper<K, T> {
}
public static void extractColumnValueString(final Appendable java, final int index, final Class resultType, final String calendarName) throws IOException {
extractColumnValueString(java, index, _tmf.getTypeId(resultType), "rs", calendarName);
extractColumnValueString(java, index, _tmf.getTypeId(resultType), resultType.getCanonicalName(), "rs", calendarName);
}
public static void extractColumnValueString(final Appendable java, final int index, final Class resultType, final String resultSetName, final String calendarName) throws IOException {
extractColumnValueString(java, index, _tmf.getTypeId(resultType), resultSetName, calendarName);
}
public static void extractColumnValueString(final Appendable java, final int index, final int resultType, final String calendarName) throws IOException {
extractColumnValueString(java, index, resultType, "rs", calendarName);
public static void extractColumnValueString(final Appendable java, final int index, final int resultType, final String enumName, final String calendarName) throws IOException {
extractColumnValueString(java, index, resultType, enumName, "rs", calendarName);
}
/**
@ -374,7 +356,7 @@ public class CompilingRowToObjectMapper<K, T> extends RowToObjectMapper<K, T> {
* @return The extracted value
* @throws java.sql.SQLException on error.
*/
public static void extractColumnValueString(final Appendable java, final int index, final int resultType, final String resultSetName, final String calendarName) throws IOException {
public static void extractColumnValueString(final Appendable java, final int index, final int resultType, final String enumName, final String resultSetName, final String calendarName) throws IOException {
switch (resultType) {
case TypeMappingsFactory.TYPE_INT:
java.append(resultSetName).append(".getInt(").append(String.valueOf(index)).append(")");
@ -422,6 +404,9 @@ public class CompilingRowToObjectMapper<K, T> extends RowToObjectMapper<K, T> {
case TypeMappingsFactory.TYPE_XMLBEAN_ENUM:
java.append(resultSetName).append(".getString(").append(String.valueOf(index)).append(")");
return;
case TypeMappingsFactory.TYPE_ENUM:
java.append(enumName).append(".valueOf(").append(resultSetName).append(".getString(").append(String.valueOf(index)).append("))");
return;
case TypeMappingsFactory.TYPE_BIG_DECIMAL:
java.append(resultSetName).append(".getBigDecimal(").append(String.valueOf(index)).append(")");
return;

View File

@ -198,7 +198,7 @@ public class RowToObjectMapper<K, T> extends AbstractRowMapper<K, T> {
if(componentType != null && componentType != Object.class){ // we want a specific value type
int typeId = _tmf.getTypeId(componentType);
for(int x = 1; x < columnLength; ++x)
ret.put(keys[x].toLowerCase(), extractColumnValue(x, typeId));
ret.put(keys[x].toLowerCase(), extractColumnValue(x, typeId, componentType));
} else // we want a generic object type
for(int x = 1; x < columnLength; ++x)
ret.put(keys[x].toLowerCase(), _resultSet.getObject(x));
@ -213,7 +213,7 @@ public class RowToObjectMapper<K, T> extends AbstractRowMapper<K, T> {
final Object ret = Array.newInstance(componentType, _columnCount);
final int typeId = _tmf.getTypeId(componentType);
for(int x = 0; x < _columnCount;)
Array.set(ret, x, extractColumnValue(++x, typeId));
Array.set(ret, x, extractColumnValue(++x, typeId, componentType));
//ret[x] = extractColumnValue(++x, typeId);
return _returnTypeClass.cast(ret);
} catch (Throwable e) {
@ -233,10 +233,10 @@ public class RowToObjectMapper<K, T> extends AbstractRowMapper<K, T> {
try {
if (typeId != TypeMappingsFactory.TYPE_UNKNOWN) {
return (T)extractColumnValue(1, typeId);
return (T)extractColumnValue(1, typeId, _returnTypeClass);
} else {
// we still might want a single value (i.e. java.util.Date)
Object val = extractColumnValue(1, typeId);
Object val = extractColumnValue(1, typeId, _returnTypeClass);
if (_returnTypeClass.isAssignableFrom(val.getClass())) {
return _returnTypeClass.cast(val);
}
@ -267,14 +267,8 @@ public class RowToObjectMapper<K, T> extends AbstractRowMapper<K, T> {
AccessibleObject f = _fields[i];
try {
_args[0] = extractColumnValue(i, _fieldTypes[i]);
_args[0] = extractColumnValue(i, _fieldTypes[i], null); // be lazy about this
//System.out.printf("field: '%s' obj: '%s' fieldType: '%s'\n", _fields[i], _args[0], _fieldTypes[i]);
// custom hacked-in support for enums, can do better when we scrap org.apache.beehive.controls.system.jdbc.TypeMappingsFactory
if(_fieldTypes[i] == 0 && _args[0] instanceof String){
Class<?> fieldType = f instanceof Field ? ((Field)f).getType() : ((Method)f).getParameterTypes()[0];
if(Enum.class.isAssignableFrom(fieldType))
_args[0] = Enum.valueOf((Class<? extends Enum>)fieldType, (String)_args[0]);
}
if (f instanceof Field) {
((Field) f).set(resultObject, _args[0]);
} else {
@ -333,7 +327,7 @@ public class RowToObjectMapper<K, T> extends AbstractRowMapper<K, T> {
*/
@SuppressWarnings({"unchecked"})
public <E> E extractColumnValue(int index, Class<E> classType) throws SQLException {
return classType.cast(extractColumnValue(index, _tmf.getTypeId(classType)));
return classType.cast(extractColumnValue(index, _tmf.getTypeId(classType), classType));
}
/**
@ -499,7 +493,7 @@ public class RowToObjectMapper<K, T> extends AbstractRowMapper<K, T> {
* @return The extracted value
* @throws java.sql.SQLException on error.
*/
protected Object extractColumnValue(int index, int resultType) throws SQLException {
protected Object extractColumnValue(final int index, final int resultType, Class<?> resultTypeClass) throws SQLException {
try{
switch (resultType) {
case TypeMappingsFactory.TYPE_INT:
@ -572,6 +566,15 @@ public class RowToObjectMapper<K, T> extends AbstractRowMapper<K, T> {
case TypeMappingsFactory.TYPE_STRING:
case TypeMappingsFactory.TYPE_XMLBEAN_ENUM:
return _resultSet.getString(index);
case TypeMappingsFactory.TYPE_ENUM:
if(resultTypeClass == null) {
// load lazily, todo: could cache? meh
final AccessibleObject f = _fields[index];
resultTypeClass = f instanceof Field ? ((Field)f).getType() : ((Method)f).getParameterTypes()[0];
}
@SuppressWarnings("unchecked")
final Enum ret = Enum.valueOf((Class<? extends Enum>)resultTypeClass, _resultSet.getString(index));
return ret;
case TypeMappingsFactory.TYPE_BIG_DECIMAL:
return _resultSet.getBigDecimal(index);
case TypeMappingsFactory.TYPE_BYTES:

View File

@ -18,11 +18,8 @@
*/
package com.moparisthebest.jdbc;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Types;
import java.util.HashMap;
import java.util.Map;
@ -31,9 +28,7 @@ import java.util.Map;
*/
public final class TypeMappingsFactory {
/* @todo: refactor! */
private static TypeMappingsFactory _instance;
private final static TypeMappingsFactory _instance = new TypeMappingsFactory();
private static Class<?> XMLBEANS_STRING_ENUM_ABSTRACT_BASE = null;
static {
@ -49,259 +44,103 @@ public final class TypeMappingsFactory {
* @return TypeMappingsFactory instance.
*/
public static TypeMappingsFactory getInstance() {
if (_instance == null) {
_instance = new TypeMappingsFactory();
}
return _instance;
}
public static final int TYPE_UNKNOWN = 0;
static final int TYPE_BYTE = 1;
static final int TYPE_SHORT = 2;
static final int TYPE_INT = 3;
static final int TYPE_LONG = 4;
static final int TYPE_FLOAT = 5;
static final int TYPE_DOUBLE = 6;
static final int TYPE_BOOLEAN = 7;
static final int TYPE_BYTE_OBJ = 8;
static final int TYPE_SHORT_OBJ = 9;
static final int TYPE_INT_OBJ = 10;
static final int TYPE_LONG_OBJ = 11;
static final int TYPE_FLOAT_OBJ = 12;
static final int TYPE_DOUBLE_OBJ = 13;
static final int TYPE_BOOLEAN_OBJ = 14;
static final int TYPE_BIG_DECIMAL = 15;
static final int TYPE_STRING = 16;
static final int TYPE_BYTES = 17;
static final int TYPE_SQLDATE = 18;
static final int TYPE_TIME = 19;
static final int TYPE_TIMESTAMP = 20;
static final int TYPE_STREAM = 21;
static final int TYPE_READER = 22;
static final int TYPE_CLOB = 23;
static final int TYPE_BLOB = 24;
static final int TYPE_ARRAY = 25;
static final int TYPE_REF = 26;
static final int TYPE_DATE = 27;
static final int TYPE_CALENDAR = 28;
static final int TYPE_STRUCT = 29;
static final int TYPE_XMLBEAN_ENUM = 30;
static final int TYPE_MAX = 31;
public static final int TYPE_BYTE = 1;
public static final int TYPE_SHORT = 2;
public static final int TYPE_INT = 3;
public static final int TYPE_LONG = 4;
public static final int TYPE_FLOAT = 5;
public static final int TYPE_DOUBLE = 6;
public static final int TYPE_BOOLEAN = 7;
public static final int TYPE_BYTE_OBJ = 8;
public static final int TYPE_SHORT_OBJ = 9;
public static final int TYPE_INT_OBJ = 10;
public static final int TYPE_LONG_OBJ = 11;
public static final int TYPE_FLOAT_OBJ = 12;
public static final int TYPE_DOUBLE_OBJ = 13;
public static final int TYPE_BOOLEAN_OBJ = 14;
public static final int TYPE_BIG_DECIMAL = 15;
public static final int TYPE_STRING = 16;
public static final int TYPE_BYTES = 17;
public static final int TYPE_SQLDATE = 18;
public static final int TYPE_TIME = 19;
public static final int TYPE_TIMESTAMP = 20;
public static final int TYPE_STREAM = 21;
public static final int TYPE_READER = 22;
public static final int TYPE_CLOB = 23;
public static final int TYPE_BLOB = 24;
public static final int TYPE_ARRAY = 25;
public static final int TYPE_REF = 26;
public static final int TYPE_DATE = 27;
public static final int TYPE_CALENDAR = 28;
public static final int TYPE_STRUCT = 29;
public static final int TYPE_XMLBEAN_ENUM = 30;
public static final int TYPE_ENUM = 31;
private static final int TYPE_MAX = TYPE_ENUM + 1; // should always reference the max
private Map<Class, Object> _primitiveDefaults;
private final Map<Class, Object> _primitiveDefaults;
//
// keys in this map are the class of the method's return type,
// values are the set of constants defined above all prefixed with
// TYPE_
//
private Map<Class, Integer> _typeMap;
private Map<Class, Integer> _typeSqlMap;
/**
* Map a string version of sql type to sql type (java.sql.Types).
* example: "INTEGER" maps to java.sql.Types.INTEGER
*/
private Map<String, Integer> _typeSqlNameMap;
private static Method _methodMapGet;
private final Map<Class, Integer> _typeMap;
/**
* Constructor
*/
TypeMappingsFactory() {
protected TypeMappingsFactory() {
_primitiveDefaults = new HashMap<Class, Object>();
_primitiveDefaults.put(Boolean.TYPE, Boolean.FALSE);
_primitiveDefaults.put(Integer.TYPE, new Integer(0));
_primitiveDefaults.put(Long.TYPE, new Long(0));
_primitiveDefaults.put(Byte.TYPE, new Byte((byte) 0));
_primitiveDefaults.put(Short.TYPE, new Short((short) 0));
_primitiveDefaults.put(Character.TYPE, new Character('\u0000'));
_primitiveDefaults.put(Float.TYPE, new Float(0.0f));
_primitiveDefaults.put(Double.TYPE, new Double(0.0d));
_primitiveDefaults.put(Integer.TYPE, 0);
_primitiveDefaults.put(Long.TYPE, 0);
_primitiveDefaults.put(Byte.TYPE, (byte) 0);
_primitiveDefaults.put(Short.TYPE, (short) 0);
_primitiveDefaults.put(Character.TYPE, '\u0000');
_primitiveDefaults.put(Float.TYPE, 0.0f);
_primitiveDefaults.put(Double.TYPE, 0.0d);
// Class to internal enum
_typeMap = new HashMap<Class, Integer>(TYPE_MAX * 2);
_typeMap.put(Boolean.TYPE, new Integer(TYPE_BOOLEAN));
_typeMap.put(Integer.TYPE, new Integer(TYPE_INT));
_typeMap.put(Long.TYPE, new Integer(TYPE_LONG));
_typeMap.put(Byte.TYPE, new Integer(TYPE_BYTE));
_typeMap.put(Short.TYPE, new Integer(TYPE_SHORT));
_typeMap.put(Float.TYPE, new Integer(TYPE_FLOAT));
_typeMap.put(Double.TYPE, new Integer(TYPE_DOUBLE));
_typeMap.put(Boolean.class, new Integer(TYPE_BOOLEAN_OBJ));
_typeMap.put(Integer.class, new Integer(TYPE_INT_OBJ));
_typeMap.put(Long.class, new Integer(TYPE_LONG_OBJ));
_typeMap.put(Byte.class, new Integer(TYPE_BYTE_OBJ));
_typeMap.put(Short.class, new Integer(TYPE_SHORT_OBJ));
_typeMap.put(Float.class, new Integer(TYPE_FLOAT_OBJ));
_typeMap.put(Double.class, new Integer(TYPE_DOUBLE_OBJ));
_typeMap.put(String.class, new Integer(TYPE_STRING));
_typeMap.put(java.math.BigDecimal.class, new Integer(TYPE_BIG_DECIMAL));
_typeMap.put(byte[].class, new Integer(TYPE_BYTES));
_typeMap.put(java.sql.Timestamp.class, new Integer(TYPE_TIMESTAMP));
_typeMap.put(java.sql.Time.class, new Integer(TYPE_TIME));
_typeMap.put(java.sql.Date.class, new Integer(TYPE_SQLDATE));
_typeMap.put(java.sql.Ref.class, new Integer(TYPE_REF));
_typeMap.put(Blob.class, new Integer(TYPE_BLOB));
_typeMap.put(Clob.class, new Integer(TYPE_CLOB));
_typeMap.put(java.sql.Array.class, new Integer(TYPE_ARRAY));
_typeMap.put(java.sql.Struct.class, new Integer(TYPE_STRUCT));
_typeMap.put(java.io.Reader.class, new Integer(TYPE_READER));
_typeMap.put(java.io.InputStream.class, new Integer(TYPE_STREAM));
_typeMap.put(java.util.Date.class, new Integer(TYPE_DATE));
_typeMap.put(java.util.Calendar.class, new Integer(TYPE_CALENDAR));
_typeMap.put(java.util.GregorianCalendar.class, new Integer(TYPE_CALENDAR));
_typeMap.put(Boolean.TYPE, TYPE_BOOLEAN);
_typeMap.put(Integer.TYPE, TYPE_INT);
_typeMap.put(Long.TYPE, TYPE_LONG);
_typeMap.put(Byte.TYPE, TYPE_BYTE);
_typeMap.put(Short.TYPE, TYPE_SHORT);
_typeMap.put(Float.TYPE, TYPE_FLOAT);
_typeMap.put(Double.TYPE, TYPE_DOUBLE);
_typeMap.put(Boolean.class, TYPE_BOOLEAN_OBJ);
_typeMap.put(Integer.class, TYPE_INT_OBJ);
_typeMap.put(Long.class, TYPE_LONG_OBJ);
_typeMap.put(Byte.class, TYPE_BYTE_OBJ);
_typeMap.put(Short.class, TYPE_SHORT_OBJ);
_typeMap.put(Float.class, TYPE_FLOAT_OBJ);
_typeMap.put(Double.class, TYPE_DOUBLE_OBJ);
_typeMap.put(String.class, TYPE_STRING);
_typeMap.put(java.math.BigDecimal.class, TYPE_BIG_DECIMAL);
_typeMap.put(byte[].class, TYPE_BYTES);
_typeMap.put(java.sql.Timestamp.class, TYPE_TIMESTAMP);
_typeMap.put(java.sql.Time.class, TYPE_TIME);
_typeMap.put(java.sql.Date.class, TYPE_SQLDATE);
_typeMap.put(java.sql.Ref.class, TYPE_REF);
_typeMap.put(Blob.class, TYPE_BLOB);
_typeMap.put(Clob.class, TYPE_CLOB);
_typeMap.put(java.sql.Array.class, TYPE_ARRAY);
_typeMap.put(java.sql.Struct.class, TYPE_STRUCT);
_typeMap.put(java.io.Reader.class, TYPE_READER);
_typeMap.put(java.io.InputStream.class, TYPE_STREAM);
_typeMap.put(java.util.Date.class, TYPE_DATE);
_typeMap.put(java.util.Calendar.class, TYPE_CALENDAR);
_typeMap.put(java.util.GregorianCalendar.class, TYPE_CALENDAR);
if (XMLBEANS_STRING_ENUM_ABSTRACT_BASE != null) {
_typeMap.put(XMLBEANS_STRING_ENUM_ABSTRACT_BASE, new Integer(TYPE_XMLBEAN_ENUM));
_typeMap.put(XMLBEANS_STRING_ENUM_ABSTRACT_BASE, TYPE_XMLBEAN_ENUM);
}
// Class to java.sql.Types
_typeSqlMap = new HashMap<Class, Integer>(TYPE_MAX * 2);
_typeSqlMap.put(Boolean.TYPE, new Integer(Types.BOOLEAN));
_typeSqlMap.put(Integer.TYPE, new Integer(Types.INTEGER));
_typeSqlMap.put(Long.TYPE, new Integer(Types.BIGINT));
_typeSqlMap.put(Byte.TYPE, new Integer(Types.TINYINT));
_typeSqlMap.put(Short.TYPE, new Integer(Types.SMALLINT));
_typeSqlMap.put(Float.TYPE, new Integer(Types.REAL));
_typeSqlMap.put(Double.TYPE, new Integer(Types.DOUBLE));
_typeSqlMap.put(Boolean.class, new Integer(Types.BOOLEAN));
_typeSqlMap.put(Integer.class, new Integer(Types.INTEGER));
_typeSqlMap.put(Long.class, new Integer(Types.BIGINT));
_typeSqlMap.put(Byte.class, new Integer(Types.TINYINT));
_typeSqlMap.put(Short.class, new Integer(Types.SMALLINT));
_typeSqlMap.put(Float.class, new Integer(Types.REAL));
_typeSqlMap.put(Double.class, new Integer(Types.DOUBLE));
_typeSqlMap.put(String.class, new Integer(Types.VARCHAR));
_typeSqlMap.put(java.math.BigDecimal.class, new Integer(Types.DECIMAL));
_typeSqlMap.put(byte[].class, new Integer(Types.VARBINARY));
_typeSqlMap.put(java.sql.Timestamp.class, new Integer(Types.TIMESTAMP));
_typeSqlMap.put(java.sql.Time.class, new Integer(Types.TIME));
_typeSqlMap.put(java.sql.Date.class, new Integer(Types.DATE));
_typeSqlMap.put(java.sql.Ref.class, new Integer(Types.REF));
_typeSqlMap.put(Blob.class, new Integer(Types.BLOB));
_typeSqlMap.put(Clob.class, new Integer(Types.CLOB));
_typeSqlMap.put(java.sql.Array.class, new Integer(Types.ARRAY));
_typeSqlMap.put(java.sql.Struct.class, new Integer(Types.STRUCT));
_typeSqlMap.put(java.util.Date.class, new Integer(Types.TIMESTAMP));
_typeSqlMap.put(java.util.Calendar.class, new Integer(Types.TIMESTAMP));
_typeSqlMap.put(java.util.GregorianCalendar.class, new Integer(Types.TIMESTAMP));
if (XMLBEANS_STRING_ENUM_ABSTRACT_BASE != null) {
_typeSqlMap.put(XMLBEANS_STRING_ENUM_ABSTRACT_BASE, new Integer(Types.VARCHAR));
}
// String to java.sql.Types
_typeSqlNameMap = new HashMap<String, Integer>(TYPE_MAX * 2);
_typeSqlNameMap.put("BIT", new Integer(Types.BIT));
_typeSqlNameMap.put("TINYINT", new Integer(Types.TINYINT));
_typeSqlNameMap.put("SMALLINT", new Integer(Types.SMALLINT));
_typeSqlNameMap.put("INTEGER", new Integer(Types.INTEGER));
_typeSqlNameMap.put("BIGINT", new Integer(Types.BIGINT));
_typeSqlNameMap.put("FLOAT", new Integer(Types.REAL));
_typeSqlNameMap.put("REAL", new Integer(Types.REAL));
_typeSqlNameMap.put("DOUBLE", new Integer(Types.DOUBLE));
_typeSqlNameMap.put("NUMERIC", new Integer(Types.NUMERIC));
_typeSqlNameMap.put("DECIMAL", new Integer(Types.DECIMAL));
_typeSqlNameMap.put("CHAR", new Integer(Types.CHAR));
_typeSqlNameMap.put("VARCHAR", new Integer(Types.VARCHAR));
_typeSqlNameMap.put("LONGVARCHAR", new Integer(Types.LONGVARCHAR));
_typeSqlNameMap.put("DATE", new Integer(Types.DATE));
_typeSqlNameMap.put("TIME", new Integer(Types.TIME));
_typeSqlNameMap.put("TIMESTAMP", new Integer(Types.TIMESTAMP));
_typeSqlNameMap.put("BINARY", new Integer(Types.BINARY));
_typeSqlNameMap.put("VARBINARY", new Integer(Types.VARBINARY));
_typeSqlNameMap.put("LONGVARBINARY", new Integer(Types.LONGVARBINARY));
_typeSqlNameMap.put("NULL", new Integer(Types.NULL));
_typeSqlNameMap.put("OTHER", new Integer(Types.OTHER));
_typeSqlNameMap.put("JAVA_OBJECT", new Integer(Types.JAVA_OBJECT));
_typeSqlNameMap.put("DISTINCT", new Integer(Types.DISTINCT));
_typeSqlNameMap.put("STRUCT", new Integer(Types.STRUCT));
_typeSqlNameMap.put("ARRAY", new Integer(Types.ARRAY));
_typeSqlNameMap.put("BLOB", new Integer(Types.BLOB));
_typeSqlNameMap.put("CLOB", new Integer(Types.CLOB));
_typeSqlNameMap.put("REF", new Integer(Types.REF));
_typeSqlNameMap.put("DATALINK", new Integer(Types.DATALINK));
_typeSqlNameMap.put("BOOLEAN", new Integer(Types.BOOLEAN));
// some JAVA synonyms
_typeSqlNameMap.put("BYTE", new Integer(Types.TINYINT));
_typeSqlNameMap.put("SHORT", new Integer(Types.SMALLINT));
_typeSqlNameMap.put("INT", new Integer(Types.INTEGER));
_typeSqlNameMap.put("LONG", new Integer(Types.BIGINT));
// cache the Map.get method for efficiency
try {
_methodMapGet = Map.class.getMethod("get", new Class[]{Object.class});
} catch (NoSuchMethodException e) {
throw new MapperException("Can not find java.util.Map.get(Object) method");
}
}
/**
* Convert a type string to its SQL Type int value.
* @param type A String containing the SQL type name.
* @return The SQL type, TYPE_UNKNOWN if cannot convert.
*/
public int convertStringToSQLType(String type) {
if (_typeSqlNameMap.containsKey(type.toUpperCase())) {
return _typeSqlNameMap.get(type.toUpperCase());
}
return TYPE_UNKNOWN;
}
/**
* Get the SQL type of a class, start at top level class an check all super classes until match is found.
* @param classType Class to get SQL type of.
* @return Types.OTHER if cannot find SQL type.
*/
public int getSqlType(Class classType) {
final Class origType = classType;
while (classType != null) {
Integer type = _typeSqlMap.get(classType);
if (type != null) {
return type.intValue();
}
classType = classType.getSuperclass();
}
//
// special check for blobs/clobs they are interfaces not derived from
//
if (Blob.class.isAssignableFrom(origType)) {
return _typeSqlMap.get(Blob.class).intValue();
} else if (Clob.class.isAssignableFrom(origType)) {
return _typeSqlMap.get(Clob.class).intValue();
}
return Types.OTHER;
}
/**
* Get the SQL type for an object.
* @param o Object to get SQL type of.
* @return SQL type of the object, Types.OTHER if cannot classify.
*/
public int getSqlType(Object o) {
if (null == o) {
return Types.NULL;
}
return getSqlType(o.getClass());
}
/**
*
* @param val
* @param args
* @return the type
* @throws IllegalAccessException
* @throws java.lang.reflect.InvocationTargetException
*/
public Object lookupType(Object val, Object[] args)
throws IllegalAccessException, InvocationTargetException
{
return _methodMapGet.invoke(val, args);
_typeMap.put(Enum.class, TYPE_ENUM);
}
/**
@ -343,64 +182,4 @@ public final class TypeMappingsFactory {
public Object fixNull(Class type) {
return type.isPrimitive() ? _primitiveDefaults.get(type) : null;
}
/**
* Create an Object array for the given array.
*
* @param o An array.
* @return A new object array.
*/
public static Object[] toObjectArray(Object o) {
Class clas = o.getClass().getComponentType();
if (null == clas) return null;
Object[] arr;
if (clas == Boolean.TYPE) {
boolean[] src = (boolean[]) o;
arr = new Object[src.length];
for (int i = 0; i < src.length; i++)
arr[i] = new Boolean(src[i]);
} else if (clas == Character.TYPE) {
char[] src = (char[]) o;
arr = new Object[src.length];
for (int i = 0; i < src.length; i++)
arr[i] = new Character(src[i]);
} else if (clas == Byte.TYPE) {
byte[] src = (byte[]) o;
arr = new Object[src.length];
for (int i = 0; i < src.length; i++)
arr[i] = new Byte(src[i]);
} else if (clas == Short.TYPE) {
short[] src = (short[]) o;
arr = new Object[src.length];
for (int i = 0; i < src.length; i++)
arr[i] = new Short(src[i]);
} else if (clas == Integer.TYPE) {
int[] src = (int[]) o;
arr = new Object[src.length];
for (int i = 0; i < src.length; i++)
arr[i] = new Integer(src[i]);
} else if (clas == Long.TYPE) {
long[] src = (long[]) o;
arr = new Object[src.length];
for (int i = 0; i < src.length; i++)
arr[i] = new Long(src[i]);
} else if (clas == Float.TYPE) {
float[] src = (float[]) o;
arr = new Object[src.length];
for (int i = 0; i < src.length; i++)
arr[i] = new Float(src[i]);
} else if (clas == Double.TYPE) {
double[] src = (double[]) o;
arr = new Object[src.length];
for (int i = 0; i < src.length; i++)
arr[i] = new Double(src[i]);
} else {
arr = (Object[]) o;
}
return arr;
}
}

View File

@ -425,4 +425,15 @@ public class QueryMapperTest {
//IFJAVA8_END
@Test
public void testEnumPerson() throws SQLException {
assertEquals(new EnumPerson(FirstName.First), qm.toObject("SELECT first_name, last_name FROM person WHERE person_no = ?", EnumPerson.class, fieldPerson1.getPersonNo()));
}
@Test
public void testEnum() throws SQLException {
assertEquals(FirstName.First, qm.toObject("SELECT first_name FROM person WHERE person_no = ?", FirstName.class, fieldPerson1.getPersonNo()));
}
}

View File

@ -0,0 +1,54 @@
package com.moparisthebest.jdbc.dto;
import java.util.Date;
/**
* Created by mopar on 6/13/17.
*/
public class EnumPerson implements Person {
public FirstName firstName;
public String lastName;
public EnumPerson() {
}
public EnumPerson(final FirstName firstName) {
this.firstName = firstName;
}
@Override
public long getPersonNo() {
return 0;
}
@Override
public Date getBirthDate() {
return null;
}
@Override
public String getFirstName() {
return firstName.name();
}
@Override
public String getLastName() {
return lastName;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (!(o instanceof EnumPerson)) return false;
final EnumPerson that = (EnumPerson) o;
return firstName == that.firstName;
}
@Override
public int hashCode() {
return firstName != null ? firstName.hashCode() : 0;
}
}

View File

@ -0,0 +1,10 @@
package com.moparisthebest.jdbc.dto;
/**
* Created by mopar on 6/13/17.
*/
public enum FirstName {
First,
Second,
Third,
}