Skip to content

Commit 57fb7a1

Browse files
committed
Refactor Criterion Renderer
1 parent e554be6 commit 57fb7a1

File tree

7 files changed

+111
-112
lines changed

7 files changed

+111
-112
lines changed

src/main/java/org/mybatis/dynamic/sql/util/FragmentAndParameters.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,6 @@ public Map<String, Object> parameters() {
3838
return parameters;
3939
}
4040

41-
public FragmentAndParameters prependFragment(String s) {
42-
return FragmentAndParameters.withFragment(s + " " + fragment) //$NON-NLS-1$
43-
.withParameters(parameters)
44-
.build();
45-
}
46-
4741
public static Builder withFragment(String fragment) {
4842
return new Builder().withFragment(fragment);
4943
}

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

Lines changed: 75 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@
2525
import org.mybatis.dynamic.sql.render.RenderingStrategy;
2626
import org.mybatis.dynamic.sql.render.TableAliasCalculator;
2727
import org.mybatis.dynamic.sql.util.FragmentAndParameters;
28+
import org.mybatis.dynamic.sql.util.FragmentCollector;
2829

2930
public class CriterionRenderer<T> {
30-
private SqlCriterion<T> sqlCriterion;
31-
private AtomicInteger sequence;
32-
private RenderingStrategy renderingStrategy;
33-
private TableAliasCalculator tableAliasCalculator;
34-
private String parameterName;
31+
private final SqlCriterion<T> sqlCriterion;
32+
private final AtomicInteger sequence;
33+
private final RenderingStrategy renderingStrategy;
34+
private final TableAliasCalculator tableAliasCalculator;
35+
private final String parameterName;
3536

3637
private CriterionRenderer(Builder<T> builder) {
3738
sqlCriterion = Objects.requireNonNull(builder.sqlCriterion);
@@ -42,18 +43,34 @@ private CriterionRenderer(Builder<T> builder) {
4243
}
4344

4445
public Optional<RenderedCriterion> render() {
45-
Optional<FragmentAndParameters> initialCondition = renderCondition();
46-
46+
FragmentAndParameters initialCondition = null;
47+
if (sqlCriterion.condition().shouldRender()) {
48+
initialCondition = renderCondition();
49+
}
50+
4751
List<RenderedCriterion> subCriteria = sqlCriterion.mapSubCriteria(this::renderSubCriterion)
4852
.filter(Optional::isPresent)
4953
.map(Optional::get)
5054
.collect(Collectors.toList());
51-
52-
return new RenderedCriterion.Builder()
53-
.withConnector(sqlCriterion.connector())
54-
.withInitialCondition(initialCondition)
55-
.withSubCriteria(subCriteria)
55+
56+
RenderedCriterion rc;
57+
if (initialCondition == null) {
58+
rc = renderWithoutInitialCondition(subCriteria);
59+
} else {
60+
rc = renderWithInitialCondition(initialCondition, subCriteria);
61+
}
62+
63+
return Optional.ofNullable(rc);
64+
}
65+
66+
private FragmentAndParameters renderCondition() {
67+
WhereConditionVisitor<T> visitor = WhereConditionVisitor.withColumn(sqlCriterion.column())
68+
.withRenderingStrategy(renderingStrategy)
69+
.withSequence(sequence)
70+
.withTableAliasCalculator(tableAliasCalculator)
71+
.withParameterName(parameterName)
5672
.build();
73+
return sqlCriterion.condition().accept(visitor);
5774
}
5875

5976
private <S> Optional<RenderedCriterion> renderSubCriterion(SqlCriterion<S> subCriterion) {
@@ -66,18 +83,54 @@ private <S> Optional<RenderedCriterion> renderSubCriterion(SqlCriterion<S> subCr
6683
.render();
6784
}
6885

69-
private Optional<FragmentAndParameters> renderCondition() {
70-
if (!sqlCriterion.condition().shouldRender()) {
71-
return Optional.empty();
86+
private RenderedCriterion renderWithoutInitialCondition(List<RenderedCriterion> subCriteria) {
87+
if (subCriteria.isEmpty()) {
88+
return null;
7289
}
7390

74-
WhereConditionVisitor<T> visitor = WhereConditionVisitor.withColumn(sqlCriterion.column())
75-
.withRenderingStrategy(renderingStrategy)
76-
.withSequence(sequence)
77-
.withTableAliasCalculator(tableAliasCalculator)
78-
.withParameterName(parameterName)
79-
.build();
80-
return Optional.of(sqlCriterion.condition().accept(visitor));
91+
return calculateRenderedCriterion(subCriteria);
92+
}
93+
94+
private RenderedCriterion renderWithInitialCondition(FragmentAndParameters initialCondition,
95+
List<RenderedCriterion> subCriteria) {
96+
if (subCriteria.isEmpty()) {
97+
return fromFragmentAndParameters(initialCondition);
98+
}
99+
100+
return calculateRenderedCriterion(initialCondition, subCriteria);
101+
}
102+
103+
private RenderedCriterion fromFragmentAndParameters(FragmentAndParameters fragmentAndParameters) {
104+
RenderedCriterion.Builder builder = new RenderedCriterion.Builder()
105+
.withFragmentAndParameters(fragmentAndParameters);
106+
107+
sqlCriterion.connector().ifPresent(builder::withConnector);
108+
109+
return builder.build();
110+
}
111+
112+
private RenderedCriterion calculateRenderedCriterion(List<RenderedCriterion> subCriteria) {
113+
return calculateRenderedCriterion(subCriteria.get(0).fragmentAndParameters(),
114+
subCriteria.subList(1, subCriteria.size()));
115+
}
116+
117+
private RenderedCriterion calculateRenderedCriterion(FragmentAndParameters initialCondition, List<RenderedCriterion> subCriteria) {
118+
FragmentCollector fc = subCriteria.stream()
119+
.map(RenderedCriterion::fragmentAndParametersWithConnector)
120+
.collect(FragmentCollector.collect(initialCondition));
121+
String fragment = calculateFragment(fc);
122+
return fromFragmentAndParameters(FragmentAndParameters.withFragment(fragment)
123+
.withParameters(fc.parameters())
124+
.build());
125+
}
126+
127+
private String calculateFragment(FragmentCollector collector) {
128+
if (collector.hasMultipleFragments()) {
129+
return collector.fragments()
130+
.collect(Collectors.joining(" ", "(", ")")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
131+
} else {
132+
return collector.fragments().findFirst().orElse(""); //$NON-NLS-1$
133+
}
81134
}
82135

83136
public static <T> Builder<T> withCriterion(SqlCriterion<T> sqlCriterion) {
@@ -94,7 +147,6 @@ public static class Builder<T> {
94147
public Builder<T> withCriterion(SqlCriterion<T> sqlCriterion) {
95148
this.sqlCriterion = sqlCriterion;
96149
return this;
97-
98150
}
99151

100152
public Builder<T> withSequence(AtomicInteger sequence) {

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

Lines changed: 24 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -15,97 +15,53 @@
1515
*/
1616
package org.mybatis.dynamic.sql.where.render;
1717

18-
import java.util.ArrayList;
19-
import java.util.List;
2018
import java.util.Objects;
21-
import java.util.Optional;
22-
import java.util.stream.Collectors;
2319

2420
import org.mybatis.dynamic.sql.util.FragmentAndParameters;
25-
import org.mybatis.dynamic.sql.util.FragmentCollector;
2621

2722
public class RenderedCriterion {
28-
private Optional<String> connector;
29-
private Optional<FragmentAndParameters> initialCondition;
30-
private List<RenderedCriterion> subCriteria;
31-
32-
private RenderedCriterion(Builder builder) {
33-
connector = Objects.requireNonNull(builder.connector);
34-
initialCondition = Objects.requireNonNull(builder.initialCondition);
35-
subCriteria = Objects.requireNonNull(builder.subCriteria);
36-
}
37-
38-
public FragmentAndParameters renderWithInitialConnector() {
39-
FragmentAndParameters fp = renderWithoutInitialConnector();
40-
41-
return connector.map(fp::prependFragment).orElse(fp);
42-
}
43-
44-
public FragmentAndParameters renderWithoutInitialConnector() {
45-
FragmentCollector fc = internalRender();
23+
private String connector;
24+
private FragmentAndParameters fragmentAndParameters;
4625

47-
String fragment = calculateFragment(fc);
48-
49-
return FragmentAndParameters.withFragment(fragment)
50-
.withParameters(fc.parameters())
51-
.build();
26+
private RenderedCriterion(Builder builder) {
27+
connector = builder.connector;
28+
fragmentAndParameters = Objects.requireNonNull(builder.fragmentAndParameters);
5229
}
5330

54-
private FragmentCollector internalRender() {
55-
return initialCondition.map(this::renderConditionAndSubCriteria)
56-
.orElseGet(this::renderSubCriteriaOnly);
31+
public FragmentAndParameters fragmentAndParameters() {
32+
return fragmentAndParameters;
5733
}
5834

59-
private FragmentCollector renderSubCriteriaOnly() {
60-
FragmentAndParameters initial = subCriteria.get(0).renderWithoutInitialConnector();
61-
62-
return subCriteria.stream()
63-
.skip(1)
64-
.map(RenderedCriterion::renderWithInitialConnector)
65-
.collect(FragmentCollector.collect(initial));
35+
public FragmentAndParameters fragmentAndParametersWithConnector() {
36+
if (connector == null) {
37+
return fragmentAndParameters;
38+
} else {
39+
return prependFragment(fragmentAndParameters, connector);
40+
}
6641
}
6742

68-
private FragmentCollector renderConditionAndSubCriteria(FragmentAndParameters initialCondition) {
69-
return subCriteria.stream()
70-
.map(RenderedCriterion::renderWithInitialConnector)
71-
.collect(FragmentCollector.collect(initialCondition));
43+
private FragmentAndParameters prependFragment(FragmentAndParameters fragmentAndParameters, String connector) {
44+
return FragmentAndParameters.withFragment(connector + " " + fragmentAndParameters.fragment()) //$NON-NLS-1$
45+
.withParameters(fragmentAndParameters.parameters())
46+
.build();
7247
}
7348

74-
private String calculateFragment(FragmentCollector collector) {
75-
if (collector.hasMultipleFragments()) {
76-
return collector.fragments()
77-
.collect(Collectors.joining(" ", "(", ")")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
78-
} else {
79-
return collector.fragments().findFirst().orElse(""); //$NON-NLS-1$
80-
}
81-
}
82-
8349
public static class Builder {
84-
private Optional<String> connector = Optional.empty();
85-
private Optional<FragmentAndParameters> initialCondition = Optional.empty();
86-
private List<RenderedCriterion> subCriteria = new ArrayList<>();
50+
private String connector;
51+
private FragmentAndParameters fragmentAndParameters;
8752

88-
public Builder withConnector(Optional<String> connector) {
53+
public Builder withConnector(String connector) {
8954
this.connector = connector;
9055
return this;
9156
}
9257

93-
public Builder withInitialCondition(Optional<FragmentAndParameters> initialCondition) {
94-
this.initialCondition = initialCondition;
58+
public Builder withFragmentAndParameters(FragmentAndParameters fragmentAndParameters) {
59+
this.fragmentAndParameters = fragmentAndParameters;
9560
return this;
9661
}
9762

98-
public Builder withSubCriteria(List<RenderedCriterion> subCriteria) {
99-
this.subCriteria.addAll(subCriteria);
100-
return this;
101-
}
102-
103-
public Optional<RenderedCriterion> build() {
104-
if (!initialCondition.isPresent() && subCriteria.isEmpty()) {
105-
return Optional.empty();
106-
}
107-
108-
return Optional.of(new RenderedCriterion(this));
63+
public RenderedCriterion build() {
64+
return new RenderedCriterion(this);
10965
}
11066
}
11167
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,11 @@ public Optional<WhereClauseProvider> render() {
5555

5656
// The first is rendered without the initial connector because we don't want something like
5757
// where and(id = ?). This can happen if the first condition doesn't render.
58-
FragmentAndParameters initialCriterion = renderedCriteria.get(0).renderWithoutInitialConnector();
58+
FragmentAndParameters initialCriterion = renderedCriteria.get(0).fragmentAndParameters();
5959

6060
FragmentCollector fc = renderedCriteria.stream()
6161
.skip(1)
62-
.map(RenderedCriterion::renderWithInitialConnector)
62+
.map(RenderedCriterion::fragmentAndParametersWithConnector)
6363
.collect(FragmentCollector.collect(initialCriterion));
6464

6565
WhereClauseProvider wcp = WhereClauseProvider.withWhereClause(calculateWhereClause(fc))

src/test/java/org/mybatis/dynamic/sql/mybatis3/CriterionRendererTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ void testAliasWithIgnore() {
5252
.build()
5353
.render()
5454
.get()
55-
.renderWithInitialConnector();
55+
.fragmentAndParametersWithConnector();
5656

5757
assertAll(
5858
() -> assertThat(fp.fragment()).isEqualTo("id = #{parameters.p1,jdbcType=INTEGER}"),
@@ -78,7 +78,7 @@ void testAliasWithoutIgnore() {
7878
.build()
7979
.render()
8080
.get()
81-
.renderWithInitialConnector();
81+
.fragmentAndParametersWithConnector();
8282

8383
assertAll(
8484
() -> assertThat(fp.fragment()).isEqualTo("a.id = #{parameters.p1,jdbcType=INTEGER}"),
@@ -106,7 +106,7 @@ void testTypeHandler() {
106106
.build()
107107
.render()
108108
.get()
109-
.renderWithInitialConnector();
109+
.fragmentAndParametersWithConnector();
110110

111111
assertAll(
112112
() -> assertThat(fp.fragment()).isEqualTo("id = #{parameters.p1,jdbcType=DATE,typeHandler=foo.Bar}"),
@@ -133,7 +133,7 @@ void testTypeHandlerAndAlias() {
133133
.build()
134134
.render()
135135
.get()
136-
.renderWithInitialConnector();
136+
.fragmentAndParametersWithConnector();
137137

138138
assertAll(
139139
() -> assertThat(fp.fragment()).isEqualTo("a.id = #{parameters.p1,jdbcType=INTEGER,typeHandler=foo.Bar}"),

src/test/java/org/mybatis/dynamic/sql/where/render/CriterionRendererTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ void testAliasWithIgnore() {
5151
.build()
5252
.render()
5353
.get()
54-
.renderWithInitialConnector();
54+
.fragmentAndParametersWithConnector();
5555

5656
assertThat(fp.fragment()).isEqualTo("id = #{parameters.p1,jdbcType=INTEGER}");
5757
assertThat(fp.parameters()).containsExactly(entry("p1", 3));
@@ -77,7 +77,7 @@ void testAliasWithoutIgnore() {
7777
.build()
7878
.render()
7979
.get()
80-
.renderWithInitialConnector();
80+
.fragmentAndParametersWithConnector();
8181

8282
assertThat(fp.fragment()).isEqualTo("a.id = #{parameters.p1,jdbcType=INTEGER}");
8383
assertThat(fp.parameters()).containsExactly(entry("p1", 3));

src/test/java/org/mybatis/dynamic/sql/where/render/RenderedCriterionTest.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818
import static org.assertj.core.api.Assertions.assertThat;
1919
import static org.junit.jupiter.api.Assertions.assertAll;
2020

21-
import java.util.Optional;
22-
2321
import org.junit.jupiter.api.Test;
2422
import org.mybatis.dynamic.sql.util.FragmentAndParameters;
2523

@@ -28,12 +26,11 @@ class RenderedCriterionTest {
2826
@Test
2927
void testSimpleCriteria() {
3028
RenderedCriterion rc = new RenderedCriterion.Builder()
31-
.withConnector(Optional.of("and"))
32-
.withInitialCondition(FragmentAndParameters.withFragment("col1 = :p1").buildOptional())
33-
.build()
34-
.get();
29+
.withConnector("and")
30+
.withFragmentAndParameters(FragmentAndParameters.withFragment("col1 = :p1").build())
31+
.build();
3532

36-
FragmentAndParameters fp = rc.renderWithInitialConnector();
33+
FragmentAndParameters fp = rc.fragmentAndParametersWithConnector();
3734

3835
assertAll(
3936
() -> assertThat(fp.fragment()).isEqualTo("and col1 = :p1"),

0 commit comments

Comments
 (0)