package com.ctp.cdi.query.meta; import java.io.Serializable; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.jboss.solder.logging.Logger; import org.jboss.solder.reflection.AnnotationInstanceProvider; import com.ctp.cdi.query.WithEntityManager; import com.ctp.cdi.query.util.EntityUtils; /** * Stores information about a specific DAO. Extracts information about: * <ul> * <li>The DAO class</li> * <li>The target entity the DAO is for</li> * <li>The primary key class</li> * <li>All methods of the DAO.</li> * </ul> * * @author thomashug */ public class DaoComponent { private final Logger log = Logger.getLogger(DaoComponent.class); private final Class<?> daoClass; private final DaoEntity entityClass; private Annotation[] qualifiers; private final Map<Method, DaoMethod> methods = new HashMap<Method, DaoMethod>(); public DaoComponent(Class<?> daoClass, DaoEntity entityClass) { if (entityClass == null) { throw new IllegalArgumentException("Entity class cannot be null"); } this.daoClass = daoClass; this.entityClass = entityClass; initialize(); } public String getEntityName() { return EntityUtils.entityName(entityClass.getEntityClass()); } /** * Looks up method meta data by a Method object. * @param method The DAO method. * @return Method meta data. */ public DaoMethod lookupMethod(Method method) { return methods.get(method); } /** * Looks up the method type by a Method object. * @param method The DAO method. * @return Method meta data. */ public MethodType lookupMethodType(Method method) { return lookupMethod(method).getMethodType(); } /** * Gets the entity class related the DAO. * @return The class of the entity related to the DAO. */ public Class<?> getEntityClass() { return entityClass.getEntityClass(); } /** * Gets the entity primary key class related the DAO. * @return The class of the entity primary key related to the DAO. */ public Class<? extends Serializable> getPrimaryKey() { return entityClass.getPrimaryClass(); } /** * Returns the original DAO class this meta data is related to. * @return The class of the DAO. */ public Class<?> getDaoClass() { return daoClass; } /** * Returns qualifiers for selecting an entity manager for the DAO component. * @return A list of annotations, empty when using the default entity manager. */ public Annotation[] getEntityManagerQualifiers() { return Arrays.copyOf(qualifiers, qualifiers.length); } private void initialize() { Collection<Class<?>> allImplemented = collectClasses(); for (Class<?> implemented : allImplemented) { Method[] daoClassMethods = implemented.getDeclaredMethods(); for (Method daoClassMethod : daoClassMethods) { DaoMethod daoMethod = new DaoMethod(daoClassMethod, this); methods.put(daoClassMethod, daoMethod); } } if (daoClass.isAnnotationPresent(WithEntityManager.class)) { Class<? extends Annotation>[] annotations = daoClass.getAnnotation(WithEntityManager.class).value(); qualifiers = new Annotation[annotations.length]; AnnotationInstanceProvider provider = new AnnotationInstanceProvider(); for (int i = 0; i < annotations.length; i++) { Class<? extends Annotation> clazz = annotations[i]; qualifiers[i] = provider.get(clazz, new HashMap<String, Object>()); } } else { qualifiers = new Annotation[] {}; } } private Set<Class<?>> collectClasses() { Set<Class<?>> result = new HashSet<Class<?>>(); Class<?> current = daoClass; while (!Object.class.equals(current) && current != null) { result.add(current); Class<?>[] interfaces = current.getInterfaces(); if (interfaces != null) { result.addAll(Arrays.asList(interfaces)); } current = current.getSuperclass(); } log.debugv("collectClasses(): Found {0} for {1}", result, daoClass); return result; } }