Skip to content

Commit 3109ed6

Browse files
authored
Merge pull request #754 from jeffgbutler/separate-empty-from-renderable
Refactoring Slice - Empty Conditions
2 parents 44b79f7 + 2d52703 commit 3109ed6

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

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

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

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

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

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

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

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

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

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ public class IsLikeCaseInsensitive extends AbstractSingleValueCondition<String>
2525
implements CaseInsensitiveVisitableCondition {
2626
private static final IsLikeCaseInsensitive EMPTY = new IsLikeCaseInsensitive(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/IsNotBetween.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525
public class IsNotBetween<T> extends AbstractTwoValueCondition<T> {
2626
private static final IsNotBetween<?> EMPTY = new IsNotBetween<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/IsNotEqualTo.java

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

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

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

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ public class IsNotLikeCaseInsensitive extends AbstractSingleValueCondition<Strin
2525
implements CaseInsensitiveVisitableCondition {
2626
private static final IsNotLikeCaseInsensitive EMPTY = new IsNotLikeCaseInsensitive(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/IsNotNull.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
public class IsNotNull<T> extends AbstractNoValueCondition<T> {
2323
private static final IsNotNull<?> EMPTY = new IsNotNull<Object>() {
2424
@Override
25-
public boolean shouldRender() {
26-
return false;
25+
public boolean isEmpty() {
26+
return true;
2727
}
2828
};
2929

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
public class IsNull<T> extends AbstractNoValueCondition<T> {
2323
private static final IsNull<?> EMPTY = new IsNull<Object>() {
2424
@Override
25-
public boolean shouldRender() {
26-
return false;
25+
public boolean isEmpty() {
26+
return true;
2727
}
2828
};
2929

src/main/java/org/mybatis/dynamic/sql/where/render/CriterionRenderer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ public Optional<RenderedCriterion> render(List<AndOrCriteriaGroup> subCriteria,
110110
}
111111

112112
private <T> Optional<FragmentAndParameters> renderColumnAndCondition(ColumnAndConditionCriterion<T> criterion) {
113-
if (criterion.condition().shouldRender()) {
113+
if (criterion.condition().shouldRender(renderingContext)) {
114114
return Optional.of(renderCondition(criterion));
115115
} else {
116116
criterion.condition().renderingSkipped();

0 commit comments

Comments
 (0)