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

win.doyto.query.core.CrudBuilder Maven / Gradle / Ivy

package win.doyto.query.core;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import win.doyto.query.entity.Persistable;

import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.persistence.Id;

import static win.doyto.query.core.CommonUtil.*;
import static win.doyto.query.core.Constant.*;

/**
 * CrudBuilder
 *
 * @author f0rb
 */
@SuppressWarnings("squid:CommentedOutCodeLine")
@Slf4j
final class CrudBuilder extends QueryBuilder {

    private final Field idField;
    private final List fields;
    private final int fieldsSize;
    private final boolean isDynamicTable;
    private final String wildInsertValue;   // ?, ?, ?
    private final String insertColumns;
    private final String wildSetClause;     // column1 = ?, column2 = ?

    public CrudBuilder(Class entityClass) {
        super(entityClass);
        idField = FieldUtils.getFieldsWithAnnotation(entityClass, Id.class)[0];

        isDynamicTable = isDynamicTable(tableName);

        // init fields
        Field[] allFields = FieldUtils.getAllFields(entityClass);
        List tempFields = new ArrayList<>(allFields.length);
        Arrays.stream(allFields).filter(field -> !ignoreField(field)).forEachOrdered(tempFields::add);
        fields = Collections.unmodifiableList(tempFields);
        fieldsSize = fields.size();

        wildInsertValue = wrapWithParenthesis(StringUtils.join(IntStream.range(0, fieldsSize).mapToObj(i -> Constant.REPLACE_HOLDER).collect(Collectors.toList()), Constant.SEPARATOR));

        List columnList = fields.stream().map(CommonUtil::resolveColumn).collect(Collectors.toList());
        insertColumns = wrapWithParenthesis(StringUtils.join(columnList, Constant.SEPARATOR));
        wildSetClause = StringUtils.join(columnList.stream().map(c -> c + EQUALS_REPLACE_HOLDER).collect(Collectors.toList()), Constant.SEPARATOR);

    }

    private static String buildInsertSql(String table, String columns, String fields) {
        ArrayList insertList = new ArrayList<>();
        insertList.add("INSERT INTO");
        insertList.add(table);
        insertList.add(columns);
        insertList.add("VALUES");
        insertList.add(fields);
        return StringUtils.join(insertList, SPACE);
    }

    private static String buildUpdateSql(String tableName, String setClauses) {
        ArrayList updateList = new ArrayList<>();
        updateList.add("UPDATE");
        updateList.add(tableName);
        updateList.add("SET");
        updateList.add(setClauses);
        return StringUtils.join(updateList, SPACE);
    }

    private static void readValueToArgList(List fields, Object entity, List argList) {
        fields.stream().map(field -> readFieldGetter(field, entity)).forEach(argList::add);
    }

    private static void readValueToArgList(List fields, Object entity, List argList, List setClauses) {
        for (Field field : fields) {
            Object o = readFieldGetter(field, entity);
            if (o != null) {
                setClauses.add(resolveColumn(field) + EQUALS_REPLACE_HOLDER);
                argList.add(o);
            }
        }
    }

    private String resolveTableName(E entity) {
        return isDynamicTable ? replaceHolderInString(entity, tableName) : tableName;
    }

    public String buildCreateAndArgs(E entity, List argList) {
        String table = resolveTableName(entity);
        readValueToArgList(fields, entity, argList);
        return buildInsertSql(table, insertColumns, wildInsertValue);
    }

    public SqlAndArgs buildCreateAndArgs(Iterable entities, String... columns) {
        StringBuilder insertSql = new StringBuilder(buildInsertSql(tableName, insertColumns, wildInsertValue));

        ArrayList argList = new ArrayList<>();
        Iterator iterator = entities.iterator();
        E next = iterator.next();
        readValueToArgList(fields, next, argList);
        while (iterator.hasNext()) {
            E entity = iterator.next();
            readValueToArgList(fields, entity, argList);
            insertSql.append(SEPARATOR).append(wildInsertValue);
        }
        if (columns.length > 0) {
            insertSql.append(" ON DUPLICATE KEY UPDATE ");
            StringJoiner stringJoiner = new StringJoiner(", ", columns.length);
            for (String column : columns) {
                stringJoiner.append(column + EQUAL + "VALUES (" + column + ")");
            }
            insertSql.append(stringJoiner.toString());
        }

        String sql = replaceHolderInString(next, insertSql.toString());
        return new SqlAndArgs(sql, argList);
    }

    public String buildUpdateAndArgs(E entity, List argList) {
        String table = resolveTableName(entity);
        readValueToArgList(fields, entity, argList);
        argList.add(readField(idField, entity));
        return buildUpdateSql(table, wildSetClause) + whereId;
    }

    public SqlAndArgs buildUpdateAndArgs(E entity) {
        ArrayList argList = new ArrayList<>();
        return new SqlAndArgs(buildUpdateAndArgs(entity, argList), argList);
    }

    public String buildPatchAndArgs(E entity, List argList) {
        String table = resolveTableName(entity);
        List setClauses = new ArrayList<>(fieldsSize);
        readValueToArgList(fields, entity, argList, setClauses);
        return buildUpdateSql(table, StringUtils.join(setClauses, Constant.SEPARATOR));
    }

    public String buildPatchAndArgsWithId(E entity, List argList) {
        String sql = buildPatchAndArgs(entity, argList) + whereId;
        argList.add(readField(idField, entity));
        return sql;
    }

    public SqlAndArgs buildPatchAndArgsWithId(E entity) {
        ArrayList argList = new ArrayList<>();
        return new SqlAndArgs(buildPatchAndArgsWithId(entity, argList), argList);
    }

    public String buildPatchAndArgsWithQuery(E entity, Object query, List argList) {
        String sql = buildPatchAndArgs(entity, argList);
        return buildWhere(sql, query, argList);
    }

    public SqlAndArgs buildPatchAndArgsWithQuery(E entity, Object query) {
        ArrayList argList = new ArrayList<>();
        String sql = buildPatchAndArgsWithQuery(entity, query, argList);
        return new SqlAndArgs(sql, argList);
    }

    public String buildDeleteAndArgs(PageQuery query, List argList) {
        return build(query, argList, "DELETE", new String[0], tableName);
    }

    public SqlAndArgs buildDeleteAndArgs(PageQuery query) {
        ArrayList argList = new ArrayList<>();
        return new SqlAndArgs(buildDeleteAndArgs(query, argList), argList);
    }

    public String buildDeleteById() {
        return "DELETE FROM " + tableName + whereId;
    }

    protected String buildDeleteById(Object entity) {
        return "DELETE FROM " + replaceHolderInString(entity, tableName) + whereId;
    }
}