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.
This commit is contained in:
Oliver Gierke
2018-06-18 19:06:45 +02:00
parent d1ebfcfc5e
commit 1f4d494f83
12 changed files with 38 additions and 39 deletions

View File

@@ -285,7 +285,7 @@ public interface PersistentEntity<T, P extends PersistentProperty<P>> extends It
* @return new {@link PersistentPropertyAccessor}.
* @since 1.10
*/
PersistentPropertyAccessor getPropertyAccessor(Object bean);
<B> PersistentPropertyAccessor<B> getPropertyAccessor(B bean);
/**
* Returns the {@link IdentifierAccessor} for the given bean.

View File

@@ -33,7 +33,7 @@ import org.springframework.util.Assert;
* @see PersistentEntity#getPropertyAccessor(Object)
* @see ConvertingPropertyAccessor
*/
public interface PersistentPropertyAccessor {
public interface PersistentPropertyAccessor<T> {
/**
* Sets the given {@link PersistentProperty} to the given value. Will do type conversion if a
@@ -71,7 +71,7 @@ public interface PersistentPropertyAccessor {
getBean().getClass().getName()));
}
PersistentPropertyAccessor accessor = parent == getBean() //
PersistentPropertyAccessor<?> accessor = parent == getBean() //
? this //
: leafProperty.getOwner().getPropertyAccessor(parent);
@@ -126,7 +126,7 @@ public interface PersistentPropertyAccessor {
}
PersistentEntity<?, ? extends PersistentProperty<?>> entity = property.getOwner();
PersistentPropertyAccessor accessor = entity.getPropertyAccessor(current);
PersistentPropertyAccessor<Object> accessor = entity.getPropertyAccessor(current);
current = accessor.getProperty(property);
}
@@ -140,5 +140,5 @@ public interface PersistentPropertyAccessor {
*
* @return will never be {@literal null}.
*/
Object getBean();
T getBean();
}

View File

@@ -461,7 +461,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
* @see org.springframework.data.mapping.PersistentEntity#getPropertyAccessor(java.lang.Object)
*/
@Override
public PersistentPropertyAccessor getPropertyAccessor(Object bean) {
public <B> PersistentPropertyAccessor<B> getPropertyAccessor(B bean) {
verifyBeanType(bean);

View File

@@ -40,7 +40,7 @@ import org.springframework.util.ReflectionUtils;
* @author Oliver Gierke
* @author Mark Paluch
*/
class BeanWrapper<T> implements PersistentPropertyAccessor {
class BeanWrapper<T> implements PersistentPropertyAccessor<T> {
private T bean;

View File

@@ -32,7 +32,7 @@ enum BeanWrapperPropertyAccessorFactory implements PersistentPropertyAccessorFac
* @see org.springframework.data.mapping.model.PersistentPropertyAccessorFactory#getPropertyAccessor(org.springframework.data.mapping.PersistentEntity, java.lang.Object)
*/
@Override
public PersistentPropertyAccessor getPropertyAccessor(PersistentEntity<?, ?> entity, Object bean) {
public <T> PersistentPropertyAccessor<T> getPropertyAccessor(PersistentEntity<?, ?> entity, T bean) {
return new BeanWrapper<>(bean);
}

View File

@@ -83,7 +83,7 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
private final ThreadLocal<Object[]> argumentCache = ThreadLocal.withInitial(() -> new Object[1]);
private volatile Map<PersistentEntity<?, ?>, Constructor<?>> constructorMap = new HashMap<>(32);
private volatile Map<TypeInformation<?>, Class<PersistentPropertyAccessor>> propertyAccessorClasses = new HashMap<>(
private volatile Map<TypeInformation<?>, Class<PersistentPropertyAccessor<?>>> propertyAccessorClasses = new HashMap<>(
32);
/*
@@ -91,13 +91,13 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
* @see org.springframework.data.mapping.model.PersistentPropertyAccessorFactory#getPropertyAccessor(org.springframework.data.mapping.PersistentEntity, java.lang.Object)
*/
@Override
public PersistentPropertyAccessor getPropertyAccessor(PersistentEntity<?, ?> entity, Object bean) {
public <T> PersistentPropertyAccessor<T> getPropertyAccessor(PersistentEntity<?, ?> entity, T bean) {
Constructor<?> constructor = constructorMap.get(entity);
if (constructor == null) {
Class<PersistentPropertyAccessor> accessorClass = potentiallyCreateAndRegisterPersistentPropertyAccessorClass(
Class<PersistentPropertyAccessor<?>> accessorClass = potentiallyCreateAndRegisterPersistentPropertyAccessorClass(
entity);
constructor = accessorClass.getConstructors()[0];
@@ -110,7 +110,7 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
args[0] = bean;
try {
return (PersistentPropertyAccessor) constructor.newInstance(args);
return (PersistentPropertyAccessor<T>) constructor.newInstance(args);
} catch (Exception e) {
throw new IllegalArgumentException(String.format("Cannot create persistent property accessor for %s", entity), e);
} finally {
@@ -177,11 +177,11 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
/**
* @param entity must not be {@literal null}.
*/
private synchronized Class<PersistentPropertyAccessor> potentiallyCreateAndRegisterPersistentPropertyAccessorClass(
private synchronized Class<PersistentPropertyAccessor<?>> potentiallyCreateAndRegisterPersistentPropertyAccessorClass(
PersistentEntity<?, ?> entity) {
Map<TypeInformation<?>, Class<PersistentPropertyAccessor>> map = this.propertyAccessorClasses;
Class<PersistentPropertyAccessor> propertyAccessorClass = map.get(entity.getTypeInformation());
Map<TypeInformation<?>, Class<PersistentPropertyAccessor<?>>> map = this.propertyAccessorClasses;
Class<PersistentPropertyAccessor<?>> propertyAccessorClass = map.get(entity.getTypeInformation());
if (propertyAccessorClass != null) {
return propertyAccessorClass;
@@ -198,10 +198,10 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
}
@SuppressWarnings("unchecked")
private Class<PersistentPropertyAccessor> createAccessorClass(PersistentEntity<?, ?> entity) {
private Class<PersistentPropertyAccessor<?>> createAccessorClass(PersistentEntity<?, ?> entity) {
try {
return (Class<PersistentPropertyAccessor>) PropertyAccessorClassGenerator.generateCustomAccessorClass(entity);
return (Class<PersistentPropertyAccessor<?>>) PropertyAccessorClassGenerator.generateCustomAccessorClass(entity);
} catch (Exception e) {
throw new RuntimeException(e);
}

View File

@@ -30,9 +30,9 @@ import org.springframework.util.Assert;
* @author Oliver Gierke
* @author Mark Paluch
*/
public class ConvertingPropertyAccessor implements PersistentPropertyAccessor {
public class ConvertingPropertyAccessor<T> implements PersistentPropertyAccessor<T> {
private final PersistentPropertyAccessor accessor;
private final PersistentPropertyAccessor<T> accessor;
private final ConversionService conversionService;
/**
@@ -42,7 +42,7 @@ public class ConvertingPropertyAccessor implements PersistentPropertyAccessor {
* @param accessor must not be {@literal null}.
* @param conversionService must not be {@literal null}.
*/
public ConvertingPropertyAccessor(PersistentPropertyAccessor accessor, ConversionService conversionService) {
public ConvertingPropertyAccessor(PersistentPropertyAccessor<T> accessor, ConversionService conversionService) {
Assert.notNull(accessor, "PersistentPropertyAccessor must not be null!");
Assert.notNull(conversionService, "ConversionService must not be null!");
@@ -78,7 +78,7 @@ public class ConvertingPropertyAccessor implements PersistentPropertyAccessor {
* @return
*/
@Nullable
public <T> T getProperty(PersistentProperty<?> property, Class<T> targetType) {
public <S> S getProperty(PersistentProperty<?> property, Class<S> targetType) {
Assert.notNull(property, "PersistentProperty must not be null!");
Assert.notNull(targetType, "Target type must not be null!");
@@ -91,7 +91,7 @@ public class ConvertingPropertyAccessor implements PersistentPropertyAccessor {
* @see org.springframework.data.mapping.PersistentPropertyAccessor#getBean()
*/
@Override
public Object getBean() {
public T getBean() {
return accessor.getBean();
}
@@ -105,8 +105,8 @@ public class ConvertingPropertyAccessor implements PersistentPropertyAccessor {
*/
@Nullable
@SuppressWarnings("unchecked")
private <T> T convertIfNecessary(@Nullable Object source, Class<T> type) {
return (T) (source == null ? null
private <S> S convertIfNecessary(@Nullable Object source, Class<S> type) {
return (S) (source == null ? null
: type.isAssignableFrom(source.getClass()) ? source : conversionService.convert(source, type));
}
}

View File

@@ -32,7 +32,7 @@ import org.springframework.util.Assert;
*/
public class IdPropertyIdentifierAccessor extends TargetAwareIdentifierAccessor {
private final PersistentPropertyAccessor accessor;
private final PersistentPropertyAccessor<?> accessor;
private final PersistentProperty<?> idProperty;
/**

View File

@@ -34,7 +34,7 @@ public interface PersistentPropertyAccessorFactory {
* @param bean must not be {@literal null}.
* @return will never be {@literal null}.
*/
PersistentPropertyAccessor getPropertyAccessor(PersistentEntity<?, ?> entity, Object bean);
<T> PersistentPropertyAccessor<T> getPropertyAccessor(PersistentEntity<?, ?> entity, T bean);
/**
* Returns whether given {@link PersistentEntity} is supported by this {@link PersistentPropertyAccessorFactory}.