Skip to content

Commit

Permalink
FIlter fixes - datatype matching
Browse files Browse the repository at this point in the history
  • Loading branch information
harshadk-sourcefuse committed Aug 21, 2023
1 parent de33839 commit 0cd2a68
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,102 +2,77 @@

import static java.util.Map.entry;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.sourcefuse.jarc.core.filters.interfaces.TriFunction;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.Predicate;
import java.util.List;
import java.util.Map;
import java.util.Set;

public final class OperationPredicates {

private static Map<String, TriFunction<CriteriaBuilder,
Expression<String>, Object, Predicate>> operatorMap =
private static ObjectMapper objectMapper = new ObjectMapper()
.registerModule(new JavaTimeModule());

@SuppressWarnings({ "unchecked", "rawtypes" })
private static Map<String, TriFunction<CriteriaBuilder,
Expression<?>, Object, Predicate>> operatorMap =
Map.ofEntries(
entry("eq", CriteriaBuilder::equal),
entry("neq", CriteriaBuilder::notEqual),
entry(
"in",
(
CriteriaBuilder criteriaBuilder,
Expression<String> path,
Object value
) ->
(CriteriaBuilder cb, Expression<?> path, Object value) ->
path.in((List<?>) value)
),
entry(
"nin",
(
CriteriaBuilder criteriaBuilder,
Expression<String> path,
Object value
) ->
criteriaBuilder.not(path.in((List<?>) value))
(CriteriaBuilder cb, Expression<?> path, Object value) ->
cb.not(path.in((List<?>) value))
),
entry(
"like",
(
CriteriaBuilder criteriaBuilder,
Expression<String> path,
Object value
) ->
criteriaBuilder.like(path, String.valueOf(value))
(CriteriaBuilder cb, Expression<?> path, Object value) ->
cb.like(path.as(String.class), String.valueOf(value))
),
entry(
"nlike",
(
CriteriaBuilder criteriaBuilder,
Expression<String> path,
Object value
) ->
criteriaBuilder.notLike(path, String.valueOf(value))
(CriteriaBuilder cb, Expression<?> path, Object value) ->
cb.notLike(path.as(String.class), String.valueOf(value))
),
entry(
"gt",
(
CriteriaBuilder criteriaBuilder,
Expression<String> path,
Object value
) ->
criteriaBuilder.greaterThan(
path.as(Double.class),
Double.valueOf(value.toString())
(CriteriaBuilder cb, Expression<?> path, Object value) ->
cb.greaterThan(
(Expression<? extends Comparable>) path,
(Comparable) value
)
),
entry(
"gte",
(
CriteriaBuilder criteriaBuilder,
Expression<String> path,
Object value
) ->
criteriaBuilder.greaterThanOrEqualTo(
path.as(Double.class),
Double.valueOf(value.toString())
(CriteriaBuilder cb, Expression<?> path, Object value) ->
cb.greaterThanOrEqualTo(
(Expression<? extends Comparable>) path,
(Comparable) value
)
),
entry(
"lt",
(
CriteriaBuilder criteriaBuilder,
Expression<String> path,
Object value
) ->
criteriaBuilder.lessThan(
path.as(Double.class),
Double.valueOf(value.toString())
(CriteriaBuilder cb, Expression<?> path, Object value) ->
cb.lessThan(
(Expression<? extends Comparable>) path,
(Comparable) value
)
),
entry(
"lte",
(
CriteriaBuilder criteriaBuilder,
Expression<String> path,
Object value
) ->
criteriaBuilder.lessThanOrEqualTo(
path.as(Double.class),
Double.valueOf(value.toString())
(CriteriaBuilder cb, Expression<?> path, Object value) ->
cb.lessThanOrEqualTo(
(Expression<? extends Comparable>) path,
(Comparable) value
)
)
);
Expand All @@ -110,20 +85,42 @@ private OperationPredicates() {
}

public static Predicate getPredicate(
CriteriaBuilder criteriaBuilder,
CriteriaBuilder cb,
String operator,
Expression<String> fieldPath,
Expression<?> fieldPath,
Object value
) {
return operatorMap
.getOrDefault(
operator,
(CriteriaBuilder builder, Expression<String> path, Object val) -> {
(CriteriaBuilder builder, Expression<?> path, Object val) -> {
throw new IllegalArgumentException(
"Unsupported operator: " + operator
);
}
)
.apply(criteriaBuilder, fieldPath, value);
.apply(cb, fieldPath, castValueToDataType(cb, fieldPath, value));
}

private static Object castValueToDataType(
CriteriaBuilder cb,
Expression<?> path,
Object value
) {
Class<?> dataType = path.getJavaType();

if (value instanceof List<?> listVal) {
return listVal
.stream()
.map(ele -> objectMapper.convertValue(ele, dataType))
.toList();
} else if (value instanceof Set<?> setVal) {
return setVal
.stream()
.map(ele -> objectMapper.convertValue(ele, dataType))
.toList();
} else {
return objectMapper.convertValue(value, dataType);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ private <T> List<Predicate> buildPredicates(
From<?, T> from,
CriteriaQuery<?> criteriaQuery
) {
if (filter == null) {
return new ArrayList<>();
}
// Apply WHERE clause
List<Predicate> predicates = new ArrayList<>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.sourcefuse.jarc.core.test.repositories.UserRepository;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
Expand Down Expand Up @@ -140,7 +141,7 @@ void testFilter_ForGreaterThanOperator() {
@Test
void testFilter_ForGreaterThanOperatorWithString() {
assertThrows(
NumberFormatException.class,
IllegalArgumentException.class,
() -> this.filterWithOperatorAndAge("gt", "24s")
);
}
Expand All @@ -155,7 +156,7 @@ void testFilter_ForGreaterThanOrEqulsToOperator() {
@Test
void testFilter_ForGreaterThanOrEqulsToOperatorWithString() {
assertThrows(
NumberFormatException.class,
IllegalArgumentException.class,
() -> this.filterWithOperatorAndAge("gte", "24s")
);
}
Expand All @@ -170,7 +171,7 @@ void testFilter_ForLessThanOperator() {
@Test
void testFilter_ForLessThanOperatorWithString() {
assertThrows(
NumberFormatException.class,
IllegalArgumentException.class,
() -> this.filterWithOperatorAndAge("lt", "24s")
);
}
Expand All @@ -185,7 +186,7 @@ void testFilter_ForLessThanOrEqualsToOperator() {
@Test
void testFilter_ForLessThanOrEqualsToOperatorWithString() {
assertThrows(
NumberFormatException.class,
IllegalArgumentException.class,
() -> this.filterWithOperatorAndAge("lte", "24s")
);
}
Expand Down Expand Up @@ -383,7 +384,7 @@ void testFilterWithJson_ForGreaterThanOperator() {
@Test
void testFilterWithJson_ForGreaterThanOperatorWithString() {
assertThrows(
NumberFormatException.class,
IllegalArgumentException.class,
() ->
filterService.executeQuery(
"{\"where\":{\"age\":{\"gt\":\"24s\"}}}",
Expand All @@ -405,7 +406,7 @@ void testFilterWithJson_ForGreaterThanOrEqulsToOperator() {
@Test
void testFilterWithJson_ForGreaterThanOrEqulsToOperatorWithString() {
assertThrows(
NumberFormatException.class,
IllegalArgumentException.class,
() ->
filterService.executeQuery(
"{\"where\":{\"age\":{\"gte\":\"20s\"}}}",
Expand All @@ -427,7 +428,7 @@ void testFilterWithJson_ForLessThanOperator() {
@Test
void testFilterWithJson_ForLessThanOperatorWithString() {
assertThrows(
NumberFormatException.class,
IllegalArgumentException.class,
() ->
filterService.executeQuery(
"{\"where\":{\"age\":{\"lt\":\"24s\"}}}",
Expand All @@ -436,6 +437,42 @@ void testFilterWithJson_ForLessThanOperatorWithString() {
);
}

@Test
void testFilterWithJson_ForGreaterThanOperatorWithLocalDateTime() {
List<User> users = filterService.executeQuery(
"{\"where\":{\"createdOn\":{\"gt\":\"" +
LocalDateTime.now().toString() +
"\"}}}",
User.class
);

assertThat(users).hasSize(0);
}

@Test
void testFilterWithJson_ForLessThanOperatorWithLocalDateTime() {
List<User> users = filterService.executeQuery(
"{\"where\":{\"createdOn\":{\"lt\":\"" +
LocalDateTime.now().toString() +
"\"}}}",
User.class
);

assertThat(users).hasSize(3).contains(user1, user2, user3);
}

@Test
void testFilterWithJson_ForInOperatorWithLocalDateTime() {
List<User> users = filterService.executeQuery(
"{\"where\":{\"createdOn\":{\"in\":[\"" +
user1.getCreatedOn().toString() +
"\"]}}}",
User.class
);

assertThat(users).hasSize(1).contains(user1);
}

@Test
void testFilterWithJson_ForLessThanOrEqualsToOperator() {
List<User> users = filterService.executeQuery(
Expand All @@ -449,7 +486,7 @@ void testFilterWithJson_ForLessThanOrEqualsToOperator() {
@Test
void testFilterWithJson_ForLessThanOrEqualsToOperatorWithString() {
assertThrows(
NumberFormatException.class,
IllegalArgumentException.class,
() ->
filterService.executeQuery(
"{\"where\":{\"age\":{\"lte\":\"24s\"}}}",
Expand Down Expand Up @@ -497,9 +534,9 @@ void testFilterWithJson_FieldSelectionTest() {
void testFilterWithJson_ForInOerator() {
List<Role> roles = filterService.executeQuery(
"{\"where\":{\"id\":{\"in\": [\"" +
tempRole.getId() +
tempRole.getId().toString() +
"\", \"" +
adminRole.getId() +
adminRole.getId().toString() +
"\"]}}}",
Role.class
);
Expand All @@ -511,9 +548,9 @@ void testFilterWithJson_ForInOerator() {
void testFilterWithJson_ForNotInOerator() {
List<Role> roles = filterService.executeQuery(
"{\"where\":{\"id\":{\"nin\": [\"" +
tempRole.getId() +
tempRole.getId().toString() +
"\", \"" +
adminRole.getId() +
adminRole.getId().toString() +
"\"]}}}",
Role.class
);
Expand Down Expand Up @@ -603,6 +640,18 @@ void testSpecificationFilterWithJson_ForEqualsOperator() {
assertThat(userRole.getId()).isEqualTo(roles.get(0).getId());
}

@Test
void testSpecificationFilterWithJson_ForEqualsOperatorWithUUID() {
Specification<Role> specs = filterService.getSpecifications(
"{\"where\":{\"id\":{\"eq\":\"" + userRole.getId().toString() + "\"}}}"
);
List<Role> roles = this.roleRepository.findAll(specs);

assertThat(roles).hasSize(1);

assertThat(userRole.getId()).isEqualTo(roles.get(0).getId());
}

@Test
void testSpecificationFilterWithJson_ForNotEqualsOperator() {
Specification<Role> specs = filterService.getSpecifications(
Expand All @@ -613,6 +662,16 @@ void testSpecificationFilterWithJson_ForNotEqualsOperator() {
assertThat(roles).hasSize(2).contains(adminRole, tempRole);
}

@Test
void testSpecificationFilterWithJson_ForNotEqualsOperatorWithUUID() {
Specification<Role> specs = filterService.getSpecifications(
"{\"where\":{\"id\":{\"neq\":\"" + userRole.getId().toString() + "\"}}}"
);
List<Role> roles = this.roleRepository.findAll(specs);

assertThat(roles).hasSize(2).contains(adminRole, tempRole);
}

@Test
void testSpecificationFilterWithJson_ForGreaterThanOperator() {
Specification<User> specs = filterService.getSpecifications(
Expand Down Expand Up @@ -689,9 +748,9 @@ void testSpecificationFilterWithJson_ForNotLikeOperator() {
void testSpecificationFilterWithJson_ForInOerator() {
Specification<Role> specs = filterService.getSpecifications(
"{\"where\":{\"id\":{\"in\": [\"" +
tempRole.getId() +
tempRole.getId().toString() +
"\", \"" +
adminRole.getId() +
adminRole.getId().toString() +
"\"]}}}"
);
List<Role> roles = this.roleRepository.findAll(specs);
Expand All @@ -703,9 +762,9 @@ void testSpecificationFilterWithJson_ForInOerator() {
void testSpecificationFilterWithJson_ForNotInOerator() {
Specification<Role> specs = filterService.getSpecifications(
"{\"where\":{\"id\":{\"nin\": [\"" +
tempRole.getId() +
tempRole.getId().toString() +
"\", \"" +
adminRole.getId() +
adminRole.getId().toString() +
"\"]}}}"
);
List<Role> roles = this.roleRepository.findAll(specs);
Expand Down
Loading

0 comments on commit 0cd2a68

Please sign in to comment.