Skip to content

Commit 6fb4ffd

Browse files
committed
Retrofit ExampleMatcher with TypedPropertyPath.
1 parent cfde864 commit 6fb4ffd

File tree

2 files changed

+136
-3
lines changed

2 files changed

+136
-3
lines changed

src/main/java/org/springframework/data/domain/ExampleMatcher.java

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.data.domain;
1717

18+
import java.util.Arrays;
1819
import java.util.Collection;
1920
import java.util.LinkedHashMap;
2021
import java.util.Map;
@@ -24,6 +25,7 @@
2425

2526
import org.jspecify.annotations.Nullable;
2627

28+
import org.springframework.data.util.TypedPropertyPath;
2729
import org.springframework.lang.CheckReturnValue;
2830
import org.springframework.lang.Contract;
2931
import org.springframework.util.Assert;
@@ -77,6 +79,21 @@ static ExampleMatcher matchingAll() {
7779
return new TypedExampleMatcher().withMode(MatchMode.ALL);
7880
}
7981

82+
/**
83+
* Returns a copy of this {@link ExampleMatcher} with the specified {@code propertyPaths}. This instance is immutable
84+
* and unaffected by this method call.
85+
*
86+
* @param ignoredPaths must not be {@literal null} and not empty.
87+
* @return new instance of {@link ExampleMatcher}.
88+
* @since 4.1
89+
*/
90+
@Contract("_ -> new")
91+
@CheckReturnValue
92+
default <T> ExampleMatcher withIgnorePaths(TypedPropertyPath<T, ?>... ignoredPaths) {
93+
return withIgnorePaths(Arrays.stream(ignoredPaths).map(TypedPropertyPath::of).map(TypedPropertyPath::toDotPath)
94+
.toArray(String[]::new));
95+
}
96+
8097
/**
8198
* Returns a copy of this {@link ExampleMatcher} with the specified {@code propertyPaths}. This instance is immutable
8299
* and unaffected by this method call.
@@ -122,6 +139,22 @@ default ExampleMatcher withIgnoreCase() {
122139
@CheckReturnValue
123140
ExampleMatcher withIgnoreCase(boolean defaultIgnoreCase);
124141

142+
/**
143+
* Returns a copy of this {@link ExampleMatcher} with the specified {@code GenericPropertyMatcher} for the
144+
* {@code propertyPath}. This instance is immutable and unaffected by this method call.
145+
*
146+
* @param propertyPath must not be {@literal null}.
147+
* @param matcherConfigurer callback to configure a {@link GenericPropertyMatcher}, must not be {@literal null}.
148+
* @return new instance of {@link ExampleMatcher}.
149+
* @since 4.1
150+
*/
151+
@Contract("_, _ -> new")
152+
@CheckReturnValue
153+
default <T, P> ExampleMatcher withMatcher(TypedPropertyPath<T, P> propertyPath,
154+
MatcherConfigurer<GenericPropertyMatcher> matcherConfigurer) {
155+
return withMatcher(propertyPath.toDotPath(), matcherConfigurer);
156+
}
157+
125158
/**
126159
* Returns a copy of this {@link ExampleMatcher} with the specified {@code GenericPropertyMatcher} for the
127160
* {@code propertyPath}. This instance is immutable and unaffected by this method call.
@@ -143,6 +176,21 @@ default ExampleMatcher withMatcher(String propertyPath, MatcherConfigurer<Generi
143176
return withMatcher(propertyPath, genericPropertyMatcher);
144177
}
145178

179+
/**
180+
* Returns a copy of this {@link ExampleMatcher} with the specified {@code GenericPropertyMatcher} for the
181+
* {@code propertyPath}. This instance is immutable and unaffected by this method call.
182+
*
183+
* @param propertyPath must not be {@literal null}.
184+
* @param genericPropertyMatcher callback to configure a {@link GenericPropertyMatcher}, must not be {@literal null}.
185+
* @return new instance of {@link ExampleMatcher}.
186+
*/
187+
@Contract("_, _ -> new")
188+
@CheckReturnValue
189+
default <T, P> ExampleMatcher withMatcher(TypedPropertyPath<T, P> propertyPath,
190+
GenericPropertyMatcher genericPropertyMatcher) {
191+
return withMatcher(propertyPath.toDotPath(), genericPropertyMatcher);
192+
}
193+
146194
/**
147195
* Returns a copy of this {@link ExampleMatcher} with the specified {@code GenericPropertyMatcher} for the
148196
* {@code propertyPath}. This instance is immutable and unaffected by this method call.
@@ -155,6 +203,22 @@ default ExampleMatcher withMatcher(String propertyPath, MatcherConfigurer<Generi
155203
@CheckReturnValue
156204
ExampleMatcher withMatcher(String propertyPath, GenericPropertyMatcher genericPropertyMatcher);
157205

206+
/**
207+
* Returns a copy of this {@link ExampleMatcher} with the specified {@code PropertyValueTransformer} for the
208+
* {@code propertyPath}.
209+
*
210+
* @param propertyPath must not be {@literal null}.
211+
* @param propertyValueTransformer must not be {@literal null}.
212+
* @return new instance of {@link ExampleMatcher}.
213+
* @since 4.1
214+
*/
215+
@Contract("_, _ -> new")
216+
@CheckReturnValue
217+
default <T, P> ExampleMatcher withTransformer(TypedPropertyPath<T, P> propertyPath,
218+
PropertyValueTransformer propertyValueTransformer) {
219+
return withTransformer(propertyPath.toDotPath(), propertyValueTransformer);
220+
}
221+
158222
/**
159223
* Returns a copy of this {@link ExampleMatcher} with the specified {@code PropertyValueTransformer} for the
160224
* {@code propertyPath}.
@@ -167,6 +231,20 @@ default ExampleMatcher withMatcher(String propertyPath, MatcherConfigurer<Generi
167231
@CheckReturnValue
168232
ExampleMatcher withTransformer(String propertyPath, PropertyValueTransformer propertyValueTransformer);
169233

234+
/**
235+
* Returns a copy of this {@link ExampleMatcher} with ignore case sensitivity for the {@code propertyPaths}. This
236+
* instance is immutable and unaffected by this method call.
237+
*
238+
* @param propertyPaths must not be {@literal null} and not empty.
239+
* @return new instance of {@link ExampleMatcher}.
240+
*/
241+
@Contract("_ -> new")
242+
@CheckReturnValue
243+
default <T> ExampleMatcher withIgnoreCase(TypedPropertyPath<T, ?>... propertyPaths) {
244+
return withIgnoreCase(Arrays.stream(propertyPaths).map(TypedPropertyPath::of).map(TypedPropertyPath::toDotPath)
245+
.toArray(String[]::new));
246+
}
247+
170248
/**
171249
* Returns a copy of this {@link ExampleMatcher} with ignore case sensitivity for the {@code propertyPaths}. This
172250
* instance is immutable and unaffected by this method call.

src/test/java/org/springframework/data/domain/ExampleMatcherUnitTests.java

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,15 @@ void ignoredPathsShouldReturnUniqueProperties() {
121121
assertThat(matcher.getIgnoredPaths()).hasSize(2);
122122
}
123123

124+
@Test //
125+
void ignoredPropertyPathsShouldReturnUniqueProperties() {
126+
127+
matcher = matching().withIgnorePaths(Person::getFirstname, Person::getLastname, Person::getFirstname);
128+
129+
assertThat(matcher.getIgnoredPaths()).contains("firstname", "lastname");
130+
assertThat(matcher.getIgnoredPaths()).hasSize(2);
131+
}
132+
124133
@Test // DATACMNS-810
125134
void withCreatesNewInstance() {
126135

@@ -160,11 +169,11 @@ void anyMatcherYieldsAnyMatching() {
160169
void shouldCompareUsingHashCodeAndEquals() {
161170

162171
matcher = matching() //
163-
.withIgnorePaths("foo", "bar", "baz") //
172+
.withIgnorePaths(Random::getFoo, Random::getBar, Random::getBaz) //
164173
.withNullHandler(NullHandler.IGNORE) //
165174
.withIgnoreCase("ignored-case") //
166-
.withMatcher("hello", GenericPropertyMatchers.contains().caseSensitive()) //
167-
.withMatcher("world", GenericPropertyMatcher::endsWith);
175+
.withMatcher(Random::getHello, GenericPropertyMatchers.contains().caseSensitive()) //
176+
.withMatcher(Random::getWorld, GenericPropertyMatcher::endsWith);
168177

169178
var sameAsMatcher = matching() //
170179
.withIgnorePaths("foo", "bar", "baz") //
@@ -182,8 +191,54 @@ void shouldCompareUsingHashCodeAndEquals() {
182191
assertThat(matcher).isEqualTo(sameAsMatcher).isNotEqualTo(different);
183192
}
184193

194+
static class Random {
195+
196+
String foo;
197+
String bar;
198+
String baz;
199+
String hello;
200+
String world;
201+
202+
public String getFoo() {
203+
return foo;
204+
}
205+
206+
public String getBar() {
207+
return bar;
208+
}
209+
210+
public String getBaz() {
211+
return baz;
212+
}
213+
214+
public String getHello() {
215+
return hello;
216+
}
217+
218+
public String getWorld() {
219+
return world;
220+
}
221+
}
222+
185223
static class Person {
186224

187225
String firstname;
226+
String lastname;
227+
228+
public String getFirstname() {
229+
return firstname;
230+
}
231+
232+
public void setFirstname(String firstname) {
233+
this.firstname = firstname;
234+
}
235+
236+
public String getLastname() {
237+
return lastname;
238+
}
239+
240+
public void setLastname(String lastname) {
241+
this.lastname = lastname;
242+
}
188243
}
189244
}

0 commit comments

Comments
 (0)