001 /* 002 @license.text@ 003 */ 004 package biz.hammurapi.sql; 005 006 import java.lang.reflect.Constructor; 007 import java.lang.reflect.InvocationTargetException; 008 import java.sql.ResultSet; 009 import java.sql.SQLException; 010 011 import biz.hammurapi.config.RuntimeConfigurationException; 012 import biz.hammurapi.convert.ConverterClosure; 013 import biz.hammurapi.convert.ConvertingService; 014 015 016 /** 017 * Base class for SQLC generated projectors. 018 * @author Pavel Vlasov 019 * 020 * @version $Revision: 1.3 $ 021 */ 022 public class SmartProjector implements Projector { 023 private ConverterClosure converter; 024 private Class targetClass; 025 private Class sourceClass; 026 private Constructor sourceClassConstructor; 027 028 public Object project(ResultSet rs) throws SQLException { 029 Object ret; 030 if (targetClass==null) { 031 ret = defaultProject(rs); 032 } else { 033 if (sourceClass.isAssignableFrom(targetClass)) { 034 ret=project(rs, targetClass); 035 } else { 036 ret=ConvertingService.convert(defaultProject(rs), targetClass); 037 } 038 } 039 040 if (converter==null) { 041 return ret; 042 } 043 044 return converter.convert(ret); 045 } 046 047 /** 048 * @param rs 049 * @param ret 050 * @return 051 * @throws SQLException 052 */ 053 private Object defaultProject(ResultSet rs) throws SQLException { 054 try { 055 if (!sourceClassConstructor.isAccessible()) { 056 sourceClassConstructor.setAccessible(true); // To use private nested classes. 057 } 058 return sourceClassConstructor.newInstance(new Object[] {rs}); 059 } catch (Exception e) { 060 throw new SQLExceptionEx(e); 061 } 062 } 063 064 /** 065 * @param rs 066 * @return 067 * @throws SQLException 068 * @throws InstantiationException 069 * @throws IllegalAccessException 070 * @throws InvocationTargetException 071 * @throws NoSuchMethodException 072 */ 073 private Object project(ResultSet rs, Class clazz) throws SQLException { 074 try { 075 Constructor constructor = clazz.getConstructor(new Class[] {ResultSet.class}); 076 if (!constructor.isAccessible()) { 077 constructor.setAccessible(true); // To use private nested classes. 078 } 079 return constructor.newInstance(new Object[] {rs}); 080 } catch (Exception e) { 081 throw new SQLExceptionEx(e); 082 } 083 } 084 085 public SmartProjector(Class sourceClass) { 086 this.sourceClass=sourceClass; 087 try { 088 this.sourceClassConstructor=sourceClass.getConstructor(new Class[] {ResultSet.class}); 089 } catch (SecurityException e) { 090 throw new RuntimeConfigurationException("Caused by: "+e, e); 091 } catch (NoSuchMethodException e) { 092 throw new RuntimeConfigurationException("Constructor from ResultSet not found in "+sourceClass+": "+e, e); 093 } 094 } 095 096 public SmartProjector(Class sourceClass, Class targetClass, ConverterClosure converter) { 097 this.converter=converter; 098 this.targetClass=targetClass; 099 this.sourceClass=sourceClass; 100 try { 101 this.sourceClassConstructor=sourceClass.getConstructor(new Class[] {ResultSet.class}); 102 } catch (SecurityException e) { 103 throw new RuntimeConfigurationException("Caused by: "+e, e); 104 } catch (NoSuchMethodException e) { 105 throw new RuntimeConfigurationException("Constructor from ResultSet not found in "+sourceClass+": "+e, e); 106 } 107 } 108 }