Clarify behavior of PropertyPath.

Update tests and documentation.

Closes #2491
This commit is contained in:
Jens Schauder
2021-10-27 11:07:00 +02:00
committed by Mark Paluch
parent 91d2fdc3f7
commit ddeb70cd7b
2 changed files with 72 additions and 9 deletions

View File

@@ -108,7 +108,15 @@ public class PropertyPath implements Streamable<PropertyPath> {
}
/**
* 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}.
*/
@@ -156,7 +164,15 @@ public class PropertyPath implements Streamable<PropertyPath> {
}
/**
* 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()
@@ -214,6 +230,29 @@ public class PropertyPath implements Streamable<PropertyPath> {
return PropertyPath.from(lookup, owningType);
}
/**
* 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() {
return new Iterator<PropertyPath>() {
@@ -289,11 +328,18 @@ public class PropertyPath implements Streamable<PropertyPath> {
}
/**
* 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, TypeInformation.of(type));
@@ -303,10 +349,15 @@ public class PropertyPath implements Streamable<PropertyPath> {
* 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) {

View File

@@ -23,6 +23,7 @@ import java.util.Set;
import java.util.regex.Pattern;
import org.junit.jupiter.api.Test;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
/**
@@ -31,6 +32,7 @@ import org.springframework.data.util.TypeInformation;
* @author Oliver Gierke
* @author Christoph Strobl
* @author Mark Paluch
* @author Jens Schauder
*/
@SuppressWarnings("unused")
class PropertyPathUnitTests {
@@ -185,6 +187,16 @@ class PropertyPathUnitTests {
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, GH-2395
void rejectsInvalidPropertyWithLeadingUnderscore() {