diff --git a/src/main/java/org/springframework/data/mapping/context/PersistentPropertyPathFactory.java b/src/main/java/org/springframework/data/mapping/context/PersistentPropertyPathFactory.java index 8431aaa212..d304eca40a 100644 --- a/src/main/java/org/springframework/data/mapping/context/PersistentPropertyPathFactory.java +++ b/src/main/java/org/springframework/data/mapping/context/PersistentPropertyPathFactory.java @@ -15,7 +15,16 @@ */ package org.springframework.data.mapping.context; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -34,7 +43,6 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ConcurrentReferenceHashMap; -import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; /** @@ -42,6 +50,7 @@ * * @author Oliver Gierke * @author Christoph Strobl + * @author Mark Paluch * @since 2.1 * @soundtrack Cypress Hill - Boom Biddy Bye Bye (Fugees Remix, Unreleased & Revamped) */ @@ -172,7 +181,7 @@ private PersistentPropertyPath

getPersistentPropertyPath(TypeInformation t private PathResolution getPotentiallyCachedPath(TypeInformation type, String propertyPath) { return propertyPaths.computeIfAbsent(TypeAndPath.of(type, propertyPath), - it -> createPersistentPropertyPath(it.getPath(), it.getType())); + it -> createPersistentPropertyPath(it.path(), it.type())); } /** @@ -200,14 +209,14 @@ private PathResolution createPersistentPropertyPath(String propertyPath, TypeInf Pair, E> pair = getPair(path, iterator, segment, current); if (pair == null) { - return new PathResolution(parts, segment, type, currentPath); + return PathResolution.unresolved(parts, segment, type, currentPath); } path = pair.getFirst(); current = pair.getSecond(); } - return new PathResolution(path); + return PathResolution.resolved(path); } @Nullable @@ -240,7 +249,7 @@ private Collection> from(E entity, Predicate> properties = new HashSet<>(); - PropertyHandler

propertyTester = (PropertyHandler

) persistentProperty -> { + PropertyHandler

propertyTester = persistentProperty -> { TypeInformation typeInformation = persistentProperty.getTypeInformation(); TypeInformation actualPropertyType = typeInformation.getActualType(); @@ -263,64 +272,19 @@ private Collection> from(E entity, Predicate handler = (AssociationHandler

) association -> propertyTester + AssociationHandler

handler = association -> propertyTester .doWithPersistentProperty(association.getInverse()); entity.doWithAssociations(handler); return properties; } - static final class TypeAndPath { - - private final TypeInformation type; - private final String path; - - private TypeAndPath(TypeInformation type, String path) { - this.type = type; - this.path = path; - } + record TypeAndPath(TypeInformation type, String path) { public static TypeAndPath of(TypeInformation type, String path) { return new TypeAndPath(type, path); } - public TypeInformation getType() { - return this.type; - } - - public String getPath() { - return this.path; - } - - @Override - public boolean equals(@Nullable Object o) { - - if (this == o) { - return true; - } - - if (!(o instanceof TypeAndPath that)) { - return false; - } - - if (!ObjectUtils.nullSafeEquals(type, that.type)) { - return false; - } - - return ObjectUtils.nullSafeEquals(path, that.path); - } - - @Override - public int hashCode() { - int result = ObjectUtils.nullSafeHashCode(type); - result = 31 * result + ObjectUtils.nullSafeHashCode(path); - return result; - } - - @Override - public String toString() { - return "PersistentPropertyPathFactory.TypeAndPath(type=" + this.getType() + ", path=" + this.getPath() + ")"; - } } static class DefaultPersistentPropertyPaths> @@ -389,7 +353,7 @@ public PersistentPropertyPaths dropPathIfSegmentMatches(Predicate> paths = this.stream() // - .filter(it -> !it.stream().anyMatch(predicate)) // + .filter(it -> it.stream().noneMatch(predicate)) // .collect(Collectors.toList()); return paths.equals(this.paths) ? this : new DefaultPersistentPropertyPaths<>(type, paths); @@ -408,8 +372,7 @@ public String toString() { * @author Oliver Gierke * @since 2.1 */ - private enum ShortestSegmentFirst - implements Comparator>> { + private enum ShortestSegmentFirst implements Comparator>> { INSTANCE; @@ -417,8 +380,7 @@ private enum ShortestSegmentFirst @SuppressWarnings("null") public int compare(PersistentPropertyPath left, PersistentPropertyPath right) { - Function, Integer> mapper = (Function, Integer>) it -> it.getName() - .length(); + Function, Integer> mapper = it -> it.getName().length(); Stream leftNames = left.stream().map(mapper); Stream rightNames = right.stream().map(mapper); @@ -440,16 +402,22 @@ private static class PathResolution { private final PersistentPropertyPath path; private final boolean resolvable; - private String source, segment; - private TypeInformation type; + private @Nullable final String source; - public PathResolution(PersistentPropertyPath path) { + private @Nullable final String segment; + private @Nullable final TypeInformation type; + + private PathResolution(PersistentPropertyPath path) { this.path = path; this.resolvable = true; + this.source = null; + this.segment = null; + this.type = null; } - PathResolution(List parts, String segment, TypeInformation type, PersistentPropertyPath path) { + private PathResolution(List parts, String segment, TypeInformation type, + PersistentPropertyPath path) { this.source = StringUtils.collectionToDelimitedString(parts, "."); this.segment = segment; @@ -458,15 +426,26 @@ public PathResolution(PersistentPropertyPath path) { this.resolvable = false; } + static PathResolution unresolved(List parts, String segment, TypeInformation type, + PersistentPropertyPath path) { + return new PathResolution(parts, segment, type, path); + } + + static PathResolution resolved(PersistentPropertyPath path) { + return new PathResolution(path); + } + /** * @return the path if available. * @throws InvalidPersistentPropertyPath when the path could not be resolved to an actual property */ - PersistentPropertyPath getResolvedPath() { + @SuppressWarnings("unchecked") +

> PersistentPropertyPath

getResolvedPath() { if (resolvable) { - return path; + return (PersistentPropertyPath

) path; } + throw new InvalidPersistentPropertyPath(source, type, segment, path); } }