Skip to content

Commit 2d52703

Browse files
committed
Refactoring Slice - Empty Conditions
This change separates the concept of an empty condition from that of a renderable condition. This will enable a future change where conditions could decide to allow rendering even if they are considered empty (such as rendering empty lists). This change should be transparent to users unless they have implemented custom conditions.
1 parent 4c21023 commit 2d52703

24 files changed

+190
-175
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ types - which is a rare usage. Please let us know if this causes an undo hardshi
3939
your code accordingly. ([#662](https://github.com/mybatis/mybatis-dynamic-sql/pull/662))
4040
2. Added the ability to code a bound value in rendered SQL. This is similar to a constant, but the value is added to
4141
the parameter map and a bind parameter marker is rendered. ([#738](https://github.com/mybatis/mybatis-dynamic-sql/pull/738))
42+
3. Refactored the conditions to separate the concept of an empty condition from that of a renderable condition. This
43+
will enable a future change where conditions could decide to allow rendering even if they are considered empty (such
44+
as rendering empty lists). This change should be transparent to users unless they have implemented custom conditions.
4245

4346
## Release 1.5.0 - April 21, 2023
4447

src/main/java/org/mybatis/dynamic/sql/AbstractListValueCondition.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ public final <R> Stream<R> mapValues(Function<T, R> mapper) {
3535
}
3636

3737
@Override
38-
public boolean shouldRender() {
39-
return !values.isEmpty();
38+
public boolean isEmpty() {
39+
return values.isEmpty();
4040
}
4141

4242
@Override
@@ -56,20 +56,20 @@ private Collection<T> applyFilter(Predicate<? super T> predicate) {
5656

5757
protected <S extends AbstractListValueCondition<T>> S filterSupport(Predicate<? super T> predicate,
5858
Function<Collection<T>, S> constructor, S self, Supplier<S> emptySupplier) {
59-
if (shouldRender()) {
59+
if (isEmpty()) {
60+
return self;
61+
} else {
6062
Collection<T> filtered = applyFilter(predicate);
6163
return filtered.isEmpty() ? emptySupplier.get() : constructor.apply(filtered);
62-
} else {
63-
return self;
6464
}
6565
}
6666

6767
protected <R, S extends AbstractListValueCondition<R>> S mapSupport(Function<? super T, ? extends R> mapper,
6868
Function<Collection<R>, S> constructor, Supplier<S> emptySupplier) {
69-
if (shouldRender()) {
70-
return constructor.apply(applyMapper(mapper));
71-
} else {
69+
if (isEmpty()) {
7270
return emptySupplier.get();
71+
} else {
72+
return constructor.apply(applyMapper(mapper));
7373
}
7474
}
7575

src/main/java/org/mybatis/dynamic/sql/AbstractNoValueCondition.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ public <R> R accept(ConditionVisitor<T, R> visitor) {
2727

2828
protected <S extends AbstractNoValueCondition<?>> S filterSupport(BooleanSupplier booleanSupplier,
2929
Supplier<S> emptySupplier, S self) {
30-
if (shouldRender()) {
31-
return booleanSupplier.getAsBoolean() ? self : emptySupplier.get();
32-
} else {
30+
if (isEmpty()) {
3331
return self;
32+
} else {
33+
return booleanSupplier.getAsBoolean() ? self : emptySupplier.get();
3434
}
3535
}
3636

src/main/java/org/mybatis/dynamic/sql/AbstractSingleValueCondition.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,19 @@ public <R> R accept(ConditionVisitor<T, R> visitor) {
3737

3838
protected <S extends AbstractSingleValueCondition<T>> S filterSupport(Predicate<? super T> predicate,
3939
Supplier<S> emptySupplier, S self) {
40-
if (shouldRender()) {
41-
return predicate.test(value) ? self : emptySupplier.get();
42-
} else {
40+
if (isEmpty()) {
4341
return self;
42+
} else {
43+
return predicate.test(value) ? self : emptySupplier.get();
4444
}
4545
}
4646

4747
protected <R, S extends AbstractSingleValueCondition<R>> S mapSupport(Function<? super T, ? extends R> mapper,
4848
Function<R, S> constructor, Supplier<S> emptySupplier) {
49-
if (shouldRender()) {
50-
return constructor.apply(mapper.apply(value));
51-
} else {
49+
if (isEmpty()) {
5250
return emptySupplier.get();
51+
} else {
52+
return constructor.apply(mapper.apply(value));
5353
}
5454
}
5555

src/main/java/org/mybatis/dynamic/sql/AbstractTwoValueCondition.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ public <R> R accept(ConditionVisitor<T, R> visitor) {
4545

4646
protected <S extends AbstractTwoValueCondition<T>> S filterSupport(BiPredicate<? super T, ? super T> predicate,
4747
Supplier<S> emptySupplier, S self) {
48-
if (shouldRender()) {
49-
return predicate.test(value1, value2) ? self : emptySupplier.get();
50-
} else {
48+
if (isEmpty()) {
5149
return self;
50+
} else {
51+
return predicate.test(value1, value2) ? self : emptySupplier.get();
5252
}
5353
}
5454

@@ -59,10 +59,10 @@ protected <S extends AbstractTwoValueCondition<T>> S filterSupport(Predicate<? s
5959

6060
protected <R, S extends AbstractTwoValueCondition<R>> S mapSupport(Function<? super T, ? extends R> mapper1,
6161
Function<? super T, ? extends R> mapper2, BiFunction<R, R, S> constructor, Supplier<S> emptySupplier) {
62-
if (shouldRender()) {
63-
return constructor.apply(mapper1.apply(value1), mapper2.apply(value2));
64-
} else {
62+
if (isEmpty()) {
6563
return emptySupplier.get();
64+
} else {
65+
return constructor.apply(mapper1.apply(value1), mapper2.apply(value2));
6666
}
6767
}
6868

src/main/java/org/mybatis/dynamic/sql/VisitableCondition.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,34 @@
1515
*/
1616
package org.mybatis.dynamic.sql;
1717

18+
import org.mybatis.dynamic.sql.render.RenderingContext;
19+
1820
@FunctionalInterface
1921
public interface VisitableCondition<T> {
2022
<R> R accept(ConditionVisitor<T, R> visitor);
2123

2224
/**
2325
* Subclasses can override this to inform the renderer if the condition should not be included
24-
* in the rendered SQL. For example, IsEqualWhenPresent will not render if the value is null.
26+
* in the rendered SQL. Typically, conditions will not render if they are empty.
2527
*
2628
* @return true if the condition should render.
2729
*/
28-
default boolean shouldRender() {
29-
return true;
30+
default boolean shouldRender(RenderingContext renderingContext) {
31+
return !isEmpty();
32+
}
33+
34+
/**
35+
* Subclasses can override this to indicate whether the condition is considered empty. This is primarily used in
36+
* map and filter operations - the map and filter functions will not be applied if the condition is empty.
37+
*
38+
* @return true if the condition is empty.
39+
*/
40+
default boolean isEmpty() {
41+
return false;
3042
}
3143

3244
/**
33-
* This method will be called during rendering when {@link VisitableCondition#shouldRender()}
45+
* This method will be called during rendering when {@link VisitableCondition#shouldRender(RenderingContext)}
3446
* returns false.
3547
*/
3648
default void renderingSkipped() {}

src/main/java/org/mybatis/dynamic/sql/select/aggregate/Sum.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ private Sum(BindableColumn<T> column) {
3636
private Sum(BindableColumn<T> column, VisitableCondition<T> condition) {
3737
super(column);
3838
renderer = rc -> {
39-
Validator.assertTrue(condition.shouldRender(), "ERROR.37", "sum"); //$NON-NLS-1$ //$NON-NLS-2$
39+
Validator.assertTrue(condition.shouldRender(rc), "ERROR.37", "sum"); //$NON-NLS-1$ //$NON-NLS-2$
4040

4141
DefaultConditionVisitor<T> visitor = new DefaultConditionVisitor.Builder<T>()
4242
.withColumn(column)

src/main/java/org/mybatis/dynamic/sql/where/condition/IsBetween.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525
public class IsBetween<T> extends AbstractTwoValueCondition<T> {
2626
private static final IsBetween<?> EMPTY = new IsBetween<Object>(null, null) {
2727
@Override
28-
public boolean shouldRender() {
29-
return false;
28+
public boolean isEmpty() {
29+
return true;
3030
}
3131
};
3232

src/main/java/org/mybatis/dynamic/sql/where/condition/IsEqualTo.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ public class IsEqualTo<T> extends AbstractSingleValueCondition<T> {
2424

2525
private static final IsEqualTo<?> EMPTY = new IsEqualTo<Object>(null) {
2626
@Override
27-
public boolean shouldRender() {
28-
return false;
27+
public boolean isEmpty() {
28+
return true;
2929
}
3030
};
3131

src/main/java/org/mybatis/dynamic/sql/where/condition/IsGreaterThan.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
public class IsGreaterThan<T> extends AbstractSingleValueCondition<T> {
2424
private static final IsGreaterThan<?> EMPTY = new IsGreaterThan<Object>(null) {
2525
@Override
26-
public boolean shouldRender() {
27-
return false;
26+
public boolean isEmpty() {
27+
return true;
2828
}
2929
};
3030

0 commit comments

Comments
 (0)