DATAREST-415 - Moved to PersistentPropertyAccessor API.

We now use the PersistentPropertyAccessor provided by the PersistentEntity to lookup property values to benefit from store-specific customizations. Code that relies on value conversion by using a ConversionService now explicitly uses a ConvertingPropertyAccessor.

Related tickets: DATACMNS-596.
This commit is contained in:
Oliver Gierke
2014-11-21 10:32:27 +01:00
parent 458cdfa7e8
commit 780d674012
5 changed files with 53 additions and 37 deletions

View File

@@ -21,6 +21,7 @@ import java.util.List;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.Resource;
import org.springframework.hateoas.Resources;
@@ -75,6 +76,15 @@ public class PersistentEntityResource extends Resource<Object> {
return entity;
}
/**
* Returns the {@link PersistentPropertyAccessor} for the underlying content bean.
*
* @return
*/
public PersistentPropertyAccessor getPropertyAccessor() {
return entity.getPropertyAccessor(getContent());
}
/**
* Returns the resources that are supposed to be rendered in the {@code _embedded} clause.
*

View File

@@ -22,8 +22,8 @@ import java.util.List;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.mapping.SimpleAssociationHandler;
import org.springframework.data.mapping.model.BeanWrapper;
import org.springframework.data.repository.support.Repositories;
import org.springframework.data.rest.core.mapping.ResourceMappings;
import org.springframework.data.rest.core.mapping.ResourceMetadata;
@@ -121,7 +121,7 @@ public class PersistentEntityResourceAssembler implements ResourceAssembler<Obje
PersistentEntity<?, ?> entity = repositories.getPersistentEntity(instance.getClass());
final List<EmbeddedWrapper> associationProjections = new ArrayList<EmbeddedWrapper>();
final BeanWrapper<Object> wrapper = BeanWrapper.create(instance, null);
final PersistentPropertyAccessor accessor = entity.getPropertyAccessor(instance);
final AssociationLinks associationLinks = new AssociationLinks(mappings);
final ResourceMetadata metadata = mappings.getMappingFor(instance.getClass());
@@ -144,7 +144,7 @@ public class PersistentEntityResourceAssembler implements ResourceAssembler<Obje
return;
}
Object value = wrapper.getProperty(association.getInverse());
Object value = accessor.getProperty(association.getInverse());
if (value == null) {
return;
@@ -197,8 +197,8 @@ public class PersistentEntityResourceAssembler implements ResourceAssembler<Obje
instanceType));
}
BeanWrapper<Object> wrapper = BeanWrapper.create(instance, null);
Object id = wrapper.getProperty(entity.getIdProperty());
PersistentPropertyAccessor accessor = entity.getPropertyAccessor(instance);
Object id = accessor.getProperty(entity.getIdProperty());
Link resourceLink = entityLinks.linkToSingleResource(entity.getType(), id);
return new Link(resourceLink.getHref(), Link.REL_SELF);

View File

@@ -29,7 +29,8 @@ import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.domain.Sort;
import org.springframework.data.mapping.model.BeanWrapper;
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
import org.springframework.data.repository.invoker.RepositoryInvoker;
import org.springframework.data.repository.support.Repositories;
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
@@ -314,7 +315,8 @@ class RepositoryEntityController extends AbstractRepositoryRestController implem
resourceInformation.verifySupportedMethod(HttpMethod.PUT, ResourceType.ITEM);
// Force ID on unmarshalled object
BeanWrapper<Object> incomingWrapper = BeanWrapper.create(payload.getContent(), conversionService);
PersistentPropertyAccessor incomingWrapper = new ConvertingPropertyAccessor(payload.getPropertyAccessor(),
conversionService);
incomingWrapper.setProperty(payload.getPersistentEntity().getIdProperty(), id);
RepositoryInvoker invoker = resourceInformation.getInvoker();

View File

@@ -35,7 +35,7 @@ import org.springframework.core.CollectionFactory;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.model.BeanWrapper;
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.repository.invoker.RepositoryInvoker;
import org.springframework.data.repository.support.Repositories;
import org.springframework.data.rest.core.event.AfterLinkDeleteEvent;
@@ -175,11 +175,11 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro
} else if (prop.property.isMap()) {
throw new HttpRequestMethodNotSupportedException("DELETE");
} else {
prop.wrapper.setProperty(prop.property, null);
prop.accessor.setProperty(prop.property, null);
}
publisher.publishEvent(new BeforeLinkDeleteEvent(prop.wrapper.getBean(), prop.propertyValue));
Object result = repoMethodInvoker.invokeSave(prop.wrapper.getBean());
publisher.publishEvent(new BeforeLinkDeleteEvent(prop.accessor.getBean(), prop.propertyValue));
Object result = repoMethodInvoker.invokeSave(prop.accessor.getBean());
publisher.publishEvent(new AfterLinkDeleteEvent(result, prop.propertyValue));
return null;
@@ -209,8 +209,8 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro
if (prop.property.isCollectionLike()) {
for (Object obj : (Iterable<?>) prop.propertyValue) {
BeanWrapper<Object> propValWrapper = BeanWrapper.create(obj, null);
String sId = propValWrapper.getProperty(prop.entity.getIdProperty()).toString();
PersistentPropertyAccessor accessor = prop.entity.getPropertyAccessor(obj);
String sId = accessor.getProperty(prop.entity.getIdProperty()).toString();
if (propertyId.equals(sId)) {
@@ -222,8 +222,8 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro
} else if (prop.property.isMap()) {
for (Map.Entry<Object, Object> entry : ((Map<Object, Object>) prop.propertyValue).entrySet()) {
BeanWrapper<Object> propValWrapper = BeanWrapper.create(entry.getValue(), null);
String sId = propValWrapper.getProperty(prop.entity.getIdProperty()).toString();
PersistentPropertyAccessor accessor = prop.entity.getPropertyAccessor(entry.getValue());
String sId = accessor.getProperty(prop.entity.getIdProperty()).toString();
if (propertyId.equals(sId)) {
@@ -325,7 +325,7 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro
coll.add(propVal);
}
prop.wrapper.setProperty(prop.property, coll);
prop.accessor.setProperty(prop.property, coll);
} else if (prop.property.isMap()) {
@@ -342,7 +342,7 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro
m.put(l.getRel(), propVal);
}
prop.wrapper.setProperty(prop.property, m);
prop.accessor.setProperty(prop.property, m);
} else {
@@ -357,11 +357,11 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro
}
Object propVal = loadPropertyValue(prop.propertyType, incoming.getLinks().get(0));
prop.wrapper.setProperty(prop.property, propVal);
prop.accessor.setProperty(prop.property, propVal);
}
publisher.publishEvent(new BeforeLinkSaveEvent(prop.wrapper.getBean(), prop.propertyValue));
Object result = invoker.invokeSave(prop.wrapper.getBean());
publisher.publishEvent(new BeforeLinkSaveEvent(prop.accessor.getBean(), prop.propertyValue));
Object result = invoker.invokeSave(prop.accessor.getBean());
publisher.publishEvent(new AfterLinkSaveEvent(result, prop.propertyValue));
return null;
@@ -400,8 +400,9 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro
Iterator<Object> itr = coll.iterator();
while (itr.hasNext()) {
Object obj = itr.next();
BeanWrapper<Object> propValWrapper = BeanWrapper.create(obj, null);
String s = propValWrapper.getProperty(prop.entity.getIdProperty()).toString();
PersistentPropertyAccessor accessor = prop.entity.getPropertyAccessor(obj);
String s = accessor.getProperty(prop.entity.getIdProperty()).toString();
if (propertyId.equals(s)) {
itr.remove();
}
@@ -411,18 +412,18 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro
Iterator<Object> itr = m.keySet().iterator();
while (itr.hasNext()) {
Object key = itr.next();
BeanWrapper<Object> propValWrapper = BeanWrapper.create(m.get(key), null);
String s = propValWrapper.getProperty(prop.entity.getIdProperty()).toString();
PersistentPropertyAccessor accessor = prop.entity.getPropertyAccessor(m.get(key));
String s = accessor.getProperty(prop.entity.getIdProperty()).toString();
if (propertyId.equals(s)) {
itr.remove();
}
}
} else {
prop.wrapper.setProperty(prop.property, null);
prop.accessor.setProperty(prop.property, null);
}
publisher.publishEvent(new BeforeLinkDeleteEvent(prop.wrapper.getBean(), prop.propertyValue));
Object result = invoker.invokeSave(prop.wrapper.getBean());
publisher.publishEvent(new BeforeLinkDeleteEvent(prop.accessor.getBean(), prop.propertyValue));
Object result = invoker.invokeSave(prop.accessor.getBean());
publisher.publishEvent(new AfterLinkDeleteEvent(result, prop.propertyValue));
return null;
@@ -456,15 +457,17 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro
throw new ResourceNotFoundException();
}
PersistentProperty<?> prop = repoRequest.getPersistentEntity().getPersistentProperty(propertyPath);
PersistentEntity<?, ?> persistentEntity = repoRequest.getPersistentEntity();
PersistentProperty<?> prop = persistentEntity.getPersistentProperty(propertyPath);
if (null == prop) {
throw new ResourceNotFoundException();
}
BeanWrapper<Object> wrapper = BeanWrapper.create(domainObj, null);
Object propVal = wrapper.getProperty(prop);
PersistentPropertyAccessor accessor = persistentEntity.getPropertyAccessor(domainObj);
Object propVal = accessor.getProperty(prop);
return handler.apply(new ReferencedProperty(prop, propVal, wrapper));
return handler.apply(new ReferencedProperty(prop, propVal, accessor));
}
private class ReferencedProperty {
@@ -473,13 +476,13 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro
final PersistentProperty<?> property;
final Class<?> propertyType;
final Object propertyValue;
final BeanWrapper<?> wrapper;
final PersistentPropertyAccessor accessor;
private ReferencedProperty(PersistentProperty<?> property, Object propertyValue, BeanWrapper<?> wrapper) {
private ReferencedProperty(PersistentProperty<?> property, Object propertyValue, PersistentPropertyAccessor wrapper) {
this.property = property;
this.propertyValue = propertyValue;
this.wrapper = wrapper;
this.accessor = wrapper;
this.propertyType = property.getActualType();
this.entity = repositories.getPersistentEntity(propertyType);
}

View File

@@ -21,8 +21,8 @@ import java.util.Map.Entry;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.mapping.context.PersistentEntities;
import org.springframework.data.mapping.model.BeanWrapper;
import org.springframework.data.rest.core.mapping.ResourceMappings;
import org.springframework.data.rest.webmvc.mapping.AssociationLinks;
import org.springframework.http.converter.HttpMessageNotReadableException;
@@ -118,8 +118,9 @@ public class DomainObjectReader {
continue;
}
BeanWrapper<T> wrapper = BeanWrapper.create(existingObject, null);
Object nested = wrapper.getProperty(property);
PersistentEntity<?, ?> entity = entities.getPersistentEntity(existingObject.getClass());
PersistentPropertyAccessor accessor = entity.getPropertyAccessor(existingObject);
Object nested = accessor.getProperty(property);
if (nested != null) {