All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.smart.data.repository.builder.QueryBuilder Maven / Gradle / Ivy

There is a newer version: 4.0.14-RELEASE
Show newest version
package org.smart.data.repository.builder;

import org.apache.log4j.Logger;
import org.smart.data.repository.annotaion.ColumnName;
import org.smart.data.repository.annotaion.IdField;
import org.smart.data.repository.annotaion.TableName;
import org.smart.data.repository.builder.service.BuilderService;
import org.smart.data.repository.builder.service.SearchCriteria;
import org.smart.data.repository.builder.service.SqlStringBuilder;
import org.smart.data.repository.util.Objects;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

import static org.smart.data.repository.builder.service.SqlStringBuilder.INSERT_QUERY_CLEANER;
import static org.smart.data.repository.builder.service.SqlStringBuilder.SELECT_UPDATE_QUERY_CLEANER;

/**
 * @author Ranzy Blessings (2017/05/30)
 */
public final class QueryBuilder implements Serializable {

    private String query;
    private final String $like = "$like";
    private final Logger LOG = Logger.getLogger(QueryBuilder.class);
    private Predicate contains$Like = (value) -> (value.contains($like));

    public QueryBuilder(String query) {
        this.query = query;
    }

    public static  QueryBuilder insert(T values) {
        return new QueryBuilder(createInsertQuery(values, values.getClass()));
    }

    private static  String createInsertQuery(T t, Class tClass) {
        String tableName = tClass.getAnnotation(TableName.class).value();
        List columns = BuilderService.getColumnNames(tClass, false);
        List fieldValues = new ArrayList();
        BuilderService.getFieldValues(t, fieldValues);
        return INSERT_QUERY_CLEANER(String.format(SqlStringBuilder.INSERT, tableName, columns, fieldValues));
    }

    public static  QueryBuilder update(T values, SearchCriteria criteria) {
        return new QueryBuilder(createUpdateQuery(values, criteria.getQuery(), values.getClass()));
    }

    private static  String createUpdateQuery(T t, Serializable criteria, Class tClass) {
        String tableName = tClass.getAnnotation(TableName.class).value();
        List fieldValueStore = new ArrayList();
        List columnAndValueList = new ArrayList();
        int fieldValueIndex = 0;
        getDeclaredFieldsForUpdate(t, fieldValueStore, fieldValueIndex, columnAndValueList);
        return SELECT_UPDATE_QUERY_CLEANER(String.format(SqlStringBuilder.UPDATE, tableName, columnAndValueList, criteria));
    }

    private static  void getDeclaredFieldsForUpdate(T t,
                                                       List fieldValues,
                                                       int fieldValueIndex,
                                                       List columnNames) {
        final Class aClass = t.getClass();
        for (Field field : aClass.getDeclaredFields()) {
            ColumnName column = field.getAnnotation(ColumnName.class);
            BuilderService.getFieldValues(t, fieldValues);
            if (Objects.notNull(column) && !field.isAnnotationPresent(IdField.class)) {
                columnNames.add(String.format(String.format("%%s = %s", fieldValues.get(fieldValueIndex++)), column.value()));
            }
        }
    }

    public static  QueryBuilder select(Class tClass) {
        return new QueryBuilder(createSelectQuery(tClass, false));
    }

    public static  QueryBuilder selectDistinct(Class tClass) {
        return new QueryBuilder(createSelectQuery(tClass, true));
    }

    private static  String createSelectQuery(Class tClass, boolean isDistinct) {
        final String tableName = tClass.getAnnotation(TableName.class).value();
        List columns = BuilderService.getColumnNames(tClass, true);
        return (isDistinct) ?
                SELECT_UPDATE_QUERY_CLEANER(String.format(SqlStringBuilder.SELECT_DISTINCT, selectHelper(columns, tableName))) :
                SELECT_UPDATE_QUERY_CLEANER(String.format(SqlStringBuilder.SELECT, selectHelper(columns, tableName)));
    }

    private static String selectHelper(List columns, String tableName) {
        return String.format(SqlStringBuilder.FROM, columns.toString(), tableName);
    }

    public QueryBuilder orderByDesc(Serializable field) {
        this.query = String.format(SqlStringBuilder.ORDER_BY_DESC, this.query, field);
        return new QueryBuilder(query);
    }

    public QueryBuilder orderByAsc(Serializable field) {
        this.query = String.format(SqlStringBuilder.ORDER_BY_ASC, this.query, field);
        return new QueryBuilder(query);
    }

    public QueryBuilder where(String column, Serializable value) {
        String query = contains$Like.test(value.toString()) ?
                likeQuery(column, value.toString()) :
                equalsQuery(column, value.toString());
        return new QueryBuilder(query);
    }

    private String likeQuery(String column, String value) {
        String $likeValue = value.substring(0, value.indexOf($like));
        return this.query = String.format(SqlStringBuilder.LIKE, this.query, column, $likeValue.toLowerCase());
    }

    private String equalsQuery(String column, String value) {
        return this.query = String.format(SqlStringBuilder.WHERE, this.query, column, value.toLowerCase());
    }

    public QueryBuilder limit(int number) {
        this.query = String.format(SqlStringBuilder.LIMIT, this.query, number);
        return new QueryBuilder(query);
    }

    public QueryBuilder and(String column, Serializable value) {
        final Serializable incomingValue = andHelper(value);
        String query = contains$Like.test(value.toString()) ?
                String.format(SqlStringBuilder.AND_LIKE, this.query, column, incomingValue) :
                String.format(SqlStringBuilder.AND, this.query, column, value);
        return new QueryBuilder(query);
    }

    private Serializable andHelper(Serializable value) {
        return contains$Like.test(value.toString()) ?
                value.toString().substring(0, value.toString().indexOf($like)) :
                value;
    }

    public QueryBuilder andOp(String column, Serializable serializable) {
        String query = String.format(SqlStringBuilder.AND_OP, this.query, column, serializable.toString());
        return new QueryBuilder(query);
    }

    public QueryBuilder orCp(String column, Serializable serializable) {
        String query = String.format(SqlStringBuilder.OR_CP, this.query, column, serializable.toString());
        return new QueryBuilder(query);
    }

    public QueryBuilder or(String column, Serializable value) {
        this.query = String.format(SqlStringBuilder.OR, query, column, value.toString().toLowerCase());
        return new QueryBuilder(query);
    }

    public static  QueryBuilder delete(Class tClass, SearchCriteria searchCriteria) {
        return new QueryBuilder(createDeleteQuery(searchCriteria, tClass));
    }

    private static  String createDeleteQuery(SearchCriteria searchCriteria, Class tClass) {
        String tableName = tClass.getAnnotation(TableName.class).value();
        return String.format(SqlStringBuilder.DELETE, tableName, searchCriteria.getQuery());
    }

    public String build() {
        LOG.info(String.format("%s\n", query));
        return String.format("%s;", this.query);
    }
}