Skip to content

Commit 8d97fdd

Browse files
committed
Polishing.
Use switch expressions, extract variables where possible. Simplify comparisons and combine common predicate blocks. Use simpler types where possible. See #603 Original pull request: #604
1 parent 768d0a8 commit 8d97fdd

File tree

4 files changed

+107
-89
lines changed

4 files changed

+107
-89
lines changed

src/main/antora/modules/ROOT/pages/repositories.adoc

-1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,3 @@ This chapter explains the basic foundations of Spring Data repositories and KeyV
55
Before continuing to the specifics, make sure you have a sound understanding of the basic concepts.
66

77
The goal of the Spring Data repository abstraction is to significantly reduce the amount of boilerplate code required to implement data access layers for various persistence stores.
8-

src/main/java/org/springframework/data/keyvalue/repository/query/PredicateQueryCreator.java

+35-53
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
*
4343
* @author Christoph Strobl
4444
* @author Tom Van Wemmel
45+
* @author Mark Paluch
4546
* @since 3.3
4647
*/
4748
public class PredicateQueryCreator extends AbstractQueryCreator<KeyValueQuery<Predicate<?>>, Predicate<?>> {
@@ -55,68 +56,47 @@ public PredicateQueryCreator(PartTree tree, ParameterAccessor parameters) {
5556
@Override
5657
protected Predicate<?> create(Part part, Iterator<Object> iterator) {
5758

58-
switch (part.getType()) {
59-
case TRUE:
60-
return PredicateBuilder.propertyValueOf(part).isTrue();
61-
case FALSE:
62-
return PredicateBuilder.propertyValueOf(part).isFalse();
63-
case SIMPLE_PROPERTY:
64-
return PredicateBuilder.propertyValueOf(part).isEqualTo(iterator.next());
65-
case NEGATING_SIMPLE_PROPERTY:
66-
return PredicateBuilder.propertyValueOf(part).isEqualTo(iterator.next()).negate();
67-
case IS_NULL:
68-
return PredicateBuilder.propertyValueOf(part).isNull();
69-
case IS_NOT_NULL:
70-
return PredicateBuilder.propertyValueOf(part).isNotNull();
71-
case LIKE:
72-
return PredicateBuilder.propertyValueOf(part).contains(iterator.next());
73-
case NOT_LIKE:
74-
return PredicateBuilder.propertyValueOf(part).contains(iterator.next()).negate();
75-
case STARTING_WITH:
76-
return PredicateBuilder.propertyValueOf(part).startsWith(iterator.next());
77-
case AFTER:
78-
case GREATER_THAN:
79-
return PredicateBuilder.propertyValueOf(part).isGreaterThan(iterator.next());
80-
case GREATER_THAN_EQUAL:
81-
return PredicateBuilder.propertyValueOf(part).isGreaterThanEqual(iterator.next());
82-
case BEFORE:
83-
case LESS_THAN:
84-
return PredicateBuilder.propertyValueOf(part).isLessThan(iterator.next());
85-
case LESS_THAN_EQUAL:
86-
return PredicateBuilder.propertyValueOf(part).isLessThanEqual(iterator.next());
87-
case ENDING_WITH:
88-
return PredicateBuilder.propertyValueOf(part).endsWith(iterator.next());
89-
case BETWEEN:
90-
return PredicateBuilder.propertyValueOf(part).isGreaterThan(iterator.next())
91-
.and(PredicateBuilder.propertyValueOf(part).isLessThan(iterator.next()));
92-
case REGEX:
93-
return PredicateBuilder.propertyValueOf(part).matches(iterator.next());
94-
case IN:
95-
return PredicateBuilder.propertyValueOf(part).in(iterator.next());
96-
case NOT_IN:
97-
return PredicateBuilder.propertyValueOf(part).in(iterator.next()).negate();
98-
default:
59+
PredicateBuilder builder = PredicateBuilder.propertyValueOf(part);
60+
61+
return switch (part.getType()) {
62+
case TRUE -> builder.isTrue();
63+
case FALSE -> builder.isFalse();
64+
case SIMPLE_PROPERTY -> builder.isEqualTo(iterator.next());
65+
case NEGATING_SIMPLE_PROPERTY -> builder.isEqualTo(iterator.next()).negate();
66+
case IS_NULL -> builder.isNull();
67+
case IS_NOT_NULL -> builder.isNotNull();
68+
case LIKE -> builder.contains(iterator.next());
69+
case NOT_LIKE -> builder.contains(iterator.next()).negate();
70+
case STARTING_WITH -> builder.startsWith(iterator.next());
71+
case AFTER, GREATER_THAN -> builder.isGreaterThan(iterator.next());
72+
case GREATER_THAN_EQUAL -> builder.isGreaterThanEqual(iterator.next());
73+
case BEFORE, LESS_THAN -> builder.isLessThan(iterator.next());
74+
case LESS_THAN_EQUAL -> builder.isLessThanEqual(iterator.next());
75+
case ENDING_WITH -> builder.endsWith(iterator.next());
76+
case BETWEEN -> builder.isGreaterThan(iterator.next()).and(builder.isLessThan(iterator.next()));
77+
case REGEX -> builder.matches(iterator.next());
78+
case IN -> builder.in(iterator.next());
79+
case NOT_IN -> builder.in(iterator.next()).negate();
80+
default ->
9981
throw new InvalidDataAccessApiUsageException(String.format("Found invalid part '%s' in query", part.getType()));
100-
101-
}
82+
};
10283
}
10384

10485
@Override
86+
@SuppressWarnings({ "unchecked", "rawtypes" })
10587
protected Predicate<?> and(Part part, Predicate<?> base, Iterator<Object> iterator) {
10688
return base.and((Predicate) create(part, iterator));
10789
}
10890

10991
@Override
92+
@SuppressWarnings({ "unchecked", "rawtypes" })
11093
protected Predicate<?> or(Predicate<?> base, Predicate<?> criteria) {
11194
return base.or((Predicate) criteria);
11295
}
11396

11497
@Override
11598
protected KeyValueQuery<Predicate<?>> complete(@Nullable Predicate<?> criteria, Sort sort) {
116-
if (criteria == null) {
117-
return new KeyValueQuery<>(it -> true, sort);
118-
}
119-
return new KeyValueQuery<>(criteria, sort);
99+
return criteria == null ? new KeyValueQuery<>(it -> true, sort) : new KeyValueQuery<>(criteria, sort);
120100
}
121101

122102
static class PredicateBuilder {
@@ -127,6 +107,7 @@ public PredicateBuilder(Part part) {
127107
this.part = part;
128108
}
129109

110+
@SuppressWarnings("unchecked")
130111
static <T> Comparator<T> comparator() {
131112
return (Comparator<T>) COMPARATOR;
132113
}
@@ -165,19 +146,19 @@ public Predicate<Object> isNotNull() {
165146
}
166147

167148
public Predicate<Object> isLessThan(Object value) {
168-
return new ValueComparingPredicate(part.getProperty(), o -> comparator().compare(o, value) == -1 ? true : false);
149+
return new ValueComparingPredicate(part.getProperty(), o -> comparator().compare(o, value) < 0);
169150
}
170151

171152
public Predicate<Object> isLessThanEqual(Object value) {
172-
return new ValueComparingPredicate(part.getProperty(), o -> comparator().compare(o, value) <= 0 ? true : false);
153+
return new ValueComparingPredicate(part.getProperty(), o -> comparator().compare(o, value) <= 0);
173154
}
174155

175156
public Predicate<Object> isGreaterThan(Object value) {
176-
return new ValueComparingPredicate(part.getProperty(), o -> comparator().compare(o, value) == 1 ? true : false);
157+
return new ValueComparingPredicate(part.getProperty(), o -> comparator().compare(o, value) > 0);
177158
}
178159

179160
public Predicate<Object> isGreaterThanEqual(Object value) {
180-
return new ValueComparingPredicate(part.getProperty(), o -> comparator().compare(o, value) >= 0 ? true : false);
161+
return new ValueComparingPredicate(part.getProperty(), o -> comparator().compare(o, value) >= 0);
181162
}
182163

183164
public Predicate<Object> matches(Pattern pattern) {
@@ -217,8 +198,9 @@ public Predicate<Object> in(Object value) {
217198
if (value instanceof Collection<?> collection) {
218199

219200
if (o instanceof Collection<?> subSet) {
220-
collection.containsAll(subSet);
201+
return collection.containsAll(subSet);
221202
}
203+
222204
return collection.contains(o);
223205
}
224206
if (ObjectUtils.isArray(value)) {
@@ -246,7 +228,7 @@ public Predicate<Object> contains(Object value) {
246228
}
247229

248230
if (o instanceof Map<?, ?> map) {
249-
return map.values().contains(value);
231+
return map.containsValue(value);
250232
}
251233

252234
if (value == null) {

src/main/java/org/springframework/data/keyvalue/repository/query/SpelQueryCreator.java

+22-16
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,14 @@ protected SpelExpression toPredicateExpression(PartTree tree) {
119119
partBuilder.append("?.equals(false)");
120120
break;
121121
case SIMPLE_PROPERTY:
122-
partBuilder.append("?.equals(").append("[").append(parameterIndex++).append("])");
123-
break;
124122
case NEGATING_SIMPLE_PROPERTY:
125-
partBuilder.append("?.equals(").append("[").append(parameterIndex++).append("]) == false");
123+
124+
partBuilder.append("?.equals(").append("[").append(parameterIndex++).append("])");
125+
126+
if (part.getType() == Type.NEGATING_SIMPLE_PROPERTY) {
127+
partBuilder.append(" == false");
128+
}
129+
126130
break;
127131
case IS_NULL:
128132
partBuilder.append(" == null");
@@ -131,10 +135,14 @@ protected SpelExpression toPredicateExpression(PartTree tree) {
131135
partBuilder.append(" != null");
132136
break;
133137
case LIKE:
134-
partBuilder.append("?.contains(").append("[").append(parameterIndex++).append("])");
135-
break;
136138
case NOT_LIKE:
137-
partBuilder.append("?.contains(").append("[").append(parameterIndex++).append("]) == false");
139+
140+
partBuilder.append("?.contains(").append("[").append(parameterIndex++).append("])");
141+
142+
if (part.getType() == Type.NOT_LIKE) {
143+
partBuilder.append(" == false");
144+
}
145+
138146
break;
139147
case STARTING_WITH:
140148
partBuilder.append("?.startsWith(").append("[").append(parameterIndex++).append("])");
@@ -174,32 +182,30 @@ protected SpelExpression toPredicateExpression(PartTree tree) {
174182

175183
partBuilder.append(" matches ").append("[").append(parameterIndex++).append("]");
176184
break;
185+
186+
case NOT_IN:
177187
case IN:
178188

179189
partBuilder.append("[").append(parameterIndex++).append("].contains(");
180190
partBuilder.append("#it?.");
181191
partBuilder.append(part.getProperty().toDotPath().replace(".", "?."));
182192
partBuilder.append(")");
183-
break;
184193

185-
case NOT_IN:
194+
if (part.getType() == Type.NOT_IN) {
195+
partBuilder.append(" == false");
196+
}
186197

187-
partBuilder.append("[").append(parameterIndex++).append("].contains(");
188-
partBuilder.append("#it?.");
189-
partBuilder.append(part.getProperty().toDotPath().replace(".", "?."));
190-
partBuilder.append(") == false");
191198
break;
192199

193200
case CONTAINING:
194201
case NOT_CONTAINING:
195202
case EXISTS:
196203
default:
197-
throw new InvalidDataAccessApiUsageException(
198-
"Found invalid part '%s' in query".formatted(part.getType()));
204+
throw new InvalidDataAccessApiUsageException("Found invalid part '%s' in query".formatted(part.getType()));
199205
}
200206

201207
if (partIter.hasNext()) {
202-
partBuilder.append("&&");
208+
partBuilder.append(" && ");
203209
}
204210

205211
partCnt++;
@@ -212,7 +218,7 @@ protected SpelExpression toPredicateExpression(PartTree tree) {
212218
}
213219

214220
if (orPartIter.hasNext()) {
215-
sb.append("||");
221+
sb.append(" || ");
216222
}
217223
}
218224

0 commit comments

Comments
 (0)