Skip to content

Clarify behavior of PropertyPath #2491

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<version>2.6.0-SNAPSHOT</version>
<version>2.6.0-clarify-propertypath-SNAPSHOT</version>

<name>Spring Data Core</name>

Expand Down
71 changes: 59 additions & 12 deletions src/main/java/org/springframework/data/mapping/PropertyPath.java
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,15 @@ public TypeInformation<?> getOwningType() {
}

/**
* Returns the name of the {@link PropertyPath}.
* Returns the first part of the {@link PropertyPath}.
*
* <pre>
* {@code
* PropertyPath.from("a.b.c", Some.class).getSegment();
* }
* </pre>
*
* will result in {@code "a"}
*
* @return the name will never be {@literal null}.
*/
Expand Down Expand Up @@ -156,7 +164,15 @@ public TypeInformation<?> getTypeInformation() {
}

/**
* Returns the next nested {@link PropertyPath}.
* Returns the {@link PropertyPath} path that results from removing the first element of the current one.
*
* <pre>
* {@code
* System.out.println(PropertyPath.from("a.b.c", Some.class).next().toDotPath());
* }
* </pre>
*
* Will result in the output: {@code b.c}
*
* @return the next nested {@link PropertyPath} or {@literal null} if no nested {@link PropertyPath} available.
* @see #hasNext()
Expand Down Expand Up @@ -214,9 +230,28 @@ public PropertyPath nested(String path) {
return PropertyPath.from(lookup, owningType);
}

/*
* (non-Javadoc)
* @see java.lang.Iterable#iterator()
/**
* Returns an {@link Iterator<PropertyPath>} that iterates over all the partial property paths with the same leaf type
* but decreasing length.
*
* <pre>
* {@code
* PropertyPath propertyPath = PropertyPath.from("a.b.c", Some.class);
* for (p : propertyPath.iterator()) {
* System.out.println(p.toDotPath());
* };
* }
* </pre>
*
* Results in the output:
*
* <pre>
* {@code
* a.b.c
* b.c
* c
* }
* </pre>
*/
public Iterator<PropertyPath> iterator() {

Expand Down Expand Up @@ -321,11 +356,18 @@ private PropertyPath requiredNext() {
}

/**
* Extracts the {@link PropertyPath} chain from the given source {@link String} and type.
* Extracts the {@link PropertyPath} chain from the given source {@link String} and {@link TypeInformation}. <br />
* Uses {@link #SPLITTER} by default and {@link #SPLITTER_FOR_QUOTED} for {@link Pattern#quote(String) quoted}
* literals.
* <p>
* Separate parts of the path may be separated by {@code "."} or by {@code "_"} or by camel case. When the match to
* properties is ambiguous longer property names are preferred. So for "userAddressCity" the interpretation
* "userAddress.city" is preferred over "user.address.city".
* </p>
*
* @param source
* @param type
* @return
* @param source a String denoting the property path. Must not be {@literal null}.
* @param type the owning type of the property path. Must not be {@literal null}.
* @return a new {@link PropertyPath} guaranteed to be not {@literal null}.
*/
public static PropertyPath from(String source, Class<?> type) {
return from(source, ClassTypeInformation.from(type));
Expand All @@ -335,10 +377,15 @@ public static PropertyPath from(String source, Class<?> type) {
* Extracts the {@link PropertyPath} chain from the given source {@link String} and {@link TypeInformation}. <br />
* Uses {@link #SPLITTER} by default and {@link #SPLITTER_FOR_QUOTED} for {@link Pattern#quote(String) quoted}
* literals.
* <p>
* Separate parts of the path may be separated by {@code "."} or by {@code "_"} or by camel case. When the match to
* properties is ambiguous longer property names are preferred. So for "userAddressCity" the interpretation
* "userAddress.city" is preferred over "user.address.city".
* </p>
*
* @param source must not be {@literal null}.
* @param type
* @return
* @param source a String denoting the property path. Must not be {@literal null}.
* @param type the owning type of the property path. Must not be {@literal null}.
* @return a new {@link PropertyPath} guaranteed to be not {@literal null}.
*/
public static PropertyPath from(String source, TypeInformation<?> type) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import java.util.regex.Pattern;

import org.junit.jupiter.api.Test;

import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;

Expand All @@ -34,6 +33,7 @@
* @author Oliver Gierke
* @author Christoph Strobl
* @author Mark Paluch
* @author Jens Schauder
*/
@SuppressWarnings("unused")
public class PropertyPathUnitTests {
Expand Down Expand Up @@ -188,6 +188,16 @@ public void returnsCorrectIteratorForMultipleElement() {
assertThat(iterator.hasNext()).isFalse();
}

@Test // GH-2491
public void nextReturnsPathWithoutFirstElement() {

PropertyPath propertyPath = PropertyPath.from("bar.user.name", Sample.class);

final PropertyPath next = propertyPath.next();
assertThat(next).isNotNull();
assertThat(next.toDotPath()).isEqualTo("user.name");
}

@Test // DATACMNS-139
public void rejectsInvalidPropertyWithLeadingUnderscore() {

Expand Down