LikeOpHandler.java

package com.github.mygreen.sqlmapper.core.where.metamodel;

import java.util.Optional;

import com.github.mygreen.sqlmapper.core.util.QueryUtils;
import com.github.mygreen.sqlmapper.metamodel.Visitor;
import com.github.mygreen.sqlmapper.metamodel.expression.Constant;
import com.github.mygreen.sqlmapper.metamodel.expression.Expression;
import com.github.mygreen.sqlmapper.metamodel.operation.Operation;
import com.github.mygreen.sqlmapper.metamodel.operator.LikeOp;

/**
 * LIKE演算子({@link LikeOp})に対する処理を定義します。
 *
 *
 * @author T.TSUCHIE
 *
 */
public class LikeOpHandler extends OperationHandler<LikeOp>{

    /**
     * デフォルトのLIKEエスケープ文字
     */
    private static char DEFAULT_LIKE_ESCAPE = '\\';

    @Override
    protected void init() {
        // 何もしない
    }

    @SuppressWarnings("unchecked")
    @Override
    public void handle(LikeOp operator, Operation<?> expr, Visitor<VisitorContext> visitor, VisitorContext context) {

        Expression<?> left = expr.getArg(0);
        Expression<?> right = expr.getArg(1);
        Optional<Expression<?>> escapeExp = expr.getOptArg(2);
        char escape = escapeExp.map(e -> ((Constant<Character>)e).getValue()).orElse(DEFAULT_LIKE_ESCAPE);

        if(right instanceof Constant) {
            String text = ((Constant<?>)right).getValue().toString();

            switch(operator) {
                case CONTAINS:
                    text = "%" + QueryUtils.escapeLike(text, escape) + "%";
                    break;
                case STARTS:
                    text = QueryUtils.escapeLike(text, escape) + "%";
                    break;
                case ENDS:
                    text = "%" + QueryUtils.escapeLike(text, escape);
                    break;
                case LIKE:
                default:
                    // 何もしない
            }

            invoke(operator, left, visitor, context);
            context.appendSql(" like ?");
            if(escapeExp.isPresent()) {
                context.appendSql(" escape '" + escape + "'");
            }
            context.addParamValue(text);

        } else {
            // 定数以外はただのLIKEとして扱う
            invoke(operator, left, visitor, context);
            context.appendSql(" like ");
            if(escapeExp.isPresent()) {
                context.appendSql(" escape '" + escape + "'");
            }
            invoke(operator, right, visitor, context);
        }
    }

}