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

com.dottydingo.hyperion.jpa.persistence.query.AbstractEntityJpaQueryBuilder Maven / Gradle / Ivy

package com.dottydingo.hyperion.jpa.persistence.query;

import com.dottydingo.hyperion.api.exception.BadRequestException;
import com.dottydingo.hyperion.core.persistence.PersistenceContext;
import com.dottydingo.hyperion.core.persistence.query.ArgumentParser;
import com.dottydingo.hyperion.core.persistence.query.DefaultArgumentParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import java.util.Collection;

/**
 */
public abstract class AbstractEntityJpaQueryBuilder implements JpaEntityQueryBuilder
{
    public static final String INCOMPATIBLE_QUERY_OPERATION = "ERROR_INCOMPATIBLE_QUERY_OPERATION";
    private Logger logger = LoggerFactory.getLogger(AbstractEntityJpaQueryBuilder.class);
    protected static final Character LIKE_WILDCARD = '*';

    protected ArgumentParser argumentParser = DefaultArgumentParser.getInstance();

    public void setArgumentParser(ArgumentParser argumentParser)
    {
        this.argumentParser = argumentParser;
    }

    /**
     * Delegate creating of a Predicate to an appropriate method according to
     * operator.
     *
     * @param root         root
     * @param query        query
     * @param propertyName property name
     * @param operator     comparison operator
     * @param argument     argument
     * @param context      context
     * @return Predicate
     */
    protected Predicate createPredicate(Path root, CriteriaQuery query, CriteriaBuilder cb, String propertyName,
                                        ComparisonOperator operator, Object argument, PersistenceContext context)
    {
        logger.debug("Creating criterion: {} {} {}", propertyName, operator, argument);

        switch (operator)
        {
            case EQUAL:
            {
                if (containWildcard(argument))
                {
                    return createLike(root, query, cb, propertyName, argument, context);
                }
                else
                {
                    return createEqual(root, query, cb, propertyName, argument, context);
                }
            }
            case NOT_EQUAL:
            {
                if (containWildcard(argument))
                {
                    return createNotLike(root, query, cb, propertyName, argument, context);
                }
                else
                {
                    return createNotEqual(root, query, cb, propertyName, argument, context);
                }
            }
            case GREATER_THAN:
                return createGreaterThan(root, query, cb, propertyName, argument, context);
            case GREATER_EQUAL:
                return createGreaterEqual(root, query, cb, propertyName, argument, context);
            case LESS_THAN:
                return createLessThan(root, query, cb, propertyName, argument, context);
            case LESS_EQUAL:
                return createLessEqual(root, query, cb, propertyName, argument, context);
            case IN:
                return createIn(root, query, cb, propertyName, argument, context);
            case NOT_IN:
                return createNotIn(root, query, cb, propertyName, argument, context);
        }
        throw new IllegalArgumentException("Unknown operator: " + operator);
    }

    /**
     * Apply an "equal" constraint to the named property.
     *
     *
     * @param query
     * @param propertyPath property name prefixed with an association alias
     * @param argument     value
     * @param context
     * @return Predicate
     */
    protected Predicate createEqual(Path root, CriteriaQuery query, CriteriaBuilder cb, String propertyPath,
                                    Object argument, PersistenceContext context)
    {
        return cb.equal(root.get(propertyPath), argument);
    }

    /**
     * Apply a case-insensitive "like" constraint to the named property. Value
     * should contains wildcards "*" (% in SQL) and "_".
     *
     *
     * @param query
     * @param propertyPath property name prefixed with an association alias
     * @param argument     value
     * @param context
     * @return Predicate
     */
    protected Predicate createLike(Path root, CriteriaQuery query, CriteriaBuilder cb, String propertyPath, Object argument,
                                   PersistenceContext context)
    {
        String like = (String) argument;
        like = like.replace(LIKE_WILDCARD, '%');

        return cb.like(cb.lower(root.get(propertyPath)), like.toLowerCase());
    }

    /**
     * Apply a "not equal" constraint to the named property.
     *
     *
     * @param query
     * @param propertyPath property name prefixed with an association alias
     * @param argument     value
     * @param context
     * @return Predicate
     */
    protected Predicate createNotEqual(Path root, CriteriaQuery query, CriteriaBuilder cb, String propertyPath, Object argument,
                                       PersistenceContext context)
    {
        return cb.notEqual(root.get(propertyPath), argument);
    }

