package com.ctp.cdi.query.param; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.persistence.Query; import org.jboss.solder.logging.Logger; import com.ctp.cdi.query.FirstResult; import com.ctp.cdi.query.MaxResults; import com.ctp.cdi.query.QueryParam; /** * Convenience class to manage method and query parameters. * @author thomashug */ public final class Parameters { private static final Logger LOG = Logger.getLogger(Parameters.class); private static final int DEFAULT_MAX = 0; private static final int DEFAULT_FIRST = -1; private final List<Parameter> parameterList; private final int max; private final int firstResult; private Parameters(List<Parameter> parameters, int max, int firstResult) { this.parameterList = parameters; this.max = max; this.firstResult = firstResult; } public static Parameters createEmpty() { List<Parameter> empty = Collections.emptyList(); return new Parameters(empty, DEFAULT_MAX, DEFAULT_FIRST); } public static Parameters create(Method method, Object[] parameters) { int max = extractSizeRestriction(method); int first = DEFAULT_FIRST; List<Parameter> result = new ArrayList<Parameter>(parameters.length); int paramIndex = 1; Annotation[][] annotations = method.getParameterAnnotations(); for (int i = 0; i < parameters.length; i++) { if (isParameter(method.getParameterAnnotations()[i])) { QueryParam qpAnnotation = extractFrom(annotations[i], QueryParam.class); if (qpAnnotation != null) { result.add(new NamedParameter(qpAnnotation.value(), parameters[i], i)); } else { result.add(new IndexedParameter(paramIndex++, parameters[i], i)); } } else { max = extractInt(parameters[i], annotations[i], MaxResults.class, max); first = extractInt(parameters[i], annotations[i], FirstResult.class, first); } } return new Parameters(result, max, first); } public Query applyTo(Query query) { for (Parameter param : parameterList) { param.apply(query); } return query; } public boolean hasSizeRestriction() { return max > DEFAULT_MAX; } public int getSizeRestriciton() { return max; } public boolean hasFirstResult() { return firstResult > DEFAULT_FIRST; } public int getFirstResult() { return firstResult; } private static int extractSizeRestriction(Method method) { if (method.isAnnotationPresent(com.ctp.cdi.query.Query.class)) { return method.getAnnotation(com.ctp.cdi.query.Query.class).max(); } return 0; } @SuppressWarnings("unchecked") private static <A extends Annotation> A extractFrom(Annotation[] annotations, Class<A> target) { for (Annotation annotation : annotations) { if (annotation.annotationType().isAssignableFrom(target)) { return (A) annotation; } } return null; } private static <A extends Annotation> int extractInt(Object parameter, Annotation[] annotations, Class<A> target, int defaultVal) { if (parameter != null) { A result = extractFrom(annotations, target); if (result != null) { if (parameter instanceof Integer) { return (Integer) parameter; } else { LOG.warnv("Method parameter extraction: Param type must be int: {0}->is:{1}", target, parameter.getClass()); } } } return defaultVal; } private static boolean isParameter(Annotation[] annotations) { return extractFrom(annotations, MaxResults.class) == null && extractFrom(annotations, FirstResult.class) == null; } }