package net.codjo.dataprocess.server.handler.handlerfactory; import net.codjo.database.api.Database; import net.codjo.database.api.query.PreparedQuery; import net.codjo.dataprocess.common.table.annotations.Arg; import net.codjo.dataprocess.common.table.annotations.QueryFactory; import net.codjo.dataprocess.common.table.annotations.Type; import net.codjo.dataprocess.common.table.model.TableModel; import net.codjo.mad.server.handler.Handler; import net.codjo.mad.server.handler.HandlerException; import net.codjo.mad.server.handler.sql.Getter; import net.codjo.mad.server.handler.sql.QueryBuilder; import net.codjo.mad.server.handler.sql.SqlHandler; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.picocontainer.MutablePicoContainer; /** * */ public class QueryHandlerFactory extends AbstractHandlerFactory { private Class<?> clazz; private Method method; public QueryHandlerFactory(MutablePicoContainer container, Class<?> clazz, Method method, TableModel tableModel) { super(container, tableModel); this.clazz = clazz; this.method = method; } public String getHandlerId() { QueryFactory queryFactory = method.getAnnotation(QueryFactory.class); net.codjo.dataprocess.common.table.annotations.Handler handlerAnno = clazz.getAnnotation(net.codjo.dataprocess.common.table.annotations.Handler.class); String part1 = handlerAnno.value(); String part2 = queryFactory.value().length() == 0 ? method.getName() : queryFactory.value(); return part1 + (part1.length() != 0 ? "." : "") + part2; } public Handler createHandler() { getContainer().registerComponentImplementation(getHandlerId(), clazz); Object componentInstance = getContainer().getComponentInstance(getHandlerId()); return new MySqlHandler(componentInstance, method, getTableModel(), getDatabase()); } private class MySqlHandler extends SqlHandler { private Method method; private Object object; MySqlHandler(Object object, Method method, TableModel tableModel, Database database) { super(tableModel.getPkAsStrArray(), "", database); this.object = object; this.method = method; int idx = 1; for (String attribute : getAttributes(method)) { addGetter(attribute, new Getter(idx++)); } } @Override protected void fillQuery(PreparedQuery query, Map<String, String> args) throws SQLException { int idx = 1; for (Arg argAnno : getArgAnnotations(method)) { if (argAnno.type() != Type.UNDEFINED) { query.setObject(idx++, args.get(argAnno.value()), argAnno.type().getSqlType()); } } } @Override protected String buildQuery(Map<String, String> arguments) throws HandlerException { return new MyQueryBuilder().buildQuery(arguments, this); } private class MyQueryBuilder implements QueryBuilder { public String buildQuery(Map<String, String> args, SqlHandler sqlHandler) throws HandlerException { try { return (String)method.invoke(object, getMethodArguments(method, args, sqlHandler)); } catch (Exception ex) { throw new HandlerException(ex); } } private Object[] getMethodArguments(Method method, Map<String, String> arguments, SqlHandler sqlHandler) { List<Object> values = new ArrayList<Object>(); Annotation[][] parameterAnnotations = method.getParameterAnnotations(); Class<?>[] parameterTypes = method.getParameterTypes(); int ii = 0; for (Annotation[] annotations : parameterAnnotations) { Class<?> parameterType = parameterTypes[ii++]; if (annotations.length > 0) { for (Annotation annotation : annotations) { if (annotation instanceof Arg) { Arg argAnno = (Arg)annotation; values.add(arguments.get(argAnno.value())); } } } else { if (parameterType.isAssignableFrom(SqlHandler.class)) { values.add(sqlHandler); } else { values.add(null); } } } return values.toArray(); } } } }