    /**
     * Apply a negative case-insensitive "like" constraint to the named property.
     * Value should contains wildcards "*" (% in SQL) and "_".
     *
     *
     * @param query
     * @param propertyPath property name prefixed with an association alias
     * @param argument     Value with wildcards.
     * @param context
     * @return Predicate
     */
    protected Predicate createNotLike(Path root, CriteriaQuery query, CriteriaBuilder cb, String propertyPath, Object argument,
                                      PersistenceContext context)
    {
        return cb.notLike(root.get(propertyPath), (String) argument);
    }

    /**
     * Apply a "greater than" constraint to the named property.
     *
     *
     * @param query
     * @param propertyPath property name prefixed with an association alias
     * @param argument     value
     * @param context
     * @return Predicate
     */
    protected Predicate createGreaterThan(Path root, CriteriaQuery query, CriteriaBuilder cb, String propertyPath, Object argument,
                                          PersistenceContext context)
    {
        if(!(argument instanceof Comparable))
            throw new BadRequestException(context.getMessageSource().getErrorMessage(
                    INCOMPATIBLE_QUERY_OPERATION, context.getLocale(), "gt"));

        return cb.greaterThan(root.get(propertyPath), (Comparable) argument);
    }

    /**
     * Apply a "greater than or equal" constraint to the named property.
     *
     *
     * @param query
     * @param propertyPath property name prefixed with an association alias
     * @param argument     value
     * @param context
     * @return Predicate
     */
    protected Predicate createGreaterEqual(Path root, CriteriaQuery query, CriteriaBuilder cb, String propertyPath, Object argument,
                                           PersistenceContext context)
    {
        if(!(argument instanceof Comparable))
            throw new BadRequestException(context.getMessageSource().getErrorMessage(
                    INCOMPATIBLE_QUERY_OPERATION, context.getLocale(), "ge"));

        return cb.greaterThanOrEqualTo(root.get(propertyPath), (Comparable) argument);
    }

    /**
     * Apply a "less than" constraint to the named property.
     *
     *
     * @param query
     * @param propertyPath property name prefixed with an association alias
     * @param argument     value
     * @param context
     * @return Predicate
     */
    protected Predicate createLessThan(Path root, CriteriaQuery query, CriteriaBuilder cb, String propertyPath, Object argument,
                                       PersistenceContext context)
    {
        if(!(argument instanceof Comparable))
            throw new BadRequestException(context.getMessageSource().getErrorMessage(
                    INCOMPATIBLE_QUERY_OPERATION, context.getLocale(), "lt"));

        return cb.lessThan(root.get(propertyPath), (Comparable) argument);
    }

    /**
     * Apply a "less than or equal" constraint to the named property.
     *
     *
     * @param query
     * @param propertyPath property name prefixed with an association alias
     * @param argument     value
     * @param context
     * @return Predicate
     */
    protected Predicate createLessEqual(Path root, CriteriaQuery query, CriteriaBuilder cb, String propertyPath, Object argument,
                                        PersistenceContext context)
    {
        if(!(argument instanceof Comparable))
            throw new BadRequestException(context.getMessageSource().getErrorMessage(
                    INCOMPATIBLE_QUERY_OPERATION,context.getLocale(),"le"));

        return cb.lessThanOrEqualTo(root.get(propertyPath), (Comparable) argument);
    }

    protected Predicate createIn(Path root, CriteriaQuery query, CriteriaBuilder cb, String propertyPath, Object argument,
                                 PersistenceContext context)
    {
        if(!(argument instanceof Collection))
            throw new BadRequestException(context.getMessageSource().getErrorMessage(
                    INCOMPATIBLE_QUERY_OPERATION, context.getLocale(), "in"));

        Path expression = root.get(propertyPath);
        return expression.in((Collection)argument);
    }

    protected Predicate createNotIn(Path root, CriteriaQuery query, CriteriaBuilder cb, String propertyPath, Object argument,
                                    PersistenceContext context)
    {
        if(!(argument instanceof Collection))
            throw new BadRequestException(context.getMessageSource().getErrorMessage(
                    INCOMPATIBLE_QUERY_OPERATION, context.getLocale(), "not in"));

        Path expression = root.get(propertyPath);
        return cb.not(expression.in((Collection)argument));
    }

    /**
     * Check if given value contains wildcard.
     *
     * @param value the value
     * @return Return true if argument contains {@link #LIKE_WILDCARD}.
     */
    protected boolean containWildcard(Object value)
    {
        if (!(value instanceof String))
        {
            return false;
        }

        String casted = (String) value;
        return casted.contains(LIKE_WILDCARD.toString());

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy