
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