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

io.github.perplexhub.rsql.RSQLJPASupport Maven / Gradle / Ivy

package io.github.perplexhub.rsql;

import java.util.*;
import java.util.stream.Collectors;

import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;

import cz.jirutka.rsql.parser.RSQLParser;
import cz.jirutka.rsql.parser.ast.ComparisonOperator;
import cz.jirutka.rsql.parser.ast.Node;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@SuppressWarnings({ "serial" })
public class RSQLJPASupport extends RSQLCommonSupport {

	public RSQLJPASupport() {
		super();
	}

	public RSQLJPASupport(Map entityManagerMap) {
		super(entityManagerMap);
	}

	public static  Specification rsql(final String rsqlQuery) {
		return toSpecification(rsqlQuery, false, null);
	}

	public static  Specification rsql(final String rsqlQuery, final boolean distinct) {
		return toSpecification(rsqlQuery, distinct, null);
	}

	public static  Specification rsql(final String rsqlQuery, final Map propertyPathMapper) {
		return toSpecification(rsqlQuery, false, propertyPathMapper);
	}

	public static  Specification rsql(final String rsqlQuery, final boolean distinct, final Map propertyPathMapper) {
		return toSpecification(rsqlQuery, distinct, propertyPathMapper);
	}

	public static  Specification rsql(final String rsqlQuery, final List> customPredicates) {
		return toSpecification(rsqlQuery, customPredicates);
	}

	public static  Specification toSpecification(final String rsqlQuery) {
		return toSpecification(rsqlQuery, false, null);
	}

	public static  Specification toSpecification(final String rsqlQuery, final Map propertyPathMapper) {
		return toSpecification(rsqlQuery, false, propertyPathMapper);
	}

	public static  Specification toSpecification(final String rsqlQuery, final boolean distinct) {
		return toSpecification(rsqlQuery, distinct, null);
	}

	public static  Specification toSpecification(final String rsqlQuery, final boolean distinct, final Map propertyPathMapper) {
		return toSpecification(rsqlQuery, distinct, propertyPathMapper, null);
	}

	public static  Specification toSpecification(final String rsqlQuery, final List> customPredicates) {
		return toSpecification(rsqlQuery, false, null, customPredicates);
	}

	public static  Specification toSpecification(final String rsqlQuery, final boolean distinct, final Map propertyPathMapper, final List> customPredicates) {
		log.debug("toSpecification({},distinct:{},propertyPathMapper:{})", rsqlQuery, distinct, propertyPathMapper);
		return new Specification() {
			public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
				query.distinct(distinct);
				if (StringUtils.hasText(rsqlQuery)) {
					Set supportedOperators = RSQLOperators.supportedOperators();
					if (customPredicates != null) {
						supportedOperators.addAll(customPredicates.stream().map(RSQLCustomPredicate::getOperator).filter(Objects::nonNull).collect(Collectors.toSet()));
					}
					Node rsql = new RSQLParser(supportedOperators).parse(rsqlQuery);
					return rsql.accept(new RSQLJPAPredicateConverter(cb, propertyPathMapper, customPredicates), root);
				} else
					return null;
			}
		};
	}

	/**
	 * Returns a single entity matching the given {@link Specification} or {@link Optional#empty()} if none found.
	 *
	 * @param jpaSpecificationExecutor JPA repository
	 * @param rsqlQuery can be {@literal null}.
	 * @return never {@literal null}.
	 * @throws org.springframework.dao.IncorrectResultSizeDataAccessException if more than one entity found.
	 */
	public static Optional findOne(JpaSpecificationExecutor jpaSpecificationExecutor, @Nullable String rsqlQuery) {
		return jpaSpecificationExecutor.findOne(toSpecification(rsqlQuery));
	}

	/**
	 * Returns all entities matching the given {@link Specification}.
	 *
	 * @param jpaSpecificationExecutor JPA repository
	 * @param rsqlQuery can be {@literal null}.
	 * @return never {@literal null}.
	 */
	public static List findAll(JpaSpecificationExecutor jpaSpecificationExecutor, @Nullable String rsqlQuery) {
		return jpaSpecificationExecutor.findAll(toSpecification(rsqlQuery));
	}

	/**
	 * Returns a {@link Page} of entities matching the given {@link Specification}.
	 *
	 * @param jpaSpecificationExecutor JPA repository
	 * @param rsqlQuery can be {@literal null}.
	 * @param pageable must not be {@literal null}.
	 * @return never {@literal null}.
	 */
	public static Page findAll(JpaSpecificationExecutor jpaSpecificationExecutor, @Nullable String rsqlQuery, Pageable pageable) {
		return jpaSpecificationExecutor.findAll(toSpecification(rsqlQuery), pageable);
	}

	/**
	 * Returns all entities matching the given {@link Specification} and {@link Sort}.
	 *
	 * @param jpaSpecificationExecutor JPA repository
	 * @param rsqlQuery can be {@literal null}.
	 * @param sort must not be {@literal null}.
	 * @return never {@literal null}.
	 */
	public static List findAll(JpaSpecificationExecutor jpaSpecificationExecutor, @Nullable String rsqlQuery, Sort sort) {
		return jpaSpecificationExecutor.findAll(toSpecification(rsqlQuery), sort);
	}

	/**
	 * Returns all entities matching the given {@link Specification} and {@link Sort}.
	 *
	 * @param jpaSpecificationExecutor JPA repository
	 * @param rsqlQuery can be {@literal null}.
	 * @param sort can be {@literal null}, comma delimited.
	 * @return never {@literal null}.
	 */
	public static List findAll(JpaSpecificationExecutor jpaSpecificationExecutor, @Nullable String rsqlQuery, @Nullable String sort) {
		return StringUtils.hasText(sort)
				? jpaSpecificationExecutor.findAll(toSpecification(rsqlQuery), Sort.by(Direction.ASC, StringUtils.commaDelimitedListToStringArray(sort)))
				: jpaSpecificationExecutor.findAll(toSpecification(rsqlQuery));
	}

	/**
	 * Returns the number of instances that the given {@link Specification} will return.
	 *
	 * @param jpaSpecificationExecutor JPA repository
	 * @param rsqlQuery the {@link Specification} to count instances for. Can be {@literal null}.
	 * @return the number of instances.
	 */
	public static long count(JpaSpecificationExecutor jpaSpecificationExecutor, @Nullable String rsqlQuery) {
		return jpaSpecificationExecutor.count(toSpecification(rsqlQuery));
	}

	protected String getVersion() {
		try {
			Properties prop = new Properties();
			prop.load(getClass().getResourceAsStream("/META-INF/maven/io.github.perplexhub/rsql-jpa/pom.properties"));
			String version = prop.getProperty("version");
			return StringUtils.hasText(version) ? "[" + version + "] " : "";
		} catch (Exception e) {
			return "";
		}
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy