View Javadoc

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 }