io.lavagna.common.QueryFactory.java Source code

Java tutorial

Introduction

Here is the source code for io.lavagna.common.QueryFactory.java

Source

/**
 * This file is part of lavagna.
 *
 * lavagna is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * lavagna is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with lavagna.  If not, see <http://www.gnu.org/licenses/>.
 */
package io.lavagna.common;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.util.Assert;

public class QueryFactory {

    private final String activeDb;
    private final NamedParameterJdbcTemplate jdbc;

    public QueryFactory(String activeDB, NamedParameterJdbcTemplate jdbc) {
        this.activeDb = activeDB;
        this.jdbc = jdbc;
    }

    public static <T> T from(final Class<T> clazz, final String activeDb) {
        return from(clazz, activeDb, null);
    }

    private static class QueryTypeAndQuery {
        private final QueryType type;
        private final String query;

        QueryTypeAndQuery(QueryType type, String query) {
            this.type = type;
            this.query = query;
        }
    }

    @SuppressWarnings("unchecked")
    private static <T> T from(final Class<T> clazz, final String activeDb, final NamedParameterJdbcTemplate jdbc) {
        return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[] { clazz }, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                QueryTypeAndQuery qs = extractQueryAnnotation(clazz, activeDb, method);
                return qs.type.apply(qs.query, jdbc, method, args);
            }
        });
    }

    private static QueryTypeAndQuery extractQueryAnnotation(Class<?> clazz, String activeDb, Method method) {
        Query q = method.getAnnotation(Query.class);
        QueriesOverride qs = method.getAnnotation(QueriesOverride.class);

        Assert.isTrue(q != null, String.format("missing @Query annotation for method %s in interface %s",
                method.getName(), clazz.getSimpleName()));
        // only one @Query annotation, thus we return the value without checking the database
        if (qs == null) {
            return new QueryTypeAndQuery(q.type(), q.value());
        }

        for (QueryOverride query : qs.value()) {
            if (query.db().equals(activeDb)) {
                return new QueryTypeAndQuery(q.type(), query.value());
            }
        }

        return new QueryTypeAndQuery(q.type(), q.value());
    }

    public <T> T from(final Class<T> clazz) {
        return from(clazz, activeDb, jdbc);
    }

}