Skip to content

Commit 1f4d494

Browse files
committed
DATACMNS-1322 - Generified PersistentPropertyAccessor API.
PersistentPropertyAccessor is now generic to be able to retain the type information about the object it was created for and the return type of ….getBean(). Adapted client APIs.
1 parent d1ebfcf commit 1f4d494

12 files changed

+38
-39
lines changed

src/main/java/org/springframework/data/auditing/MappingAuditableBeanWrapperFactory.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ public boolean isAuditable() {
148148
*/
149149
static class MappingMetadataAuditableBeanWrapper<T> extends DateConvertingAuditableBeanWrapper<T> {
150150

151-
private final PersistentPropertyAccessor accessor;
151+
private final PersistentPropertyAccessor<T> accessor;
152152
private final MappingAuditingMetadata metadata;
153153

154154
/**
@@ -158,7 +158,8 @@ static class MappingMetadataAuditableBeanWrapper<T> extends DateConvertingAudita
158158
* @param accessor must not be {@literal null}.
159159
* @param metadata must not be {@literal null}.
160160
*/
161-
public MappingMetadataAuditableBeanWrapper(PersistentPropertyAccessor accessor, MappingAuditingMetadata metadata) {
161+
public MappingMetadataAuditableBeanWrapper(PersistentPropertyAccessor<T> accessor,
162+
MappingAuditingMetadata metadata) {
162163

163164
Assert.notNull(accessor, "PersistentPropertyAccessor must not be null!");
164165
Assert.notNull(metadata, "Auditing metadata must not be null!");
@@ -224,9 +225,8 @@ public TemporalAccessor setLastModifiedDate(TemporalAccessor value) {
224225
* @see org.springframework.data.auditing.AuditableBeanWrapper#getBean()
225226
*/
226227
@Override
227-
@SuppressWarnings("unchecked")
228228
public T getBean() {
229-
return (T) accessor.getBean();
229+
return accessor.getBean();
230230
}
231231

232232
private <S, P extends PersistentProperty<?>> S setProperty(

src/main/java/org/springframework/data/mapping/PersistentEntity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ default <A extends Annotation> A getRequiredAnnotation(Class<A> annotationType)
285285
* @return new {@link PersistentPropertyAccessor}.
286286
* @since 1.10
287287
*/
288-
PersistentPropertyAccessor getPropertyAccessor(Object bean);
288+
<B> PersistentPropertyAccessor<B> getPropertyAccessor(B bean);
289289

290290
/**
291291
* Returns the {@link IdentifierAccessor} for the given bean.

src/main/java/org/springframework/data/mapping/PersistentPropertyAccessor.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
* @see PersistentEntity#getPropertyAccessor(Object)
3434
* @see ConvertingPropertyAccessor
3535
*/
36-
public interface PersistentPropertyAccessor {
36+
public interface PersistentPropertyAccessor<T> {
3737

3838
/**
3939
* Sets the given {@link PersistentProperty} to the given value. Will do type conversion if a
@@ -71,7 +71,7 @@ default void setProperty(PersistentPropertyPath<? extends PersistentProperty<?>>
7171
getBean().getClass().getName()));
7272
}
7373

74-
PersistentPropertyAccessor accessor = parent == getBean() //
74+
PersistentPropertyAccessor<?> accessor = parent == getBean() //
7575
? this //
7676
: leafProperty.getOwner().getPropertyAccessor(parent);
7777

@@ -126,7 +126,7 @@ default Object getProperty(PersistentPropertyPath<? extends PersistentProperty<?
126126
}
127127

128128
PersistentEntity<?, ? extends PersistentProperty<?>> entity = property.getOwner();
129-
PersistentPropertyAccessor accessor = entity.getPropertyAccessor(current);
129+
PersistentPropertyAccessor<Object> accessor = entity.getPropertyAccessor(current);
130130

131131
current = accessor.getProperty(property);
132132
}
@@ -140,5 +140,5 @@ default Object getProperty(PersistentPropertyPath<? extends PersistentProperty<?
140140
*
141141
* @return will never be {@literal null}.
142142
*/
143-
Object getBean();
143+
T getBean();
144144
}

src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ public void setPersistentPropertyAccessorFactory(PersistentPropertyAccessorFacto
461461
* @see org.springframework.data.mapping.PersistentEntity#getPropertyAccessor(java.lang.Object)
462462
*/
463463
@Override
464-
public PersistentPropertyAccessor getPropertyAccessor(Object bean) {
464+
public <B> PersistentPropertyAccessor<B> getPropertyAccessor(B bean) {
465465

466466
verifyBeanType(bean);
467467

src/main/java/org/springframework/data/mapping/model/BeanWrapper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
* @author Oliver Gierke
4141
* @author Mark Paluch
4242
*/
43-
class BeanWrapper<T> implements PersistentPropertyAccessor {
43+
class BeanWrapper<T> implements PersistentPropertyAccessor<T> {
4444

4545
private T bean;
4646

src/main/java/org/springframework/data/mapping/model/BeanWrapperPropertyAccessorFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ enum BeanWrapperPropertyAccessorFactory implements PersistentPropertyAccessorFac
3232
* @see org.springframework.data.mapping.model.PersistentPropertyAccessorFactory#getPropertyAccessor(org.springframework.data.mapping.PersistentEntity, java.lang.Object)
3333
*/
3434
@Override
35-
public PersistentPropertyAccessor getPropertyAccessor(PersistentEntity<?, ?> entity, Object bean) {
35+
public <T> PersistentPropertyAccessor<T> getPropertyAccessor(PersistentEntity<?, ?> entity, T bean) {
3636
return new BeanWrapper<>(bean);
3737
}
3838

src/main/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactory.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,21 +83,21 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
8383
private final ThreadLocal<Object[]> argumentCache = ThreadLocal.withInitial(() -> new Object[1]);
8484

8585
private volatile Map<PersistentEntity<?, ?>, Constructor<?>> constructorMap = new HashMap<>(32);
86-
private volatile Map<TypeInformation<?>, Class<PersistentPropertyAccessor>> propertyAccessorClasses = new HashMap<>(
86+
private volatile Map<TypeInformation<?>, Class<PersistentPropertyAccessor<?>>> propertyAccessorClasses = new HashMap<>(
8787
32);
8888

8989
/*
9090
* (non-Javadoc)
9191
* @see org.springframework.data.mapping.model.PersistentPropertyAccessorFactory#getPropertyAccessor(org.springframework.data.mapping.PersistentEntity, java.lang.Object)
9292
*/
9393
@Override
94-
public PersistentPropertyAccessor getPropertyAccessor(PersistentEntity<?, ?> entity, Object bean) {
94+
public <T> PersistentPropertyAccessor<T> getPropertyAccessor(PersistentEntity<?, ?> entity, T bean) {
9595

9696
Constructor<?> constructor = constructorMap.get(entity);
9797

9898
if (constructor == null) {
9999

100-
Class<PersistentPropertyAccessor> accessorClass = potentiallyCreateAndRegisterPersistentPropertyAccessorClass(
100+
Class<PersistentPropertyAccessor<?>> accessorClass = potentiallyCreateAndRegisterPersistentPropertyAccessorClass(
101101
entity);
102102
constructor = accessorClass.getConstructors()[0];
103103

@@ -110,7 +110,7 @@ public PersistentPropertyAccessor getPropertyAccessor(PersistentEntity<?, ?> ent
110110
args[0] = bean;
111111

112112
try {
113-
return (PersistentPropertyAccessor) constructor.newInstance(args);
113+
return (PersistentPropertyAccessor<T>) constructor.newInstance(args);
114114
} catch (Exception e) {
115115
throw new IllegalArgumentException(String.format("Cannot create persistent property accessor for %s", entity), e);
116116
} finally {
@@ -177,11 +177,11 @@ private boolean hasUniquePropertyHashCodes(PersistentEntity<?, ?> entity) {
177177
/**
178178
* @param entity must not be {@literal null}.
179179
*/
180-
private synchronized Class<PersistentPropertyAccessor> potentiallyCreateAndRegisterPersistentPropertyAccessorClass(
180+
private synchronized Class<PersistentPropertyAccessor<?>> potentiallyCreateAndRegisterPersistentPropertyAccessorClass(
181181
PersistentEntity<?, ?> entity) {
182182

183-
Map<TypeInformation<?>, Class<PersistentPropertyAccessor>> map = this.propertyAccessorClasses;
184-
Class<PersistentPropertyAccessor> propertyAccessorClass = map.get(entity.getTypeInformation());
183+
Map<TypeInformation<?>, Class<PersistentPropertyAccessor<?>>> map = this.propertyAccessorClasses;
184+
Class<PersistentPropertyAccessor<?>> propertyAccessorClass = map.get(entity.getTypeInformation());
185185

186186
if (propertyAccessorClass != null) {
187187
return propertyAccessorClass;
@@ -198,10 +198,10 @@ private synchronized Class<PersistentPropertyAccessor> potentiallyCreateAndRegis
198198
}
199199

200200
@SuppressWarnings("unchecked")
201-
private Class<PersistentPropertyAccessor> createAccessorClass(PersistentEntity<?, ?> entity) {
201+
private Class<PersistentPropertyAccessor<?>> createAccessorClass(PersistentEntity<?, ?> entity) {
202202

203203
try {
204-
return (Class<PersistentPropertyAccessor>) PropertyAccessorClassGenerator.generateCustomAccessorClass(entity);
204+
return (Class<PersistentPropertyAccessor<?>>) PropertyAccessorClassGenerator.generateCustomAccessorClass(entity);
205205
} catch (Exception e) {
206206
throw new RuntimeException(e);
207207
}

src/main/java/org/springframework/data/mapping/model/ConvertingPropertyAccessor.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@
3030
* @author Oliver Gierke
3131
* @author Mark Paluch
3232
*/
33-
public class ConvertingPropertyAccessor implements PersistentPropertyAccessor {
33+
public class ConvertingPropertyAccessor<T> implements PersistentPropertyAccessor<T> {
3434

35-
private final PersistentPropertyAccessor accessor;
35+
private final PersistentPropertyAccessor<T> accessor;
3636
private final ConversionService conversionService;
3737

3838
/**
@@ -42,7 +42,7 @@ public class ConvertingPropertyAccessor implements PersistentPropertyAccessor {
4242
* @param accessor must not be {@literal null}.
4343
* @param conversionService must not be {@literal null}.
4444
*/
45-
public ConvertingPropertyAccessor(PersistentPropertyAccessor accessor, ConversionService conversionService) {
45+
public ConvertingPropertyAccessor(PersistentPropertyAccessor<T> accessor, ConversionService conversionService) {
4646

4747
Assert.notNull(accessor, "PersistentPropertyAccessor must not be null!");
4848
Assert.notNull(conversionService, "ConversionService must not be null!");
@@ -78,7 +78,7 @@ public Object getProperty(PersistentProperty<?> property) {
7878
* @return
7979
*/
8080
@Nullable
81-
public <T> T getProperty(PersistentProperty<?> property, Class<T> targetType) {
81+
public <S> S getProperty(PersistentProperty<?> property, Class<S> targetType) {
8282

8383
Assert.notNull(property, "PersistentProperty must not be null!");
8484
Assert.notNull(targetType, "Target type must not be null!");
@@ -91,7 +91,7 @@ public <T> T getProperty(PersistentProperty<?> property, Class<T> targetType) {
9191
* @see org.springframework.data.mapping.PersistentPropertyAccessor#getBean()
9292
*/
9393
@Override
94-
public Object getBean() {
94+
public T getBean() {
9595
return accessor.getBean();
9696
}
9797

@@ -105,8 +105,8 @@ public Object getBean() {
105105
*/
106106
@Nullable
107107
@SuppressWarnings("unchecked")
108-
private <T> T convertIfNecessary(@Nullable Object source, Class<T> type) {
109-
return (T) (source == null ? null
108+
private <S> S convertIfNecessary(@Nullable Object source, Class<S> type) {
109+
return (S) (source == null ? null
110110
: type.isAssignableFrom(source.getClass()) ? source : conversionService.convert(source, type));
111111
}
112112
}

src/main/java/org/springframework/data/mapping/model/IdPropertyIdentifierAccessor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
*/
3333
public class IdPropertyIdentifierAccessor extends TargetAwareIdentifierAccessor {
3434

35-
private final PersistentPropertyAccessor accessor;
35+
private final PersistentPropertyAccessor<?> accessor;
3636
private final PersistentProperty<?> idProperty;
3737

3838
/**

src/main/java/org/springframework/data/mapping/model/PersistentPropertyAccessorFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public interface PersistentPropertyAccessorFactory {
3434
* @param bean must not be {@literal null}.
3535
* @return will never be {@literal null}.
3636
*/
37-
PersistentPropertyAccessor getPropertyAccessor(PersistentEntity<?, ?> entity, Object bean);
37+
<T> PersistentPropertyAccessor<T> getPropertyAccessor(PersistentEntity<?, ?> entity, T bean);
3838

3939
/**
4040
* Returns whether given {@link PersistentEntity} is supported by this {@link PersistentPropertyAccessorFactory}.

src/test/java/org/springframework/data/mapping/model/BasicPersistentEntityUnitTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ public void returnsBeanWrapperForPropertyAccessor() {
193193
PersistentEntity<Object, SamplePersistentProperty> entity = context.getRequiredPersistentEntity(Entity.class);
194194

195195
Entity value = new Entity();
196-
PersistentPropertyAccessor accessor = entity.getPropertyAccessor(value);
196+
PersistentPropertyAccessor<Entity> accessor = entity.getPropertyAccessor(value);
197197

198198
assertThat(accessor).isInstanceOf(BeanWrapper.class);
199199
assertThat(accessor.getBean()).isEqualTo(value);

src/test/java/org/springframework/data/mapping/model/PersistentPropertyAccessorTests.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,11 @@
4242
@RunWith(Parameterized.class)
4343
public class PersistentPropertyAccessorTests {
4444

45-
private final static SampleMappingContext mappingContext = new SampleMappingContext();
45+
private final static SampleMappingContext MAPPING_CONTEXT = new SampleMappingContext();
4646

47-
private final Function<Object, PersistentPropertyAccessor> propertyAccessorFunction;
47+
private final Function<Object, PersistentPropertyAccessor<?>> propertyAccessorFunction;
4848

49-
public PersistentPropertyAccessorTests(Function<Object, PersistentPropertyAccessor> propertyAccessor,
49+
public PersistentPropertyAccessorTests(Function<Object, PersistentPropertyAccessor<?>> propertyAccessor,
5050
String displayName) {
5151

5252
this.propertyAccessorFunction = propertyAccessor;
@@ -60,9 +60,9 @@ public static List<Object[]> parameters() {
6060

6161
ClassGeneratingPropertyAccessorFactory factory = new ClassGeneratingPropertyAccessorFactory();
6262

63-
Function<Object, PersistentPropertyAccessor> beanWrapper = BeanWrapper::new;
64-
Function<Object, PersistentPropertyAccessor> classGenerating = it -> factory
65-
.getPropertyAccessor(mappingContext.getRequiredPersistentEntity(it.getClass()), it);
63+
Function<Object, PersistentPropertyAccessor<?>> beanWrapper = BeanWrapper::new;
64+
Function<Object, PersistentPropertyAccessor<?>> classGenerating = it -> factory
65+
.getPropertyAccessor(MAPPING_CONTEXT.getRequiredPersistentEntity(it.getClass()), it);
6666

6767
parameters.add(new Object[] { beanWrapper, "BeanWrapper" });
6868
parameters.add(new Object[] { classGenerating, "ClassGeneratingPropertyAccessorFactory" });
@@ -147,8 +147,7 @@ public void shouldRejectImmutableKotlinClassPropertyUpdate() {
147147
}
148148

149149
private static SamplePersistentProperty getProperty(Object bean, String propertyName) {
150-
151-
return mappingContext.getRequiredPersistentEntity(bean.getClass()).getRequiredPersistentProperty(propertyName);
150+
return MAPPING_CONTEXT.getRequiredPersistentEntity(bean.getClass()).getRequiredPersistentProperty(propertyName);
152151
}
153152

154153
@Data

0 commit comments

Comments
 (0)