1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sf.morph.reflect.reflectors;
17
18 import java.sql.Blob;
19 import java.sql.Clob;
20 import java.sql.ResultSet;
21 import java.sql.ResultSetMetaData;
22 import java.util.Iterator;
23
24 import org.springframework.jdbc.support.JdbcUtils;
25
26 import net.sf.morph.reflect.BeanReflector;
27 import net.sf.morph.reflect.ContainerReflector;
28 import net.sf.morph.reflect.support.ResultSetIterator;
29 import net.sf.morph.transform.TransformationException;
30
31 /**
32 * <p>
33 * Exposes the information in a ResultSet. This reflector can function both as a
34 * container reflector and as a bean reflector. When functionining a container
35 * reflector, this reflector exposes the rows in a ResultSet. As a bean
36 * reflector, this reflector exposes the column names from a particular row of a
37 * ResultSet as properties. The column names are always converted to all
38 * lowercase.
39 * </p>
40 *
41 * <p>
42 * Note: Code from the {@link #getImpl(Object, String)} method was taken from
43 * Spring's {@link JdbcUtils} class.
44 * </p>
45 *
46 * @author Matt Sgarlata
47 * @since Dec 18, 2004
48 */
49 public class ResultSetReflector
50 extends BaseBeanReflector
51 implements BeanReflector, ContainerReflector {
52
53 private static final Class[] REFLECTABLE_TYPES = new Class[] {
54 ResultSet.class
55 };
56
57 private ResultSet getResultSet(Object bean) {
58 return (ResultSet) bean;
59 }
60
61 private ResultSetMetaData getMetaData(Object bean) throws Exception {
62 return getResultSet(bean).getMetaData();
63 }
64
65
66
67 protected Class getContainedTypeImpl(Class clazz) throws Exception {
68 return ResultSet.class;
69 }
70 protected Iterator getIteratorImpl(Object container) throws Exception {
71 return new ResultSetIterator((ResultSet) container);
72 }
73
74
75
76 private int getIndexForColumn(Object bean, String propertyName) throws Exception {
77 int numColumns = getMetaData(bean).getColumnCount();
78 String lowerCasePropertyName = propertyName.toLowerCase();
79 for (int i=1; i<numColumns; i++) {
80 if (lowerCasePropertyName.equals(getMetaData(bean).getColumnLabel(i).toLowerCase())) {
81 return i;
82 }
83 }
84 throw new TransformationException("The propertyName you specified '" + propertyName + "' was not found to be a column in the given ResultSet");
85 }
86
87 protected String[] getPropertyNamesImpl(Object bean) throws Exception {
88 ResultSetMetaData meta = getMetaData(bean);
89 int numColumns = meta.getColumnCount();
90 String[] propertyNames = new String[numColumns];
91 for (int i=0; i<propertyNames.length; i++) {
92 propertyNames[i] = meta.getColumnName(i+1).toLowerCase();
93 }
94 return propertyNames;
95 }
96
97 protected Class getTypeImpl(Object bean, String propertyName)
98 throws Exception {
99 return Class.forName(getMetaData(bean).getColumnClassName(
100 getIndexForColumn(bean, propertyName)));
101 }
102
103 protected boolean isWriteableImpl(Object bean, String propertyName)
104 throws Exception {
105 return getMetaData(bean).isWritable(
106 getIndexForColumn(bean, propertyName));
107 }
108
109 /**
110 * NOTE: Code copied here from Spring's
111 * {@link org.springframework.jdbc.support.JdbcUtils} class.
112 */
113 protected Object getImpl(Object bean, String propertyName) throws Exception {
114 ResultSet rs = getResultSet(bean);
115 Object obj = rs.getObject(propertyName);
116 if (obj instanceof Blob) {
117 obj = rs.getBytes(propertyName);
118 }
119 else if (obj instanceof Clob) {
120 obj = rs.getString(propertyName);
121 }
122 else if (obj != null && obj.getClass().getName().startsWith("oracle.sql.TIMESTAMP")) {
123 obj = rs.getTimestamp(propertyName);
124 }
125 else if (obj != null && obj.getClass().getName().startsWith("oracle.sql.DATE")) {
126 int index = getIndexForColumn(bean, propertyName);
127 String metaDataClassName = rs.getMetaData().getColumnClassName(index);
128 if ("java.sql.Timestamp".equals(metaDataClassName) ||
129 "oracle.sql.TIMESTAMP".equals(metaDataClassName)) {
130 obj = rs.getTimestamp(propertyName);
131 }
132 else {
133 obj = rs.getDate(propertyName);
134 }
135 }
136 else if (obj != null && obj instanceof java.sql.Date) {
137 int index = getIndexForColumn(bean, propertyName);
138 if ("java.sql.Timestamp".equals(rs.getMetaData().getColumnClassName(index))) {
139 obj = rs.getTimestamp(propertyName);
140 }
141 }
142 return obj;
143 }
144
145 protected void setImpl(Object bean, String propertyName, Object value)
146 throws Exception {
147 getResultSet(bean).updateObject(propertyName, value);
148 }
149
150 protected Class[] getReflectableClassesImpl() throws Exception {
151 return REFLECTABLE_TYPES;
152 }
153
154 public boolean isStrictlyTyped() {
155 return true;
156 }
157
158 }