1 package sharin.sql.runner.processor;
2
3 import java.math.BigDecimal;
4 import java.sql.Date;
5 import java.sql.ResultSet;
6 import java.sql.ResultSetMetaData;
7 import java.sql.Time;
8 import java.sql.Timestamp;
9 import java.util.HashMap;
10 import java.util.Map;
11
12 import sharin.sql.runner.ColumnConverter;
13 import sharin.sql.runner.ResultSetProcessor;
14 import sharin.sql.runner.converter.BigDecimalColumnConverter;
15 import sharin.sql.runner.converter.BooleanColumnConverter;
16 import sharin.sql.runner.converter.ByteColumnConverter;
17 import sharin.sql.runner.converter.BytesColumnConverter;
18 import sharin.sql.runner.converter.DateColumnConverter;
19 import sharin.sql.runner.converter.DoubleColumnConverter;
20 import sharin.sql.runner.converter.FloatColumnConverter;
21 import sharin.sql.runner.converter.IntegerColumnConverter;
22 import sharin.sql.runner.converter.LongColumnConverter;
23 import sharin.sql.runner.converter.ObjectColumnConverter;
24 import sharin.sql.runner.converter.PrimitiveBooleanColumnConverter;
25 import sharin.sql.runner.converter.PrimitiveByteColumnConverter;
26 import sharin.sql.runner.converter.PrimitiveDoubleColumnConverter;
27 import sharin.sql.runner.converter.PrimitiveFloatColumnConverter;
28 import sharin.sql.runner.converter.PrimitiveIntColumnConverter;
29 import sharin.sql.runner.converter.PrimitiveLongColumnConverter;
30 import sharin.sql.runner.converter.PrimitiveShortColumnConverter;
31 import sharin.sql.runner.converter.ShortColumnConverter;
32 import sharin.sql.runner.converter.StringColumnConverter;
33 import sharin.sql.runner.converter.TimeColumnConverter;
34 import sharin.sql.runner.converter.TimestampColumnConverter;
35 import sharin.util.PropertyUtils;
36 import sharin.util.ReflectUtils;
37 import sharin.util.SqlUtils;
38
39 public class BeanResultSetProcessor implements ResultSetProcessor {
40
41 private static final Map<Class<?>, ColumnConverter> defaultColumnConverterMap;
42
43 static {
44 Map<Class<?>, ColumnConverter> map = new HashMap<Class<?>, ColumnConverter>();
45
46 map.put(boolean.class, new PrimitiveBooleanColumnConverter());
47 map.put(byte.class, new PrimitiveByteColumnConverter());
48 map.put(double.class, new PrimitiveDoubleColumnConverter());
49 map.put(float.class, new PrimitiveFloatColumnConverter());
50 map.put(int.class, new PrimitiveIntColumnConverter());
51 map.put(long.class, new PrimitiveLongColumnConverter());
52 map.put(short.class, new PrimitiveShortColumnConverter());
53
54 map.put(BigDecimal.class, new BigDecimalColumnConverter());
55 map.put(Boolean.class, new BooleanColumnConverter());
56 map.put(Byte.class, new ByteColumnConverter());
57 map.put(byte[].class, new BytesColumnConverter());
58 map.put(Date.class, new DateColumnConverter());
59 map.put(Double.class, new DoubleColumnConverter());
60 map.put(Float.class, new FloatColumnConverter());
61 map.put(Integer.class, new IntegerColumnConverter());
62 map.put(Long.class, new LongColumnConverter());
63 map.put(Object.class, new ObjectColumnConverter());
64 map.put(Short.class, new ShortColumnConverter());
65 map.put(String.class, new StringColumnConverter());
66 map.put(Time.class, new TimeColumnConverter());
67 map.put(Timestamp.class, new TimestampColumnConverter());
68
69 defaultColumnConverterMap = map;
70 }
71
72 private final Class<?> beanClass;
73
74 private final Map<Class<?>, ColumnConverter> columnConverterMap;
75
76 private final ColumnConverter objectColumnConverter;
77
78 public BeanResultSetProcessor(Class<?> beanClass) {
79 this(beanClass, null);
80 }
81
82 public BeanResultSetProcessor(Class<?> beanClass,
83 Map<Class<?>, ColumnConverter> columnConverterMap) {
84
85 this.beanClass = beanClass;
86
87 Map<Class<?>, ColumnConverter> map = new HashMap<Class<?>, ColumnConverter>();
88 map.putAll(defaultColumnConverterMap);
89
90 if (columnConverterMap != null) {
91 map.putAll(columnConverterMap);
92 }
93
94 this.columnConverterMap = map;
95 this.objectColumnConverter = map.get(Object.class);
96 }
97
98 public Object prepare(ResultSet rs) {
99 ResultSetMetaData metaData = SqlUtils.getMetaData(rs);
100 int columnCount = SqlUtils.getColumnCount(metaData);
101 String[] columnLabels = new String[columnCount];
102 ColumnConverter[] columnConverters = new ColumnConverter[columnCount];
103
104 for (int i = 0; i < columnCount; i++) {
105 columnLabels[i] = SqlUtils.getColumnLabel(metaData, i + 1);
106 Class<?> type = PropertyUtils.getNestedPropertyType(beanClass,
107 columnLabels[i]);
108
109 if (type != null) {
110 columnConverters[i] = columnConverterMap.get(type);
111 }
112
113 if (columnConverters[i] == null) {
114 columnConverters[i] = objectColumnConverter;
115 }
116 }
117
118 Map<String, Object> mapContext = new HashMap<String, Object>();
119 mapContext.put("columnLabels", columnLabels);
120 mapContext.put("columnConverters", columnConverters);
121 return mapContext;
122 }
123
124 @SuppressWarnings("unchecked")
125 public Object process(ResultSet rs, Object context) {
126 Map<String, Object> mapContext = (Map<String, Object>) context;
127 String[] columnLabels = (String[]) mapContext.get("columnLabels");
128 ColumnConverter[] columnConverters = (ColumnConverter[]) mapContext
129 .get("columnConverters");
130 Object result = ReflectUtils.newInstance(beanClass);
131
132 for (int i = 0; i < columnLabels.length; i++) {
133 Object value = columnConverters[i].convert(rs, i + 1);
134 PropertyUtils
135 .setNestedPropertyValue(result, columnLabels[i], value);
136 }
137
138 return result;
139 }
140 }