1 18 19 package org.apache.beehive.controls.system.jdbc; 20 21 import org.apache.beehive.controls.api.ControlException; 22 23 import java.lang.reflect.AccessibleObject ; 24 import java.lang.reflect.Field ; 25 import java.lang.reflect.InvocationTargetException ; 26 import java.lang.reflect.Method ; 27 import java.lang.reflect.Modifier ; 28 import java.sql.ResultSet ; 29 import java.sql.ResultSetMetaData ; 30 import java.sql.SQLException ; 31 import java.util.Calendar ; 32 import java.util.HashMap ; 33 34 40 public class RowToObjectMapper extends RowMapper { 41 42 private final int _columnCount; 43 44 private AccessibleObject [] _fields; 45 private int[] _fieldTypes; 46 47 private final Object [] _args = new Object [1]; 48 49 56 RowToObjectMapper(ResultSet resultSet, Class returnTypeClass, Calendar cal) { 57 super(resultSet, returnTypeClass, cal); 58 59 _fields = null; 60 61 try { 62 _columnCount = resultSet.getMetaData().getColumnCount(); 63 } catch (SQLException e) { 64 throw new ControlException("RowToObjectMapper: SQLException: " + e.getMessage(), e); 65 } 66 } 67 68 73 public Object mapRowToReturnType() { 74 75 Object resultObject = null; 76 77 if (_columnCount == 1) { 81 82 final int typeId = _tmf.getTypeId(_returnTypeClass); 83 84 try { 85 if (typeId != TypeMappingsFactory.TYPE_UNKNOWN) { 86 return extractColumnValue(1, typeId); 87 } else { 88 Object val = extractColumnValue(1, typeId); 90 if (_returnTypeClass.isAssignableFrom(val.getClass())) { 91 return val; 92 } 93 } 94 } catch (SQLException e) { 95 throw new ControlException(e.getMessage(), e); 96 } 97 } 98 99 if (_fields == null) { 100 try { 101 getFieldMappings(); 102 } catch (SQLException e) { 103 throw new ControlException(e.getMessage(), e); 104 } 105 } 106 107 try { 108 resultObject = _returnTypeClass.newInstance(); 109 } catch (InstantiationException e) { 110 throw new ControlException("InstantiationException when trying to create instance of : " 111 + _returnTypeClass.getName(), e); 112 } catch (IllegalAccessException e) { 113 throw new ControlException("IllegalAccessException when trying to create instance of : " 114 + _returnTypeClass.getName(), e); 115 } 116 117 for (int i = 1; i < _fields.length; i++) { 118 AccessibleObject f = _fields[i]; 119 Object resultValue = null; 120 121 try { 122 resultValue = extractColumnValue(i, _fieldTypes[i]); 123 if (f instanceof Field ) { 124 ((Field ) f).set(resultObject, resultValue); 125 } else { 126 _args[0] = resultValue; 127 ((Method ) f).invoke(resultObject, _args); 128 } 129 } catch (SQLException e) { 130 throw new ControlException(e.getMessage(), e); 131 } catch (IllegalArgumentException iae) { 132 133 try { 134 ResultSetMetaData md = _resultSet.getMetaData(); 135 if (f instanceof Field ) { 136 throw new ControlException("The declared Java type for field " + ((Field ) f).getName() 137 + ((Field ) f).getType().toString() 138 + " is incompatible with the SQL format of column " + md.getColumnName(i).toString() 139 + md.getColumnTypeName(i).toString() 140 + " which returns objects of type " + resultValue.getClass().getName()); 141 } else { 142 throw new ControlException("The declared Java type for method " + ((Method ) f).getName() 143 + ((Method ) f).getParameterTypes()[0].toString() 144 + " is incompatible with the SQL format of column " + md.getColumnName(i).toString() 145 + md.getColumnTypeName(i).toString() 146 + " which returns objects of type " + resultValue.getClass().getName()); 147 } 148 } catch (SQLException e) { 149 throw new ControlException(e.getMessage(), e); 150 } 151 152 } catch (IllegalAccessException e) { 153 if (f instanceof Field ) { 154 throw new ControlException("IllegalAccessException when trying to access field " + ((Field ) f).getName(), e); 155 } else { 156 throw new ControlException("IllegalAccessException when trying to access method " + ((Method ) f).getName(), e); 157 } 158 } catch (InvocationTargetException e) { 159 if (f instanceof Field ) { 160 throw new ControlException("InvocationTargetException when trying to access field " + ((Field ) f).getName(), e); 161 } else { 162 throw new ControlException("InvocationTargetException when trying to access method " + ((Method ) f).getName(), e); 163 } 164 } 165 } 166 return resultObject; 167 } 168 169 174 protected void getFieldMappings() 175 throws SQLException { 176 177 final String [] keys = getKeysFromResultSet(); 178 179 HashMap <String , AccessibleObject > mapFields = new HashMap <String , AccessibleObject >(_columnCount * 2); 183 for (int i = 1; i <= _columnCount; i++) { 184 mapFields.put(keys[i], null); 185 } 186 187 Method [] classMethods = _returnTypeClass.getMethods(); 189 for (Method m : classMethods) { 190 191 if (isSetterMethod(m)) { 192 final String fieldName = m.getName().substring(3).toUpperCase(); 193 if (mapFields.containsKey(fieldName)) { 194 195 Object field = mapFields.get(fieldName); 197 if (field == null) { 198 mapFields.put(fieldName, m); 199 } else { 200 throw new ControlException("Unable to choose between overloaded methods " + m.getName() 201 + " on the " + _returnTypeClass.getName() + " class. Mapping is done using " 202 + "a case insensitive comparision of SQL ResultSet columns to field " 203 + "names and public setter methods on the return class."); 204 } 205 } 206 } 207 } 208 209 for (Class clazz = _returnTypeClass; clazz != null && clazz != Object .class; clazz = clazz.getSuperclass()) { 211 Field [] classFields = clazz.getDeclaredFields(); 212 for (Field f : classFields) { 213 if (Modifier.isStatic(f.getModifiers())) continue; 214 if (!Modifier.isPublic(f.getModifiers())) continue; 215 String fieldName = f.getName().toUpperCase(); 216 if (!mapFields.containsKey(fieldName)) continue; 217 218 Object field = mapFields.get(fieldName); 219 if (field == null) { 220 mapFields.put(fieldName, f); 221 } 222 } 223 } 224 225 _fields = new AccessibleObject [_columnCount + 1]; 227 _fieldTypes = new int[_columnCount + 1]; 228 229 for (int i = 1; i < _fields.length; i++) { 230 AccessibleObject f = mapFields.get(keys[i]); 231 if (f == null) { 232 throw new ControlException("Unable to map the SQL column " + keys[i] 233 + " to a field on the " + _returnTypeClass.getName() + 234 " class. Mapping is done using a case insensitive comparision of SQL ResultSet " 235 + "columns to field names and public setter methods on the return class."); 236 } 237 238 _fields[i] = f; 239 if (f instanceof Field ) { 240 _fieldTypes[i] = _tmf.getTypeId(((Field ) f).getType()); 241 } else { 242 _fieldTypes[i] = _tmf.getTypeId(((Method ) f).getParameterTypes()[0]); 243 } 244 } 245 } 246 } 247 | Popular Tags |