Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@
*
* @author Destan Sarpkaya
* @author Ersan Ceylan
* @author Sedat Gokcen
*/
enum CriteriaOperation {
enum CriteriaOperation implements Operation {

JOIN,
JOIN_FETCH,
EQUAL,
EQUAL_TO_MANY,
EQUAL_TO_ONE,
Expand Down
30 changes: 8 additions & 22 deletions src/main/java/com/kodgemisi/specification/FilterCriteria.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@
import lombok.Setter;
import org.springframework.lang.NonNull;

import javax.persistence.criteria.JoinType;

/**
* Created on October, 2018
*
* @author Destan Sarpkaya
* @author Ersan Ceylan
* @author Gökhan Birinci
* @author Sedat Gokcen
*/

/**
Expand All @@ -28,38 +27,25 @@ class FilterCriteria<T> {
private final T value;

@NonNull
private final CriteriaOperation operation;

private final JoinType joinType;
private final Operation operation;

private final Class<T> clazz;

private final RelationType relationType;

FilterCriteria(String key, T value, CriteriaOperation operation, Class<T> clazz) {
FilterCriteria(String key, T value, Operation operation, Class<T> clazz, RelationType relationType) {
this.key = key;
this.value = value;
this.operation = operation;
this.joinType = null;
this.clazz = clazz;
this.relationType = RelationType.NO_RELATION;
this.relationType = relationType;
}

FilterCriteria(String key, T value, CriteriaOperation operation, Class<T> clazz, RelationType relationType) {
this.key = key;
this.value = value;
this.operation = operation;
this.joinType = null;
this.clazz = clazz;
this.relationType = relationType;
FilterCriteria(String key, T value, Operation operation, Class<T> clazz) {
this(key, value, operation, clazz, RelationType.NO_RELATION);
}

FilterCriteria(String key, CriteriaOperation operation, JoinType joinType, Class<T> clazz) {
this.key = key;
this.operation = operation;
this.joinType = joinType;
this.clazz = clazz;
this.value = null;
this.relationType = RelationType.NO_RELATION;
FilterCriteria(String key, Operation operation, Class<T> clazz) {
this(key, null, operation, clazz, RelationType.NO_RELATION);
}
}
105 changes: 57 additions & 48 deletions src/main/java/com/kodgemisi/specification/GenericSpecification.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
* @author Destan Sarpkaya
* @author Ersan Ceylan
* @author Gökhan Birinci
* @author Sedat Gokcen
*/

@SuppressWarnings({"rawtypes", "unchecked"})
Expand All @@ -31,70 +32,78 @@ class GenericSpecification<E, T, C extends Comparable<? super C>> implements Spe
@Override
public Predicate toPredicate(Root<E> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {

final CriteriaOperation operation = filterCriteria.getOperation();
final Operation operation = filterCriteria.getOperation();
final String key = filterCriteria.getKey();

switch (operation) {
case JOIN: {
final JoinType joinType = filterCriteria.getJoinType();
root.join(key, joinType);
if (operation instanceof JoinOperation) {
JoinOperation joinOperation = (JoinOperation) operation;
processJoinOperation(joinOperation, key, root, query);
return null;
}

case JOIN_FETCH: {
final Class clazz = query.getResultType();
final JoinType joinType = filterCriteria.getJoinType();
if (clazz.equals(Long.class) || clazz.equals(long.class)) {
// If clazz is long then it's a count query for pageable
root.join(key, joinType);
return null;
final CriteriaOperation criteriaOperation = (CriteriaOperation) operation;

switch (criteriaOperation) {
case EQUAL: {
final Path<?> path = resolvePath(root, filterCriteria.getKey(), filterCriteria.getRelationType());
return criteriaBuilder.equal(path, filterCriteria.getValue());
}
else {
root.fetch(key, joinType);
return null;

case LIKE: {
final Path<?> path = resolvePath(root, filterCriteria.getKey(), filterCriteria.getRelationType());
return criteriaBuilder.like(path.as(String.class), "%" + filterCriteria.getValue() + "%");
}
}
case EQUAL: {
final Path<?> path = resolvePath(root, filterCriteria.getKey(), filterCriteria.getRelationType());
return criteriaBuilder.equal(path, filterCriteria.getValue());
}

case LIKE: {
final Path<?> path = resolvePath(root, filterCriteria.getKey(), filterCriteria.getRelationType());
return criteriaBuilder.like(path.as(String.class), "%" + filterCriteria.getValue() + "%");
}
case IN: {
final Path<?> path = resolvePath(root, filterCriteria.getKey(), filterCriteria.getRelationType());
return path.in(filterCriteria.getValue());
}

case IN: {
final Path<?> path = resolvePath(root, filterCriteria.getKey(), filterCriteria.getRelationType());
return path.in(filterCriteria.getValue());
}
case GREATER_THAN: {
final ComparableFilterCriteria<C> comparableFilterCriteria = getComparableFilterCriteria();
final Path<?> path = resolvePath(root, filterCriteria.getKey(), filterCriteria.getRelationType());
return criteriaBuilder.greaterThan(path.as(comparableFilterCriteria.getClazz()), comparableFilterCriteria.getValue());
}

case GREATER_THAN: {
final ComparableFilterCriteria<C> comparableFilterCriteria = getComparableFilterCriteria();
final Path<?> path = resolvePath(root, filterCriteria.getKey(), filterCriteria.getRelationType());
return criteriaBuilder.greaterThan(path.as(comparableFilterCriteria.getClazz()), comparableFilterCriteria.getValue());
}
case GREATER_THAN_OR_EQUAL_TO: {
final ComparableFilterCriteria<C> comparableFilterCriteria = getComparableFilterCriteria();
final Path<?> path = resolvePath(root, filterCriteria.getKey(), filterCriteria.getRelationType());
return criteriaBuilder.greaterThanOrEqualTo(path.as(comparableFilterCriteria.getClazz()), comparableFilterCriteria.getValue());
}

case GREATER_THAN_OR_EQUAL_TO: {
final ComparableFilterCriteria<C> comparableFilterCriteria = getComparableFilterCriteria();
final Path<?> path = resolvePath(root, filterCriteria.getKey(), filterCriteria.getRelationType());
return criteriaBuilder.greaterThanOrEqualTo(path.as(comparableFilterCriteria.getClazz()), comparableFilterCriteria.getValue());
}
case LESS_THAN: {
final ComparableFilterCriteria<C> comparableFilterCriteria = getComparableFilterCriteria();
final Path<?> path = resolvePath(root, filterCriteria.getKey(), filterCriteria.getRelationType());
return criteriaBuilder.lessThan(path.as(comparableFilterCriteria.getClazz()), comparableFilterCriteria.getValue());
}

case LESS_THAN_OR_EQUAL_TO: {
final ComparableFilterCriteria<C> comparableFilterCriteria = getComparableFilterCriteria();
final Path<?> path = resolvePath(root, filterCriteria.getKey(), filterCriteria.getRelationType());
return criteriaBuilder.lessThanOrEqualTo(path.as(comparableFilterCriteria.getClazz()), comparableFilterCriteria.getValue());
}

case LESS_THAN: {
final ComparableFilterCriteria<C> comparableFilterCriteria = getComparableFilterCriteria();
final Path<?> path = resolvePath(root, filterCriteria.getKey(), filterCriteria.getRelationType());
return criteriaBuilder.lessThan(path.as(comparableFilterCriteria.getClazz()), comparableFilterCriteria.getValue());
default:
return null;
}
}

private void processJoinOperation(JoinOperation joinOperation, String key, Root<E> root, CriteriaQuery<?> query) {
final JoinType joinType = joinOperation.getType();

case LESS_THAN_OR_EQUAL_TO: {
final ComparableFilterCriteria<C> comparableFilterCriteria = getComparableFilterCriteria();
final Path<?> path = resolvePath(root, filterCriteria.getKey(), filterCriteria.getRelationType());
return criteriaBuilder.lessThanOrEqualTo(path.as(comparableFilterCriteria.getClazz()), comparableFilterCriteria.getValue());
if (joinOperation == JoinOperation.JOIN) {
root.join(key, joinType);
return;
}

default:
return null;
final Class clazz = query.getResultType();

if (clazz.equals(Long.class) || clazz.equals(long.class)) {
// If clazz is long then it's a count query for pageable
root.join(key, joinType);
}
else {
root.fetch(key, joinType);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
* @author Destan Sarpkaya
* @author Ersan Ceylan
* @author Gökhan Birinci
* @author Sedat Gokcen
*/
public class GenericSpecificationBuilder<E> {

Expand Down Expand Up @@ -55,8 +56,8 @@ public static <E> GenericSpecificationBuilder<E> of(Class<E> clazz) {
return new GenericSpecificationBuilder<>();
}

private GenericSpecificationBuilder<E> addCriteria(String key, CriteriaOperation operation, JoinType joinType) {
filterCriteriaList.add(new FilterCriteria<Void>(key, operation, joinType, Void.class));
private GenericSpecificationBuilder<E> addCriteria(String key, Operation operation) {
filterCriteriaList.add(new FilterCriteria<Void>(key, operation, Void.class));
return this;
}

Expand All @@ -82,7 +83,7 @@ private <C extends Comparable<? super C>> GenericSpecificationBuilder<E> addCom
* @return
*/
public GenericSpecificationBuilder<E> join(String key) {
return addCriteria(key, CriteriaOperation.JOIN, JoinType.INNER);
return addCriteria(key, JoinOperation.JOIN.type(JoinType.INNER));
}

/**
Expand All @@ -92,7 +93,7 @@ public GenericSpecificationBuilder<E> join(String key) {
* @return
*/
public GenericSpecificationBuilder<E> join(String key, JoinType joinType) {
return addCriteria(key, CriteriaOperation.JOIN, joinType);
return addCriteria(key, JoinOperation.JOIN.type(joinType));
}

/**
Expand All @@ -101,7 +102,7 @@ public GenericSpecificationBuilder<E> join(String key, JoinType joinType) {
* @return
*/
public GenericSpecificationBuilder<E> joinFetch(String key) {
return addCriteria(key, CriteriaOperation.JOIN_FETCH, JoinType.INNER);
return addCriteria(key, JoinOperation.JOIN_FETCH.type(JoinType.INNER));
}

/**
Expand All @@ -111,7 +112,7 @@ public GenericSpecificationBuilder<E> joinFetch(String key) {
* @return
*/
public GenericSpecificationBuilder<E> joinFetch(String key, JoinType joinType) {
return addCriteria(key, CriteriaOperation.JOIN_FETCH, joinType);
return addCriteria(key, JoinOperation.JOIN_FETCH.type(joinType));
}

/**
Expand Down
24 changes: 24 additions & 0 deletions src/main/java/com/kodgemisi/specification/JoinOperation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.kodgemisi.specification;

import javax.persistence.criteria.JoinType;

/**
* Created on November, 2018
*
* @author Sedat Gokcen
*/
public enum JoinOperation implements Operation {
JOIN,
JOIN_FETCH;

private JoinType type = JoinType.INNER;

public JoinOperation type(JoinType type) {
this.type = type;
return this;
}

public JoinType getType() {
return type;
}
}
9 changes: 9 additions & 0 deletions src/main/java/com/kodgemisi/specification/Operation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.kodgemisi.specification;

/**
* Created on November, 2018
*
* @author Sedat Gokcen
*/
interface Operation {
}