Skip to content
Open
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>4.2.0-SNAPSHOT</version>
<version>4.2.0-GH-3515-SNAPSHOT</version>

<name>Spring Data Core</name>
<description>Core Spring concepts underpinning every Spring Data module.</description>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,13 @@ default E getRequiredPersistentEntity(TypeInformation<?> type) throws MappingExc
E getPersistentEntity(P persistentProperty);

/**
* Returns the {@link PersistentEntity} mapped by the given {@link PersistentProperty}.
* Returns the {@link PersistentEntity} mapped by the given {@link PersistentProperty}. Will throw
* {@link MappingException} for types that are considered simple ones.
*
* @param persistentProperty must not be {@literal null}.
* @return the {@link PersistentEntity} mapped by the given {@link PersistentProperty} or {@literal null} if no
* {@link PersistentEntity} exists for it or the {@link PersistentProperty} does not refer to an entity (the
* type of the property is considered simple see
* {@link org.springframework.data.mapping.model.SimpleTypeHolder#isSimpleType(Class)}).
* @return the {@link PersistentEntity} mapped by the given {@link PersistentProperty}.
* @throws MappingException when no {@link PersistentEntity} can be found for given {@link PersistentProperty}.
* @see #getPersistentEntity(PersistentProperty)
*/
default E getRequiredPersistentEntity(P persistentProperty) throws MappingException {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,16 @@
*/
package org.springframework.data.mapping.context;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
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.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -49,8 +57,6 @@
*/
class PersistentPropertyPathFactory<E extends PersistentEntity<?, P>, P extends PersistentProperty<P>> {

private static final Predicate<PersistentProperty<? extends PersistentProperty<?>>> IS_ENTITY = PersistentProperty::isEntity;

private final ConcurrentLruCache<TypeAndPath, PathResolution> propertyPaths = new ConcurrentLruCache<>(512, it -> createPersistentPropertyPath(it.path(), it.type()));
private final MappingContext<E, P> context;

Expand Down Expand Up @@ -228,7 +234,18 @@ private <T> Collection<PersistentPropertyPath<P>> from(TypeInformation<T> type,
return Collections.emptyList();
}

return from(context.getRequiredPersistentEntity(actualType), filter, traversalGuard, basePath);
E entity;
if (type.isCollectionLike() || type.isMap()) {
entity = context.getPersistentEntity(actualType);
} else {
entity = context.getRequiredPersistentEntity(actualType);
}

if (entity == null) {
return Collections.emptyList();
}

return from(entity, filter, traversalGuard, basePath);
}

private Collection<PersistentPropertyPath<P>> from(E entity, Predicate<? super P> filter, Predicate<P> traversalGuard,
Expand All @@ -251,9 +268,11 @@ private Collection<PersistentPropertyPath<P>> from(E entity, Predicate<? super P
properties.add(currentPath);
}

if (traversalGuard.and(IS_ENTITY).test(persistentProperty)) {
var persistentEntity = context.getRequiredPersistentEntity(persistentProperty);
properties.addAll(from(persistentEntity, filter, traversalGuard, currentPath));
if (traversalGuard.test(persistentProperty)) {
E persistentEntity = context.getPersistentEntity(persistentProperty);
if (persistentEntity != null) {
properties.addAll(from(persistentEntity, filter, traversalGuard, currentPath));
}
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,18 @@ void cacheWarmedWithKnownPersistentEntities() {
assertThat(metadataCache).hasSize(4);
}

@Test // GH-3515
void initializesFactoryForEntityWithNestedMapProperty() {

var context = new SampleMappingContext();
context.getPersistentEntity(WithNestedMap.class);
context.findPersistentPropertyPaths(WithNestedMap.class, it -> true);

var factory = new MappingAuditableBeanWrapperFactory(PersistentEntities.of(context));

assertThat(factory.getBeanWrapperFor(new WithNestedMap())).isNotNull();
}

@Test // DATACMNS-365
void discoversAuditingPropertyOnField() {

Expand Down Expand Up @@ -406,4 +418,12 @@ static class WithEmbedded {
Collection<Embedded> embeddeds;
Map<String, Embedded> embeddedMap;
}

static class Cell {
Object value;
}

static class WithNestedMap {
Map<String, Map<String, Cell>> values;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
*
* @author Oliver Gierke
* @author Christoph Strobl
* @author Mark Paluch
* @soundtrack Cypress Hill - Illusions (Q-Tip Remix, Unreleased & Revamped)
*/
class PersistentPropertyPathFactoryUnitTests {
Expand Down Expand Up @@ -176,6 +177,22 @@ void returnsShortestPathFirst() {
.hasValueSatisfying(it -> assertThat(it.toDotPath()).isEqualTo("third.lastname"));
}

@Test // GH-3515
void returnsPathsForMapWithEntityKeyAndSimpleValueType() {

var paths = factory.from(WithEntityKeyMap.class, it -> true);

assertThat(paths).extracting(PersistentPropertyPath::toDotPath).containsExactly("map");
}

@Test // GH-3515
void returnsPathsForRawTypeComplexBound() {

var paths = factory.from(BoundedGeneric.class, it -> true);

assertThat(paths).extracting(PersistentPropertyPath::toDotPath).containsExactly("map");
}

static class PersonSample {
List<Person> persons;
}
Expand Down Expand Up @@ -222,4 +239,13 @@ static class Second {
static class Third {
String lastname;
}

static class WithEntityKeyMap {
Map<Second, Double> map;
}

static class BoundedGeneric<T extends Second> {
Map<T, Double> map;
}

}
Loading