package ddth.dasp.framework.bo; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.commons.lang3.text.WordUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Use this class as starting point for Business Object implementation. * * @author NBThanh <btnguyen2k@gmail.com> * @version 0.1.0 */ public abstract class BaseBo implements IBo { private Logger LOGGER = LoggerFactory.getLogger(BaseBo.class); private Map<String, Object[]> dataMappings; /** * Sets BO data mappings. * * @param dataMappings * @see IBo#getDataMappings() */ public void setDataMappings(Map<String, Object[]> dataMappings) { this.dataMappings = dataMappings; } /** * {@inheritDoc} */ @Override public Map<String, Object[]> getDataMappings() { return dataMappings; } protected Boolean toBoolean(Object value) { if (value == null) { return null; } if (value instanceof Number) { return ((Number) value).doubleValue() != 0.0; } if (value instanceof Character) { char c = ((Character) value).charValue(); return c == 'Y' || c == 'y' || c == 'T' || c == 't'; } if (value instanceof String) { return "YES".equalsIgnoreCase(value.toString()) || "Y".equalsIgnoreCase(value.toString()) || "TRUE".equalsIgnoreCase(value.toString()) || "T".equalsIgnoreCase(value.toString()); } return Boolean.parseBoolean(value.toString()); } protected Character toCharacter(Object value) { if (value == null) { return null; } String str = value.toString(); return str.length() > 0 ? str.charAt(0) : null; } /** * {@inheritDoc} */ @Override public void populate(Map<String, ?> data) { Map<String, Object[]> dataMappings = getDataMappings(); if (dataMappings == null) { populateWithAnnotations(data); } else { populateWithDataMappings(data, dataMappings); } } protected void populateWithAnnotations(Map<String, ?> data) { Class<?> clazz = this.getClass(); Class<? extends Annotation> annoClazz = FieldMapping.class; while (clazz != Object.class) { final List<Method> allMethods = new ArrayList<Method>(Arrays.asList(clazz .getDeclaredMethods())); for (final Method method : allMethods) { if (method.isAnnotationPresent(annoClazz)) { FieldMapping annotation = (FieldMapping) method.getAnnotation(annoClazz); String field = annotation.field(); Object value = data.get(field); if (value == null) { String msg = "Found setter method [" + method.getName() + "] for field [" + field + "], but no value fould!"; LOGGER.warn(msg); } else { if (!annotation.type().isAssignableFrom(value.getClass())) { String msg = "Value of type [" + value.getClass() + "] mismatches [" + annotation.type() + "]!"; throw new RuntimeException(msg); } else { try { method.invoke(this, value); } catch (Exception e) { if (e instanceof RuntimeException) { throw (RuntimeException) e; } else { throw new RuntimeException(e); } } } } } } clazz = clazz.getSuperclass(); } } protected void populateWithDataMappings(Map<String, ?> data, Map<String, Object[]> dataMappings) { Class<?> myClass = getClass(); for (Entry<String, Object[]> entry : dataMappings.entrySet()) { String externalField = entry.getKey(); Object[] boInfo = entry.getValue(); String boAttr = boInfo[0].toString(); Class<?> boAttrType = (Class<?>) boInfo[1]; Object boValue = data.get(externalField); if ((boAttrType == boolean.class || boAttrType == Boolean.class) && !(boValue instanceof Boolean)) { boValue = toBoolean(boValue); } else if ((boAttrType == char.class || boAttrType == Character.class) && !(boValue instanceof Character)) { boValue = toCharacter(boValue); } String methodName = "set" + WordUtils.capitalize(boAttr); if (LOGGER.isDebugEnabled()) { String msg = "Calling method " + methodName + "(" + boValue + ") to populate db column [" + externalField + "]."; LOGGER.debug(msg); } try { // Method method = myClass.getDeclaredMethod(methodName, // boAttrType); Method method = myClass.getMethod(methodName, boAttrType); if (method != null) { method.setAccessible(true); method.invoke(this, boValue); } else { LOGGER.warn("No setter method found [" + methodName + "] for class [" + myClass + "]!"); } } catch (Exception e) { LOGGER.error(e.getMessage(), e); throw new RuntimeException(e); } } } }