Skip to content

Commit 23f4774

Browse files
committed
Consider nested property paths containing a number.
PropertyPath now considers nested property paths (userLastname2 -> user.lastname2) that contain or end with a number. Closes #2472
1 parent 6aa3458 commit 23f4774

File tree

3 files changed

+35
-4
lines changed

3 files changed

+35
-4
lines changed

Diff for: src/main/java/org/springframework/data/mapping/PropertyPath.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ public class PropertyPath implements Streamable<PropertyPath> {
5050
private static final String ALL_UPPERCASE = "[A-Z0-9._$]+";
5151
private static final Pattern SPLITTER = Pattern.compile("(?:[%s]?([%s]*?[^%s]+))".replaceAll("%s", DELIMITERS));
5252
private static final Pattern SPLITTER_FOR_QUOTED = Pattern.compile("(?:[%s]?([%s]*?[^%s]+))".replaceAll("%s", "\\."));
53+
private static final Pattern NESTED_PROPERTY_PATTERN = Pattern.compile("\\p{Lu}[\\p{Ll}\\p{Nd}]*$");
5354
private static final Map<Key, PropertyPath> cache = new ConcurrentReferenceHashMap<>();
5455

5556
private final TypeInformation<?> owningType;
@@ -81,7 +82,7 @@ public class PropertyPath implements Streamable<PropertyPath> {
8182

8283
Assert.hasText(name, "Name must not be null or empty!");
8384
Assert.notNull(owningType, "Owning type must not be null!");
84-
Assert.notNull(base, "Perviously found properties must not be null!");
85+
Assert.notNull(base, "Previously found properties must not be null!");
8586

8687
String propertyName = Introspector.decapitalize(name);
8788
TypeInformation<?> propertyType = owningType.getProperty(propertyName);
@@ -458,8 +459,7 @@ private static PropertyPath create(String source, TypeInformation<?> type, Strin
458459
exception = e;
459460
}
460461

461-
Pattern pattern = Pattern.compile("\\p{Lu}\\p{Ll}*$");
462-
Matcher matcher = pattern.matcher(source);
462+
Matcher matcher = NESTED_PROPERTY_PATTERN.matcher(source);
463463

464464
if (matcher.find() && matcher.start() != 0) {
465465

Diff for: src/test/java/org/springframework/data/mapping/PropertyPathUnitTests.java

+22-1
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,20 @@ public void rejectsInvalidPathsContainingDigits() {
218218
.isThrownBy(() -> from("PropertyThatWillFail4Sure", Foo.class));
219219
}
220220

221+
@Test // GH-2472
222+
public void acceptsValidPathWithDigits() {
223+
assertThat(from("bar1", Sample.class)).isNotNull();
224+
assertThat(from("bar1foo", Sample.class)).isNotNull();
225+
}
226+
227+
@Test // GH-2472
228+
public void acceptsValidNestedPathWithDigits() {
229+
assertThat(from("sample.bar1", SampleHolder.class)).isNotNull();
230+
assertThat(from("sample.bar1foo", SampleHolder.class)).isNotNull();
231+
assertThat(from("sampleBar1", SampleHolder.class)).isNotNull();
232+
assertThat(from("sampleBar1foo", SampleHolder.class)).isNotNull();
233+
}
234+
221235
@Test
222236
public void rejectsInvalidProperty() {
223237

@@ -353,7 +367,7 @@ public void createsNestedPropertyPath() {
353367
}
354368

355369
@Test // DATACMNS-1199
356-
public void rejectsNonExistantNestedPath() {
370+
public void rejectsNonExistentNestedPath() {
357371

358372
assertThatExceptionOfType(PropertyReferenceException.class) //
359373
.isThrownBy(() -> from("user", Bar.class).nested("nonexistant")) //
@@ -419,6 +433,13 @@ private class Sample {
419433
private String userName;
420434
private FooBar user;
421435
private Bar bar;
436+
private Bar bar1;
437+
private Bar bar1foo;
438+
}
439+
440+
private class SampleHolder {
441+
442+
private Sample sample;
422443
}
423444

424445
private class Sample2 {

Diff for: src/test/java/org/springframework/data/repository/query/parser/PartTreeUnitTests.java

+10
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,11 @@ void identifiesCountAndDistinctByCorrectly() {
425425
assertThat(tree.isDistinct()).isTrue();
426426
}
427427

428+
@Test // GH-2472
429+
void resolvesPropertyPathsWithNumbers() {
430+
assertThat(new PartTree("findByUserLastname2", UserHolder.class)).isNotNull();
431+
}
432+
428433
@Test // DATAJPA-324
429434
void resolvesPropertyPathFromGettersOnInterfaces() {
430435
assertThat(new PartTree("findByCategoryId", Product.class)).isNotNull();
@@ -735,9 +740,14 @@ private static <T> Collection<T> toCollection(Iterable<T> iterable) {
735740
return result;
736741
}
737742

743+
class UserHolder {
744+
User user;
745+
}
746+
738747
class User {
739748
String firstname;
740749
String lastname;
750+
String lastname2;
741751
double[] location;
742752
boolean active;
743753
Date birthday;

0 commit comments

Comments
 (0)