1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.mybatis.dynamic.sql.common;
17
18 import static org.mybatis.dynamic.sql.util.StringUtilities.spaceAfter;
19
20 import java.util.Objects;
21 import java.util.Optional;
22 import java.util.stream.Collectors;
23
24 import org.jspecify.annotations.Nullable;
25 import org.mybatis.dynamic.sql.render.RenderingContext;
26 import org.mybatis.dynamic.sql.util.FragmentAndParameters;
27 import org.mybatis.dynamic.sql.util.FragmentCollector;
28 import org.mybatis.dynamic.sql.where.render.CriterionRenderer;
29 import org.mybatis.dynamic.sql.where.render.RenderedCriterion;
30
31 public abstract class AbstractBooleanExpressionRenderer {
32 protected final AbstractBooleanExpressionModel model;
33 private final String prefix;
34 private final CriterionRenderer criterionRenderer;
35 protected final RenderingContext renderingContext;
36
37 protected AbstractBooleanExpressionRenderer(String prefix, AbstractBuilder<?> builder) {
38 model = Objects.requireNonNull(builder.model);
39 this.prefix = Objects.requireNonNull(prefix);
40 renderingContext = Objects.requireNonNull(builder.renderingContext);
41 criterionRenderer = new CriterionRenderer(renderingContext);
42 }
43
44 public Optional<FragmentAndParameters> render() {
45 return criterionRenderer.render(model.initialCriterion(), model.subCriteria(), this::calculateClause)
46 .map(RenderedCriterion::fragmentAndParameters);
47 }
48
49 private String calculateClause(FragmentCollector collector) {
50 if (collector.hasMultipleFragments()) {
51 return collector.collectFragments(
52 Collectors.joining(" ", spaceAfter(prefix), ""));
53 } else {
54 return collector.firstFragment()
55 .map(this::stripEnclosingParenthesesIfPresent)
56 .map(this::addPrefix)
57 .orElse("");
58 }
59 }
60
61 private String stripEnclosingParenthesesIfPresent(String fragment) {
62
63
64 if (fragment.startsWith("(") && fragment.endsWith(")")) {
65 return fragment.substring(1, fragment.length() - 1);
66 } else {
67 return fragment;
68 }
69 }
70
71 private String addPrefix(String fragment) {
72 return spaceAfter(prefix) + fragment;
73 }
74
75 public abstract static class AbstractBuilder<B extends AbstractBuilder<B>> {
76 private final AbstractBooleanExpressionModel model;
77 private @Nullable RenderingContext renderingContext;
78
79 protected AbstractBuilder(AbstractBooleanExpressionModel model) {
80 this.model = model;
81 }
82
83 public B withRenderingContext(RenderingContext renderingContext) {
84 this.renderingContext = renderingContext;
85 return getThis();
86 }
87
88 protected abstract B getThis();
89 }
90 }