1 18 19 package org.apache.beehive.controls.system.jdbc; 20 21 import org.apache.beehive.controls.api.ControlException; 22 import org.apache.xmlbeans.SchemaProperty; 23 import org.apache.xmlbeans.SchemaType; 24 import org.apache.xmlbeans.XmlObject; 25 import org.apache.xmlbeans.XmlOptions; 26 27 import java.lang.reflect.Field ; 28 import java.lang.reflect.InvocationTargetException ; 29 import java.lang.reflect.Method ; 30 import java.lang.reflect.Modifier ; 31 import java.sql.ResultSet ; 32 import java.sql.ResultSetMetaData ; 33 import java.sql.SQLException ; 34 import java.util.Calendar ; 35 import java.util.HashMap ; 36 37 40 public class RowToXmlObjectMapper extends RowMapper { 41 42 private final int _columnCount; 43 private final SchemaType _schemaType; 44 45 private SetterMethod[] _setterMethods; 46 private final Object [] _args = new Object [1]; 47 48 56 RowToXmlObjectMapper(ResultSet resultSet, Class returnTypeClass, Calendar cal) 57 throws SQLException { 58 super(resultSet, returnTypeClass, cal); 59 60 _columnCount = resultSet.getMetaData().getColumnCount(); 61 _schemaType = getSchemaType(_returnTypeClass); 62 _setterMethods = null; 63 } 64 65 70 public Object mapRowToReturnType() { 71 72 Object resultObject = null; 73 if (_columnCount == 1) { 74 75 final int typeId = _tmf.getTypeId(_returnTypeClass); 76 77 try { 78 if (typeId != TypeMappingsFactory.TYPE_UNKNOWN) { 79 return extractColumnValue(1, typeId); 80 } else { 81 Object val = extractColumnValue(1, typeId); 83 if (_returnTypeClass.isAssignableFrom(val.getClass())) { 84 return val; 85 } 86 } 87 } catch (SQLException e) { 88 throw new ControlException(e.getMessage(), e); 89 } 90 } 91 92 if (_setterMethods == null) { 93 try { 94 getResultSetMappings(); 95 } catch (SQLException e) { 96 throw new ControlException(e.getMessage(), e); 97 } 98 } 99 100 resultObject = XmlObject.Factory.newInstance(new XmlOptions().setDocumentType(_schemaType)); 101 102 for (int i = 1; i < _setterMethods.length; i++) { 103 Method setterMethod = _setterMethods[i].getSetter(); 104 Object resultValue = null; 105 106 try { 107 resultValue = extractColumnValue(i, _setterMethods[i].getParameterType()); 108 109 if (_setterMethods[i].getParameterType() == TypeMappingsFactory.TYPE_XMLBEAN_ENUM) { 113 Class parameterClass = _setterMethods[i].getParameterClass(); 114 Method m = parameterClass.getMethod("forString", new Class []{String .class}); 115 resultValue = m.invoke(null, new Object []{resultValue}); 116 } 117 118 _args[0] = resultValue; 119 setterMethod.invoke(resultObject, _args); 120 121 if (_setterMethods[i].getNilable() != null) { 122 if (_resultSet.wasNull()) { 123 _setterMethods[i].getNilable().invoke(resultObject, (Object []) null); 124 } 125 } 126 } catch (SQLException se) { 127 throw new ControlException(se.getMessage(), se); 128 } catch (IllegalArgumentException iae) { 129 try { 130 ResultSetMetaData md = _resultSet.getMetaData(); 131 throw new ControlException("The declared Java type for method " + setterMethod.getName() 132 + setterMethod.getParameterTypes()[0].toString() 133 + " is incompatible with the SQL format of column " + md.getColumnName(i).toString() 134 + md.getColumnTypeName(i).toString() 135 + " which returns objects of type " + resultValue.getClass().getName()); 136 } catch (SQLException e) { 137 throw new ControlException(e.getMessage(), e); 138 } 139 } catch (IllegalAccessException e) { 140 throw new ControlException("IllegalAccessException when trying to access method " + setterMethod.getName(), e); 141 } catch (NoSuchMethodException e) { 142 throw new ControlException("NoSuchMethodException when trying to map schema enum value using Enum.forString().", e); 143 } catch (InvocationTargetException e) { 144 throw new ControlException("IllegalInvocationException when trying to access method " + setterMethod.getName(), e); 145 } 146 } 147 return resultObject; 148 } 149 150 151 153 158 private void getResultSetMappings() throws SQLException { 159 160 if (_schemaType.isDocumentType()) { 164 return; 165 } 166 167 final String [] keys = getKeysFromResultSet(); 168 169 HashMap <String , Method > mapFields = new HashMap <String , Method >(_columnCount * 2); 173 for (int i = 1; i <= _columnCount; i++) { 174 mapFields.put(keys[i], null); 175 } 176 177 Method [] classMethods = _returnTypeClass.getMethods(); 179 for (Method method : classMethods) { 180 181 if (isSetterMethod(method)) { 182 final String fieldName = method.getName().substring(3).toUpperCase(); 183 if (mapFields.containsKey(fieldName)) { 184 mapFields.put(fieldName, method); 185 } 186 } 187 } 188 189 _setterMethods = new SetterMethod[_columnCount + 1]; 191 192 for (int i = 1; i < _setterMethods.length; i++) { 193 Method setterMethod = mapFields.get(keys[i]); 194 if (setterMethod == null) { 195 throw new ControlException("Unable to map the SQL column " + keys[i] 196 + " to a field on the " + _returnTypeClass.getName() + 197 " class. Mapping is done using a case insensitive comparision of SQL ResultSet " 198 + "columns to public setter methods on the return class."); 199 } 200 201 _setterMethods[i] = new SetterMethod(setterMethod); 202 } 203 } 204 205 211 protected String [] getKeysFromResultSet() 212 throws SQLException { 213 214 String [] keys = super.getKeysFromResultSet(); 215 216 SchemaProperty[] props = _schemaType.getElementProperties(); 218 for (int i = 0; i < props.length; i++) { 219 220 int col = -1; 221 try { 222 col = _resultSet.findColumn(props[i].getName().getLocalPart()); 223 } catch (SQLException x) { 224 } 225 226 if (col > 0) { 227 keys[col] = props[i].getJavaPropertyName().toUpperCase(); 228 } 229 } 230 return keys; 231 } 232 233 239 private SchemaType getSchemaType(Class returnType) { 240 SchemaType schemaType = null; 241 if (XmlObject.class.isAssignableFrom(returnType)) { 242 try { 243 Field f = returnType.getField("type"); 244 if (SchemaType.class.isAssignableFrom(f.getType()) && Modifier.isStatic(f.getModifiers())) { 245 schemaType = (SchemaType) f.get(null); 246 } 247 } catch (NoSuchFieldException x) { 248 } catch (IllegalAccessException x) { 249 } 250 } 251 return schemaType; 252 } 253 254 256 259 private final class SetterMethod { 260 private final Method _setter; 261 private final int _parameterType; 262 private final Class _parameterClass; 263 private final Method _nilable; 264 265 270 SetterMethod(Method setter) { 271 _setter = setter; 272 _parameterClass = _setter.getParameterTypes()[0]; 273 _parameterType = _tmf.getTypeId(_parameterClass); 274 _nilable = isNilable(); 275 } 276 277 282 Method getSetter() { return _setter; } 283 284 289 Class getParameterClass() { return _parameterClass; } 290 291 297 int getParameterType() { return _parameterType; } 298 299 304 Method getNilable() { return _nilable; } 305 306 316 private Method isNilable() { 317 try { 318 return _returnTypeClass.getMethod("setNil" + _setter.getName().substring(3), new Class []{}); 319 } catch (NoSuchMethodException e) { 320 } 322 return null; 323 } 324 } 325 } 326 | Popular Tags |