Supongamos que queremos realizar una búsqueda de registros en Base de Datos y para ello utilizamos QueryDsl. Si tenemos parámetros optativos tendremos que montar una estructura de if’s de la siguiente forma:
[java]protected BooleanBuilder buildPredicate(final AreaCriteria criteria) {
QArea qArea = QArea.area;
BooleanBuilder booleanBuilder = new BooleanBuilder();
if (Boolean.TRUE.equals(criteria.getActive()) {
booleanBuilder.and(qArea.active.isTrue());
}
if (criteria.getAreaId() != null) {
booleanBuilder.and(qArea.areaId.eq(criteria.getAreaId()));
}
if (criteria.getAreaTitle() != null && !criteria.getAreaTitle().isEmpty()) {
booleanBuilder.and(qArea.areaTitle.containsIgnoreCase(criteria.getAreaTitle()));
}
return booleanBuilder;
}
[/java]Como vemos llenamos el código de if’s que vamos a intentar eliminar utilizando las FunctionalInterfaces de Java 8.
Dado que BooleanBuilder es una clase final y no podemos extenderla, lo que haremos será crear una nueva clase envoltorio, es decir, un Wrapper).
[java]public class BooleanBuilderExt implements Predicate, Cloneable {
private static final long serialVersionUID = 1L;
@Nullable
private BooleanBuilder booleanBuilder;
public BooleanBuilderExt() {
}
public BooleanBuilderExt(final Predicate initial) {
}
@Override
public <R, C> R accept(final Visitor<R, C> v, final C context) {
}
public BooleanBuilderExt and(@Nullable final Predicate right) {
}
public BooleanBuilderExt andAnyOf(final Predicate… args) {
}
public BooleanBuilderExt andIfFalse(final Boolean filter, final Supplier<Predicate> predicator) {
booleanBuilder = new BooleanBuilder();
booleanBuilder = new BooleanBuilder(initial);
return booleanBuilder.accept(v, context);
booleanBuilder.and(right);
return this;
booleanBuilder.andAnyOf(args);
return this;
if (Boolean.FALSE.equals(filter)) {
booleanBuilder.and(predicator.get());
}
return this;
}
public BooleanBuilderExt andIfNotFalse(final Boolean filter, final Supplier<Predicate> predicator) {
if (!Boolean.FALSE.equals(filter)) {
booleanBuilder.and(predicator.get());
}
return this;
}
public BooleanBuilderExt andIfNotTrue(final Boolean filter, final Supplier<Predicate> predicator) {
if (!Boolean.TRUE.equals(filter)) {
booleanBuilder.and(predicator.get());
}
return this;
}
public <T> BooleanBuilderExt andIfPresent(final T filter, final Function<T, Predicate> predicator) {
if (!isEmpty(filter)) {
booleanBuilder.and(predicator.apply(filter));
}
return this;
}
public BooleanBuilderExt andIfTrue(final Boolean filter, final Supplier<Predicate> predicator) {
if (Boolean.TRUE.equals(filter)) {
booleanBuilder.and(predicator.get());
}
return this;
}
public BooleanBuilderExt andIfTrueFalse(final Boolean filter, final Supplier<Predicate> predicatorTrue, final
Supplier<Predicate> predicatorFalse) {
if (Boolean.TRUE.equals(filter)) {
booleanBuilder.and(predicatorTrue.get());
} else if (Boolean.FALSE.equals(filter)) {
booleanBuilder.and(predicatorFalse.get());
}
return this;
}
public BooleanBuilderExt andNot(final Predicate right) {
}
public boolean equals(final Object o) {
booleanBuilder.andNot(right);
return this;
if (o == this) {
return true;
} else if (o instanceof BooleanBuilderExt) {
return Objects.equal(((BooleanBuilderExt) o).getValue(), getValue());
} else {
return false;
}
}
@Override
public Class<? extends Boolean> getType() {
}
return booleanBuilder.getType();
public Predicate getValue() {
return booleanBuilder.getValue();
}
public int hashCode() {
if (booleanBuilder == null) {
}
return booleanBuilder.hashCode();
}
public boolean hasValue() {
return booleanBuilder.hasValue();
}
@Override
public BooleanBuilderExt not() {
booleanBuilder.not();
return this;
}
public BooleanBuilderExt or(@Nullable final Predicate right) {
booleanBuilder.or(right);
return this;
}
public BooleanBuilderExt orAllOf(final Predicate… args) {
booleanBuilder.orAllOf(args);
return this;
}
public BooleanBuilderExt orIfFalse(final Boolean filter, final Supplier<Predicate> predicator) {
if (Boolean.FALSE.equals(filter)) {
}
return this;
}
public BooleanBuilderExt orIfNotFalse(final Boolean filter, final Supplier<Predicate> predicator) {
if (!Boolean.FALSE.equals(filter)) {
}
return this;
}
public BooleanBuilderExt orIfNotTrue(final Boolean filter, final Supplier<Predicate> predicator) {
if (!Boolean.TRUE.equals(filter)) {
}
return this;
}
public <T> BooleanBuilderExt orIfPresent(final T filter, final Function<T, Predicate> predicator) {
if (!isEmpty(filter)) {
}
return this;
}
public BooleanBuilderExt orIfTrue(final Boolean filter, final Supplier<Predicate> predicator) {
return 0;
booleanBuilder.or(predicator.get());
booleanBuilder.or(predicator.get());
booleanBuilder.or(predicator.get());
booleanBuilder.or(predicator.apply(filter));
if (Boolean.TRUE.equals(filter)) {
booleanBuilder.or(predicator.get());
}
return this;
}
public BooleanBuilderExt orNot(final Predicate right) {
}
public String toString() {
}
public BooleanBuilderExt clone() throws CloneNotSupportedException {
}
private boolean isEmpty(final Object object) {
&& ((Collection<?>) object).isEmpty();
}
}
[/java]Como vemos básicamente lo que hemos hecho es tener un atributo con el booleanBuilder al que redirigiremos todas las llamadas que ya tenía (accept, and, andAnyOf, andNot, or, orAllOf, …).
Hemos añadido por ejemplo una función que revise si el filtro que se le pase tiene valor y añada al booleanBuilder un and (con el resultado de la función pasada como parámetro). Usaremos para ello un Function (expresión lambda que recibe un argumento y devuelve un resultado):
[java]public <T> BooleanBuilderExt andIfPresent(final T filter, final Function<T, Predicate> predicator) {
booleanBuilder.orNot(right);
return this;
return booleanBuilder.toString();
return (BooleanBuilderExt) super.clone();
return object == null || object instanceof String && ((String) object).isEmpty() || object instanceof Collection
if (!isEmpty(filter)) {
booleanBuilder.and(predicator.apply(filter));
}
return this;
}
[/java]Otro ejemplo añadido sería una función que añada un and (con el resultado de la función pasada como parámetro) sólo si lo que se pase en el parámetro filter es un TRUE. En este caso utilizaremos un Supplier (expresión lambda sin argumentos que devuelve un resultado):
[java]public BooleanBuilderExt andIfTrue(final Boolean filter, final Supplier<Predicate> predicator) {
if (Boolean.TRUE.equals(filter)) {
booleanBuilder.and(predicator.get());
}
return this;
}
[/java]Como ejemplo de uso, ahora el código anterior lo podemos cambiar por:
[java]protected BooleanBuilderExt buildPredicate(final AreaCriteria criteria) {
QArea qArea = QArea.area;
BooleanBuilderExt booleanBuilder = new BooleanBuilderExt();
booleanBuilder.andIfTrue(criteria.getActive(), () -> qArea.active.isTrue());
booleanBuilder.andIfPresent(criteria.getAreaId(), s -> qArea.areaId.eq(s));
booleanBuilder.andIfPresent(criteria.getAreaTitle(), s -> qArea.areaTitle.containsIgnoreCase(s));
return booleanBuilder;
}
[/java]Como vemos hemos logrado minimizar las líneas de código, haciéndolo mucho más legible. Y, ya se sabe… cuantas menos líneas existan, menos posibilidad de error tendremos.
Leave a Reply