Skip to content

Commit

Permalink
feat(dsl): allow dsl extension by replacing enum for class (#3)
Browse files Browse the repository at this point in the history
* feat(dsl): allow dsl extension by replacing enum for class
  • Loading branch information
arnaud-thorel-of authored Dec 21, 2023
1 parent 12a7fa4 commit f4f8141
Show file tree
Hide file tree
Showing 21 changed files with 122 additions and 141 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>fr.ouestfrance.querydsl</groupId>
<artifactId>querydsl</artifactId>
<version>1.1.2-SNAPSHOT</version>
<version>1.2.0-SNAPSHOT</version>
<name>querydsl</name>
<description>Unified queryDSL based on annotations</description>
<url>https://github.com/ouest-france/querydsl</url>
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/fr/ouestfrance/querydsl/FilterField.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,18 @@
*
* @return operation type
*/
FilterOperation operation() default FilterOperation.EQ;
Class<? extends FilterOperation> operation() default FilterOperation.EQ.class;

/**
* Should handle null possible value (isNull or isEqualsTo(XXX))
*
* @return <code>true</code> is should handle null, otherwise <code>false</code>
*/
boolean orNull() default false;

/**
* Group the filter in "or group" every filter with "orGroup" will be joined together
*
* @return group name
*/
String groupName() default "";
Expand Down
72 changes: 52 additions & 20 deletions src/main/java/fr/ouestfrance/querydsl/FilterOperation.java
Original file line number Diff line number Diff line change
@@ -1,43 +1,75 @@
package fr.ouestfrance.querydsl;

import fr.ouestfrance.querydsl.service.validators.ValidatedBy;
import fr.ouestfrance.querydsl.service.validators.impl.CollectionValidator;
import fr.ouestfrance.querydsl.service.validators.impl.ComparableValidator;
import fr.ouestfrance.querydsl.service.validators.impl.StringValidator;

/**
* Type of operations
* Operations allowed by querydsl
*/
public enum FilterOperation {
public interface FilterOperation {

/**
* Should be equals
* Not Equals Operation
*/
EQ,
@ValidatedBy(ComparableValidator.class)
class NEQ implements FilterOperation {
}

/**
* Should contains data
* Equals Operation
*/
LIKE,
@ValidatedBy(ComparableValidator.class)
class EQ implements FilterOperation {
}

/**
* Should be greater than
* Greater than Operation
*/
GT,
@ValidatedBy(ComparableValidator.class)
class GT implements FilterOperation {
}

/**
* Should be greater than or equals to
* Greater than or equals Operation
*/
GTE,
@ValidatedBy(ComparableValidator.class)
class GTE implements FilterOperation {
}

/**
* Should be less than
* Less than Operation
*/
LT,
@ValidatedBy(ComparableValidator.class)
class LT implements FilterOperation {
}

/**
* Should be less than or equals to
* Less than or equals Operation
*/
LTE,
@ValidatedBy(ComparableValidator.class)
class LTE implements FilterOperation {
}

/**
* Should be not equals to
* Like Operation
*/
NEQ,
@ValidatedBy(StringValidator.class)
class LIKE implements FilterOperation {
}

/**
* Should be in a specific list
* Not Like Operation
*/
IN,
@ValidatedBy(CollectionValidator.class)
class IN implements FilterOperation {
}

/**
* Should not be in a specific list
* Not In Operation
*/
NOT_IN
@ValidatedBy(CollectionValidator.class)
class NOTIN implements FilterOperation {
}
}
10 changes: 6 additions & 4 deletions src/main/java/fr/ouestfrance/querydsl/model/SimpleFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@

/**
* FilterFieldInfoModel allow to store object representation of FilterField Annotation
* @param key key of the criteria
*
* @param key key of the criteria
* @param operation operator to apply
* @param orNull allow the field to be null
* @param field field of the field representing type, method accessor and field name
* @param orNull allow the field to be null
* @param field field of the field representing type, method accessor and field name
*/
public record SimpleFilter(String key, FilterOperation operation, boolean orNull, Field field) implements Filter {
public record SimpleFilter(String key, Class<? extends FilterOperation> operation, boolean orNull,
Field field) implements Filter {
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* }
* }
* }</pre>
*
* @param <T> type of result
*/
public interface Mapper<T> {
Expand All @@ -40,5 +41,5 @@ public interface Mapper<T> {
*
* @return operation type
*/
FilterOperation operation();
Class<? extends FilterOperation> operation();
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ private Optional<T> handleFilter(SimpleFilter filter, Object object) {
* @param operation type of operation
* @return mapper for this operation
*/
Mapper<T> getMapper(FilterOperation operation);
Mapper<T> getMapper(Class<? extends FilterOperation> operation);

/**
* Allow to group multiple filters with logical operand
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@

import fr.ouestfrance.querydsl.FilterOperation;
import fr.ouestfrance.querydsl.model.SimpleFilter;
import fr.ouestfrance.querydsl.service.validators.impl.EqualsValidator;
import fr.ouestfrance.querydsl.service.validators.impl.GreaterLessValidator;
import fr.ouestfrance.querydsl.service.validators.impl.InValidator;
import fr.ouestfrance.querydsl.service.validators.impl.LikeValidator;

import java.util.Arrays;
import java.util.List;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
Expand Down Expand Up @@ -38,9 +35,9 @@
public class FilterFieldValidatorService {

/**
* List of validators
* Map of validators
*/
private final List<FilterFieldValidator> validators = List.of(new EqualsValidator(), new GreaterLessValidator(), new InValidator(), new LikeValidator());
private static final Map<Class<? extends FilterFieldValidator>, FilterFieldValidator> VALIDATOR_MAP = new HashMap<>();

/**
* Check each filter and build a filter of violations
Expand All @@ -49,9 +46,12 @@ public class FilterFieldValidatorService {
* @return empty filter if everything is ok, otherwise it returns filter of {@link FilterFieldViolation}
*/
public Optional<FilterFieldViolation> validate(SimpleFilter filter) {
return getValidator(filter.operation())
.filter(x-> !x.validate((Class<?>) filter.field().getType()))
.map(x -> new FilterFieldViolation(filter.field().getName(), "Operation " + filter.operation() + " " + x.message()));
FilterFieldValidator validator = getValidator(filter.operation());
if (validator.validate(filter.field().getType())) {
return Optional.empty();
} else {
return Optional.of(new FilterFieldViolation(filter.field().getName(), "Operation " + filter.operation() + " " + validator.message()));
}
}

/**
Expand All @@ -60,7 +60,18 @@ public Optional<FilterFieldViolation> validate(SimpleFilter filter) {
* @param operation operation in the FilterField annotation
* @return Validator for this field
*/
private Optional<FilterFieldValidator> getValidator(FilterOperation operation) {
return validators.stream().filter(x -> Arrays.asList(x.getClass().getAnnotation(ValidatedBy.class).value()).contains(operation)).findFirst();
private FilterFieldValidator getValidator(Class<? extends FilterOperation> operation) {
ValidatedBy validator = operation.getAnnotation(ValidatedBy.class);
if (validator == null) {
throw new IllegalStateException("Operation " + operation + " should be annotated with @ValidatedBy");
}
return VALIDATOR_MAP.computeIfAbsent(validator.value(), x -> {
try {
return x.getConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException |
InvocationTargetException e) {
throw new IllegalStateException("Validator " + x + " should have a default constructor", e);
}
});
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package fr.ouestfrance.querydsl.service.validators;

import fr.ouestfrance.querydsl.FilterOperation;

import java.lang.annotation.*;

/**
Expand All @@ -17,5 +15,5 @@
*
* @return operation
*/
FilterOperation[] value();
Class<? extends FilterFieldValidator> value();
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
package fr.ouestfrance.querydsl.service.validators.impl;

import fr.ouestfrance.querydsl.FilterOperation;
import fr.ouestfrance.querydsl.service.validators.FilterFieldValidator;
import fr.ouestfrance.querydsl.service.validators.ValidatedBy;
import lombok.NoArgsConstructor;

import java.util.Collection;

/**
* Validator that handle filter operations containing (IN, NOT_IN)
*/
@ValidatedBy({FilterOperation.IN, FilterOperation.NOT_IN})
@NoArgsConstructor
public class InValidator implements FilterFieldValidator {
public class CollectionValidator implements FilterFieldValidator {

@Override
public boolean validate(Class<?> clazz) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@
/**
* Validator that handle filter operations giving equalities (EQ, NEQ)
*/
@ValidatedBy({FilterOperation.EQ, FilterOperation.NEQ})
@NoArgsConstructor
public class EqualsValidator implements FilterFieldValidator {
public class ComparableValidator implements FilterFieldValidator {

@Override
public boolean validate(Class<?> clazz) {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
package fr.ouestfrance.querydsl.service.validators.impl;

import fr.ouestfrance.querydsl.FilterOperation;
import fr.ouestfrance.querydsl.service.validators.FilterFieldValidator;
import fr.ouestfrance.querydsl.service.validators.ValidatedBy;
import lombok.NoArgsConstructor;

/**
* Validator that handle filter operations giving like (LIKE)
*/
@ValidatedBy({FilterOperation.LIKE})
@NoArgsConstructor
public class LikeValidator implements FilterFieldValidator {
public class StringValidator implements FilterFieldValidator {
@Override
public boolean validate(Class<?> clazz) {
return String.class.isAssignableFrom(clazz);
Expand Down
6 changes: 3 additions & 3 deletions src/test/java/fr/ouestfrance/querydsl/dummy/DummyRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ public class DummyRequest {
@FilterField(key = "productCode")
private String code;

@FilterField(operation = FilterOperation.IN, key = "edition")
@FilterField(operation = FilterOperation.IN.class, key = "edition")
private List<String> editions;

@FilterField(operation = FilterOperation.GTE, key = "startDate")
@FilterField(operation = FilterOperation.LTE, key = "endDate", orNull = true)
@FilterField(operation = FilterOperation.GTE.class, key = "startDate")
@FilterField(operation = FilterOperation.LTE.class, key = "endDate", orNull = true)
private LocalDate validityDate;

@FilterField
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ public class DummyRequestOrSingleField {

@FilterField(key = "size", groupName = "group1")
@FilterFields(groupName = "group1", value = {
@FilterField(key = "minSize", operation = FilterOperation.GTE),
@FilterField(key = "maxSize", operation = FilterOperation.LTE)
@FilterField(key = "minSize", operation = FilterOperation.GTE.class),
@FilterField(key = "maxSize", operation = FilterOperation.LTE.class)
})
private String size;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package fr.ouestfrance.querydsl.dummy;

import fr.ouestfrance.querydsl.FilterField;
import fr.ouestfrance.querydsl.FilterOperation;
import fr.ouestfrance.querydsl.FilterOperation.IN;
import fr.ouestfrance.querydsl.FilterOperation.LTE;
import fr.ouestfrance.querydsl.FilterOperation.LIKE;
import lombok.Getter;
import lombok.Setter;

Expand All @@ -11,12 +13,12 @@
@Setter
public class DummyViolatedRulesRequest {

@FilterField(operation = FilterOperation.IN)
@FilterField(operation = IN.class)
private String code;

@FilterField(operation = FilterOperation.LTE, key = "edition")
@FilterField(operation = LTE.class, key = "edition")
private List<String> editions;

@FilterField(operation = FilterOperation.LIKE)
@FilterField(operation = LIKE.class)
private int quantity;
}
Loading

0 comments on commit f4f8141

Please sign in to comment.