Imagine that I have several filters and I need several if
to validate if the value is present, and if it is, I add a criteria each time it is present and at the end of the flow I return a query.
I would then need to go through each of the filters, see if the value is present and then add a criterion.
How would I do this without using if
and using only Java's Reactor powers?
I can use filter, map, filterWhen, zipWhen etc.
private Mono<Query> createQueryWithFilters(Filters filters) {
Criteria criteria = new Criteria();
Query query = new Query();
if (filters.getName().isPresent()) {
query.addCriteria(criteria.and("name")
.regex(filters.getName().get()));
}
if (filters.getAge().isPresent()) {
query.addCriteria(criteria.and("age")
.regex(filters.getAge().get()));
}
return Mono.just(query);
}
In the code above I want to return without using if and I would like to instantiate Query()
and Criteria()
in the stream using Mono
or Flux
.
An example of coding is the one below, you can see that it is very readable and the code is more beautiful.
Code pattern example:
public Mono<TaskDTO> getTaskById(String configId, String taskId) {
return configRepository.findById(configId)
.switchIfEmpty(error(notFoundException(IAC_CONFIG_NOT_FOUND_ERROR_MSG)))
.map(Config::getTasks)
.filter(v -> v.stream().anyMatch(t -> Objects.equals(t.getId(), taskId)))
.switchIfEmpty(error(notFoundException(IAC_TASK_NOT_FOUND_MSG)))
.map(v -> v.stream().findAny())
.filter(Optional::isPresent)
.map(v -> taskConverter.convert(v.get()));
}
CodePudding user response:
You can try this solution.
private static final Map<String, Function<Filter, Criteria>>
FILTERS = new HashMap<>();
static {
FILTERS.put("NAME", value -> Criteria.where("name").regex((String) value.getValue()));
FILTERS.put("AGE", value -> Criteria.where("age").is(value.getValue()));
}
public Mono<Query> createQueryWithFilters(Flux<Filter> filterFlux) {
Criteria criteria = new Criteria();
return Mono.from(
filterFlux.map(filter -> FILTERS.get(filter.getKey()).apply(filter))
.map(f -> new Query(criteria.andOperator(f)))
);
}
Filter class
@Data
@AllArgsConstructor
public class Filter {
String key;
Object value;
}
Test cases
Flux<Filter> filterFlux = Flux.just(new Filter("NAME", "john"), new Filter("AGE", 19));
createQueryWithFilters(filterFlux)
.subscribe(val -> System.out.println(val.toString()));