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

cn.mybatisboost.nosql.MethodNameParser Maven / Gradle / Ivy

The newest version!
package cn.mybatisboost.nosql;

import cn.mybatisboost.util.SqlUtils;
import cn.mybatisboost.util.tuple.BinaryTuple;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.RowBounds;

import java.util.*;
import java.util.regex.Pattern;

public class MethodNameParser {

    private static final Pattern PATTERN_ORDER_BY_SEPARATOR = Pattern.compile(" (?!ASC|DESC)");

    private final String methodName, tableName;
    private final boolean mapUnderscoreToCamelCase;
    private String parsedSql;
    private int offset, limit;

    public MethodNameParser(String methodName, String tableName, boolean mapUnderscoreToCamelCase) {
        this.methodName = methodName;
        this.tableName = tableName;
        this.mapUnderscoreToCamelCase = mapUnderscoreToCamelCase;
    }

    public String toSql() {
        if (parsedSql != null) return parsedSql;
        StringBuilder sqlBuilder = new StringBuilder();
        Method method = Method.of(StringUtils.capitalize(methodName));
        sqlBuilder.append(method.sqlFragment()).append(' ').append(tableName).append(' ');

        String expression = this.methodName.substring(method.name().length());
        expression = prepare(sqlBuilder, expression);
        if (expression.isEmpty()) {
            return parsedSql = sqlBuilder.toString().trim();
        }

        Map keywordMap = new TreeMap<>();
        for (String kw : Predicate.keywords()) {
            int index = -1;
            while ((index = expression.indexOf(kw, index + 1)) >= 0) {
                if (index + kw.length() == expression.length() ||
                        Character.isUpperCase(expression.charAt(index + kw.length()))) {
                    keywordMap.put(index, kw);
                }
            }
        }
        for (String it : keywordMap.values()) {
            expression = expression.replace(it, "?");
        }

        int offset = 0, predicateIndex;
        Iterator iterator = keywordMap.values().iterator();
        boolean containsOrderBy = false;
        int orderByIndex = 0;
        while ((predicateIndex = expression.indexOf("?", offset)) >= 0) {
            Predicate predicate = Predicate.of(iterator.next());

            if (predicateIndex > offset) {
                sqlBuilder.append(SqlUtils.normalizeColumn
                        (expression.substring(offset, predicateIndex), mapUnderscoreToCamelCase)).append(' ');
                if (!predicate.containsParameters()) {
                    sqlBuilder.append("= ? ");
                }
            }
            sqlBuilder.append(predicate.sqlFragment()).append(' ');
            offset = predicateIndex + 1;

            if (predicate == Predicate.OrderBy) {
                containsOrderBy = true;
                orderByIndex = sqlBuilder.length();
            }
        }
        if (offset < expression.length() - 1) {
            sqlBuilder.append(SqlUtils.normalizeColumn
                    (expression.substring(offset), mapUnderscoreToCamelCase));
            if (!containsOrderBy) {
                sqlBuilder.append(" = ?");
            }
        }
        if (containsOrderBy) {
            String correctedOrderByExpression = PATTERN_ORDER_BY_SEPARATOR.matcher
                    (sqlBuilder.substring(orderByIndex).trim()).replaceAll(", ");
            sqlBuilder.replace(orderByIndex, sqlBuilder.length(), correctedOrderByExpression);
        }
        return parsedSql = sqlBuilder.toString().trim();
    }

    public RowBounds toRowBounds() {
        if (parsedSql == null) toSql();
        return offset > 0 || limit > 0 ? new RowBounds(offset, limit) : RowBounds.DEFAULT;
    }

    private String prepare(StringBuilder sqlBuilder, String expression) {
        if (expression.startsWith("All")) {
            expression = expression.substring(3);
        } else {
            if (expression.startsWith("First")) {
                limit = 1;
                expression = expression.substring(5);
            } else if (expression.startsWith("Top")) {
                Optional> optional =
                        extractKeyNumber(expression, "Top", false);
                if (optional.isPresent()) {
                    BinaryTuple tuple = optional.get();
                    limit = tuple.second();
                    expression = tuple.first();
                }
            }
        }
        if (expression.startsWith("By")) {
            sqlBuilder.append("WHERE ");
            expression = expression.substring(2);
        }

        Optional> optional =
                extractKeyNumber(expression, "Limit", true);
        if (optional.isPresent()) {
            BinaryTuple tuple = optional.get();
            limit = tuple.second();
            expression = tuple.first();

            optional = extractKeyNumber(expression, "Offset", true);
            if (optional.isPresent()) {
                tuple = optional.get();
                offset = tuple.second();
                expression = tuple.first();
            }
        }
        return expression;
    }

    private Optional> extractKeyNumber(String s, String key, boolean fromEnd) {
        int index = fromEnd ? s.lastIndexOf(key) : s.indexOf(key);
        if (index < 0) return Optional.empty();

        char[] chars = s.toCharArray();
        for (int i = index + key.length(); i < chars.length; i++) {
            if (!Character.isDigit(chars[i]) || i + 1 == chars.length) {
                if (i + 1 == chars.length) i++;
                char[] copy = Arrays.copyOfRange(chars, index + key.length(), i);
                return Optional.of(new BinaryTuple<>
                        (new StringBuilder(s).replace(index, i, "").toString(),
                                Integer.parseInt(new String(copy))));
            }
        }
        throw new IllegalArgumentException("Invalid string");
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy