package org.jboss.capedwarf.common.dto; import java.io.Serializable; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; /** * Default DTO model. * * @author <a href="mailto:ales.justin@jboss.org">Ales Justin</a> */ public class DefaultDTOModel<U extends Serializable> implements DTOModel<U> { private Class<U> entityClass; private boolean needsClassName; private Method idMethod; private Class<?> dto; private Map<Method, Method> properties; private Map<String, ValueConverter> converters; public DefaultDTOModel(Class<U> entityClass) { if (entityClass == null) throw new IllegalArgumentException("Null entity class"); this.entityClass = entityClass; init(); } private void init() { DTOClass dtoc = entityClass.getAnnotation(DTOClass.class); if (dtoc == null) throw new IllegalArgumentException("No such DTOClass: " + entityClass); this.dto = dtoc.value(); needsClassName = dtoc.needsClassName(); try { idMethod = entityClass.getMethod("getId"); if (idMethod.getReturnType() != Long.class) idMethod = null; // ignore non Long id } catch (Throwable ignored) { } try { properties = new HashMap<Method, Method>(); converters = new HashMap<String, ValueConverter>(); resolve(entityClass); } catch (Exception e) { throw new RuntimeException(e); } } private void resolve(Class<?> clazz) throws Exception { Method[] methods = clazz.getMethods(); for (Method m : methods) { DTOProperty dtop = m.getAnnotation(DTOProperty.class); if (dtop != null) { String name = m.getName(); if (name.startsWith("get") == false && name.startsWith("is") == false) throw new IllegalArgumentException("Not a getter method: " + m); if (converters.containsKey(name) == false) { String dp = dtop.property(); String pn; if (dp != null && dp.length() > 0) { pn = dp; } else { if (name.startsWith("is")) pn = "set" + name.substring(2); // is else pn = "s" + name.substring(1); //get } Method dtoM = dto.getMethod(pn); properties.put(m, dtoM); ValueConverter vc = getVC(dtop); converters.put(name, vc); } } } } private ValueConverter getVC(DTOProperty dtop) throws Exception { Class<? extends ValueConverter> vcc = dtop.converter(); if (vcc == NoopValueConverter.class) return NoopValueConverter.INSTANCE; else if (vcc == StringValueConverter.class) return StringValueConverter.INSTANCE; return vcc.newInstance(); } @SuppressWarnings({"unchecked"}) public Object toDTO(U entity) { try { Object dtoInstance = dto.newInstance(); if (dtoInstance instanceof Identity) { Identity identity = (Identity) dtoInstance; if (needsClassName) identity.setClassName(entityClass.getName()); if (idMethod != null) identity.setId((Long) idMethod.invoke(entity)); } for (Method key : properties.keySet()) { Method dtoProperty = properties.get(key); ValueConverter vc = converters.get(key.getName()); Object value = vc.convert(key.invoke(entity)); dtoProperty.invoke(dtoInstance, value); } return dtoInstance; } catch (Exception e) { throw new RuntimeException(e); } } }