/******************************************************************************* * Copyright (c) 2010 Robert "Unlogic" Olofsson (unlogic@unlogic.se). * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser Public License v3 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/lgpl-3.0-standalone.html ******************************************************************************/ package se.unlogic.standardutils.populators.annotated; import se.unlogic.standardutils.annotations.NoAnnotatedFieldsFoundException; import se.unlogic.standardutils.annotations.UnsupportedFieldTypeException; import se.unlogic.standardutils.dao.BeanResultSetPopulator; import se.unlogic.standardutils.dao.ResultSetField; import se.unlogic.standardutils.dao.ResultSetMethods; import se.unlogic.standardutils.dao.annotations.DAOManaged; import se.unlogic.standardutils.dao.annotations.ManyToMany; import se.unlogic.standardutils.dao.annotations.ManyToOne; import se.unlogic.standardutils.dao.annotations.OneToMany; import se.unlogic.standardutils.dao.annotations.OneToOne; import se.unlogic.standardutils.populators.BeanStringPopulator; import se.unlogic.standardutils.populators.BeanStringPopulatorRegistery; import se.unlogic.standardutils.populators.EnumPopulator; import se.unlogic.standardutils.reflection.ReflectionUtils; import se.unlogic.standardutils.string.StringUtils; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Arrays; import java.util.HashMap; import java.util.List; public class AnnotatedResultSetPopulator<T> implements BeanResultSetPopulator<T>{ protected Class<T> beanClass; protected HashMap<Field,ResultSetField> resultSetFieldMap = new HashMap<Field,ResultSetField>(); public AnnotatedResultSetPopulator(Class<T> beanClass) throws UnsupportedFieldTypeException{ this(beanClass, (List<BeanStringPopulator<?>>)null); } public AnnotatedResultSetPopulator(Class<T> beanClass, BeanStringPopulator<?>... populators) throws UnsupportedFieldTypeException{ this(beanClass,Arrays.asList(populators)); } @SuppressWarnings("unchecked") public AnnotatedResultSetPopulator(Class<T> beanClass, List<? extends BeanStringPopulator<?>> populators) throws UnsupportedFieldTypeException{ this.beanClass = beanClass; //cache fields List<Field> fields = ReflectionUtils.getFields(beanClass); for(Field field : fields){ DAOManaged annotation = field.getAnnotation(DAOManaged.class); if(annotation != null && (!field.isAnnotationPresent(OneToOne.class) && !field.isAnnotationPresent(OneToMany.class) && !field.isAnnotationPresent(ManyToOne.class) && !field.isAnnotationPresent(ManyToMany.class) )){ if(Modifier.isFinal(field.getModifiers())){ throw new UnsupportedFieldTypeException("The annotated field " + field.getName() + " in class " + beanClass + " is final!", field, annotation.getClass(), beanClass); } Method resultSetColumnNameMethod = ResultSetMethods.getColumnNameMethod(field.getType()); BeanStringPopulator<?> typePopulator = null; if(resultSetColumnNameMethod == null){ if(populators != null){ typePopulator = this.getPopulator(populators, field, annotation); } if(typePopulator == null){ typePopulator = BeanStringPopulatorRegistery.getBeanStringPopulator(field.getType()); } if(typePopulator == null){ if(field.getType().isEnum()){ typePopulator = EnumPopulator.getInstanceFromField(field); }else if(List.class.isAssignableFrom(field.getType()) && ReflectionUtils.getGenericlyTypeCount(field) == 1 && ((Class<?>)ReflectionUtils.getGenericType(field)).isEnum()){ typePopulator = EnumPopulator.getInstanceFromListField(field); } } if(typePopulator == null){ throw new UnsupportedFieldTypeException("The annotated field " + field.getName() + " in class " + beanClass + " is of unsupported type " + field.getType(), field, annotation.annotationType() , beanClass); } } ReflectionUtils.fixFieldAccess(field); Method resultSetColumnIndexMethod = ResultSetMethods.getColumnIndexMethod(field.getType()); if(!StringUtils.isEmpty(annotation.columnName())){ this.resultSetFieldMap.put(field,new ResultSetField(field,resultSetColumnNameMethod,resultSetColumnIndexMethod,annotation.columnName(),typePopulator)); }else{ this.resultSetFieldMap.put(field,new ResultSetField(field,resultSetColumnNameMethod,resultSetColumnIndexMethod,field.getName(),typePopulator)); } } } if(this.resultSetFieldMap.isEmpty()){ throw new NoAnnotatedFieldsFoundException(beanClass,DAOManaged.class); } } private BeanStringPopulator<?> getPopulator(List<? extends BeanStringPopulator<?>> populators, Field field, DAOManaged annotation) { String populatorID = annotation.populatorID(); Object clazz = field.getType(); for(BeanStringPopulator<?> populator : populators){ if(clazz.equals(populator.getType())){ if((StringUtils.isEmpty(populatorID) && populator.getPopulatorID() == null) || populatorID.equals(populator.getPopulatorID())){ return populator; } } } return null; } public T populate(ResultSet rs) throws SQLException, BeanResultSetPopulationException { ResultSetField currentField = null; try { T bean = beanClass.newInstance(); for(ResultSetField resultSetField : this.resultSetFieldMap.values()){ currentField = resultSetField; if(currentField.getResultSetColumnNameMethod() != null){ Object value = resultSetField.getResultSetColumnNameMethod().invoke(rs, resultSetField.getAlias()); if(rs.wasNull() && !resultSetField.getBeanField().getType().isPrimitive()){ resultSetField.getBeanField().set(bean, null); }else{ resultSetField.getBeanField().set(bean, value); } }else{ String value = rs.getString(currentField.getAlias()); if(value != null || currentField.getBeanStringPopulator().getType().isPrimitive()){ resultSetField.getBeanField().set(bean, currentField.getBeanStringPopulator().getValue(value)); }else{ resultSetField.getBeanField().set(bean, null); } } } return bean; } catch (InstantiationException e) { throw new BeanResultSetPopulationException(currentField,e); } catch (IllegalAccessException e) { throw new BeanResultSetPopulationException(currentField,e); } catch (IllegalArgumentException e) { throw new BeanResultSetPopulationException(currentField,e); } catch (InvocationTargetException e) { throw new BeanResultSetPopulationException(currentField,e); } } public ResultSetField getResultSetField(Field field){ return this.resultSetFieldMap.get(field); } }