DATAREST-93 - Improvements after API updates in Spring Data Commons.

Switched to the usage of Simple(Property|Association)Handler to avoid having to use raw PersistentProperty instances.
This commit is contained in:
Oliver Gierke
2013-11-14 09:54:03 +00:00
parent 8f2e3eb4fe
commit 4ee1850a37
5 changed files with 102 additions and 59 deletions

View File

@@ -23,7 +23,6 @@ import java.util.List;
import java.util.Map;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty;
import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.repository.support.Repositories;
import org.springframework.data.rest.core.Path;
@@ -267,8 +266,7 @@ public class ResourceMappings implements Iterable<ResourceMetadata> {
Assert.notNull(property, "PersistentProperty must not be null!");
this.property = property;
this.typeMapping = typeMapping;
this.annotation = property instanceof AnnotationBasedPersistentProperty ? ((AnnotationBasedPersistentProperty<?>) property)
.findAnnotation(RestResource.class) : null;
this.annotation = property.findAnnotation(RestResource.class);
}
/*

View File

@@ -18,15 +18,17 @@ package org.springframework.data.rest.core.support;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.AssociationHandler;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.mapping.SimpleAssociationHandler;
import org.springframework.data.mapping.SimplePropertyHandler;
import org.springframework.data.mapping.model.BeanWrapper;
import org.springframework.data.repository.support.Repositories;
import org.springframework.util.Assert;
/**
* @author Jon Brisbin
* @author Oliver Gierke
*/
public class DomainObjectMerger {
@@ -35,32 +37,51 @@ public class DomainObjectMerger {
@Autowired
public DomainObjectMerger(Repositories repositories, ConversionService conversionService) {
Assert.notNull(repositories, "Repositories must not be null!");
Assert.notNull(conversionService, "ConversionService must not be null!");
this.repositories = repositories;
this.conversionService = conversionService;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public void merge(Object from, Object target) {
if (null == from || null == target) {
return;
}
final BeanWrapper<?, Object> fromWrapper = BeanWrapper.create(from, conversionService);
final BeanWrapper<?, Object> targetWrapper = BeanWrapper.create(target, conversionService);
PersistentEntity<?, ?> entity = repositories.getPersistentEntity(target.getClass());
entity.doWithProperties(new PropertyHandler() {
entity.doWithProperties(new SimplePropertyHandler() {
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.SimplePropertyHandler#doWithPersistentProperty(org.springframework.data.mapping.PersistentProperty)
*/
@Override
public void doWithPersistentProperty(PersistentProperty persistentProperty) {
Object fromVal = fromWrapper.getProperty(persistentProperty);
if (null != fromVal && !fromVal.equals(targetWrapper.getProperty(persistentProperty))) {
targetWrapper.setProperty(persistentProperty, fromVal);
public void doWithPersistentProperty(PersistentProperty<?> property) {
Object fromVal = fromWrapper.getProperty(property);
if (null != fromVal && !fromVal.equals(targetWrapper.getProperty(property))) {
targetWrapper.setProperty(property, fromVal);
}
}
});
entity.doWithAssociations(new AssociationHandler() {
entity.doWithAssociations(new SimpleAssociationHandler() {
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.SimpleAssociationHandler#doWithAssociation(org.springframework.data.mapping.Association)
*/
@Override
public void doWithAssociation(Association association) {
PersistentProperty persistentProperty = association.getInverse();
public void doWithAssociation(Association<? extends PersistentProperty<?>> association) {
PersistentProperty<?> persistentProperty = association.getInverse();
Object fromVal = fromWrapper.getProperty(persistentProperty);
if (null != fromVal && !fromVal.equals(targetWrapper.getProperty(persistentProperty))) {
targetWrapper.setProperty(persistentProperty, fromVal);
@@ -68,5 +89,4 @@ public class DomainObjectMerger {
}
});
}
}

View File

@@ -219,9 +219,11 @@ class RepositorySearchController extends AbstractRepositoryRestController {
private Links getSearchLinks(Class<?> domainType) {
List<Link> links = new ArrayList<Link>();
LinkBuilder builder = entityLinks.linkFor(domainType).slash(SEARCH);
for (ResourceMapping mapping : mappings.getSearchResourceMappings(domainType)) {
SearchResourceMappings searchMappings = mappings.getSearchResourceMappings(domainType);
LinkBuilder builder = entityLinks.linkFor(domainType).slash(searchMappings.getPath());
for (ResourceMapping mapping : searchMappings) {
if (!mapping.isExported()) {
continue;

View File

@@ -19,10 +19,10 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.AssociationHandler;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.mapping.SimpleAssociationHandler;
import org.springframework.data.mapping.SimplePropertyHandler;
import org.springframework.data.mapping.model.BeanWrapper;
import org.springframework.data.repository.support.Repositories;
import org.springframework.data.rest.core.UriDomainClassConverter;
@@ -234,26 +234,29 @@ public class PersistentEntityJackson2Module extends SimpleModule implements Init
}
}
@SuppressWarnings("rawtypes")
private class ResourceSerializer extends StdSerializer<PersistentEntityResource> {
private class ResourceSerializer extends StdSerializer<PersistentEntityResource<?>> {
@SuppressWarnings({ "unchecked", "rawtypes" })
private ResourceSerializer() {
super(PersistentEntityResource.class);
super((Class) PersistentEntityResource.class);
}
@SuppressWarnings({ "unchecked" })
/*
* (non-Javadoc)
* @see com.fasterxml.jackson.databind.ser.std.StdSerializer#serialize(java.lang.Object, com.fasterxml.jackson.core.JsonGenerator, com.fasterxml.jackson.databind.SerializerProvider)
*/
@Override
public void serialize(final PersistentEntityResource resource, final JsonGenerator jgen,
public void serialize(final PersistentEntityResource<?> resource, final JsonGenerator jgen,
final SerializerProvider provider) throws IOException, JsonGenerationException {
if (LOG.isDebugEnabled()) {
LOG.debug("Serializing PersistentEntity " + resource.getPersistentEntity());
}
Object obj = resource.getContent();
final PersistentEntity entity = resource.getPersistentEntity();
final BeanWrapper wrapper = BeanWrapper.create(obj, null);
final PersistentEntity<?, ?> entity = resource.getPersistentEntity();
final BeanWrapper<PersistentEntity<Object, ?>, Object> wrapper = BeanWrapper.create(obj, null);
final Object entityId = wrapper.getProperty(entity.getIdProperty());
final ResourceMappings mappings = new ResourceMappings(config, repositories);
final ResourceMetadata metadata = mappings.getMappingFor(entity.getType());
@@ -262,12 +265,18 @@ public class PersistentEntityJackson2Module extends SimpleModule implements Init
final List<Link> links = new ArrayList<Link>();
// Start with ResourceProcessor-added links
links.addAll(resource.getLinks());
jgen.writeStartObject();
try {
entity.doWithProperties(new PropertyHandler() {
entity.doWithProperties(new SimplePropertyHandler() {
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.SimplePropertyHandler#doWithPersistentProperty(org.springframework.data.mapping.PersistentProperty)
*/
@Override
public void doWithPersistentProperty(PersistentProperty property) {
public void doWithPersistentProperty(PersistentProperty<?> property) {
boolean idAvailableAndShallNotBeExposed = property.isIdProperty()
&& !config.isIdExposedFor(entity.getType());
@@ -276,10 +285,6 @@ public class PersistentEntityJackson2Module extends SimpleModule implements Init
return;
}
// if (property.isEntity() && maybeAddAssociationLink(builder, mappings, property, links)) {
// return;
// }
// Property is a normal or non-managed property.
Object propertyValue = wrapper.getProperty(property);
try {
@@ -291,11 +296,16 @@ public class PersistentEntityJackson2Module extends SimpleModule implements Init
});
// Add associations as links
entity.doWithAssociations(new AssociationHandler() {
@Override
public void doWithAssociation(Association association) {
entity.doWithAssociations(new SimpleAssociationHandler() {
PersistentProperty property = association.getInverse();
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.SimpleAssociationHandler#doWithAssociation(org.springframework.data.mapping.Association)
*/
@Override
public void doWithAssociation(Association<? extends PersistentProperty<?>> association) {
PersistentProperty<?> property = association.getInverse();
if (!mappings.isMapped(property)) {
return;
@@ -315,9 +325,11 @@ public class PersistentEntityJackson2Module extends SimpleModule implements Init
});
jgen.writeArrayFieldStart("links");
for (Link l : links) {
jgen.writeObject(l);
}
jgen.writeEndArray();
} catch (IllegalStateException e) {
@@ -327,5 +339,4 @@ public class PersistentEntityJackson2Module extends SimpleModule implements Init
}
}
}
}

View File

@@ -13,19 +13,21 @@ import javax.validation.constraints.NotNull;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.ConditionalGenericConverter;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.AssociationHandler;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.mapping.SimpleAssociationHandler;
import org.springframework.data.mapping.SimplePropertyHandler;
import org.springframework.data.repository.support.Repositories;
import org.springframework.data.rest.core.annotation.Description;
import org.springframework.data.rest.core.mapping.ResourceMappings;
import org.springframework.data.rest.core.mapping.ResourceMetadata;
import org.springframework.data.rest.webmvc.support.RepositoryLinkBuilder;
import org.springframework.hateoas.Link;
import org.springframework.util.Assert;
/**
* @author Jon Brisbin
* @author Oliver Gierke
*/
public class PersistentEntityToJsonSchemaConverter implements ConditionalGenericConverter {
@@ -37,11 +39,17 @@ public class PersistentEntityToJsonSchemaConverter implements ConditionalGeneric
private final Repositories repositories;
/**
* Creates a new {@link PersistentEntityToJsonSchemaConverter} for the given {@link Repositories} and
* {@link ResourceMappings}.
*
* @param repositories must not be {@literal null}.
* @param mappings must not be {@literal null}.
*/
public PersistentEntityToJsonSchemaConverter(Repositories repositories, ResourceMappings mappings) {
Assert.notNull(repositories, "Repositories must not be null!");
Assert.notNull(mappings, "ResourceMappings must not be null!");
this.repositories = repositories;
this.mappings = mappings;
@@ -73,7 +81,10 @@ public class PersistentEntityToJsonSchemaConverter implements ConditionalGeneric
return (JsonSchema) convert(domainType, STRING_TYPE, SCHEMA_TYPE);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
/*
* (non-Javadoc)
* @see org.springframework.core.convert.converter.GenericConverter#convert(java.lang.Object, org.springframework.core.convert.TypeDescriptor, org.springframework.core.convert.TypeDescriptor)
*/
@Override
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
@@ -81,41 +92,42 @@ public class PersistentEntityToJsonSchemaConverter implements ConditionalGeneric
final ResourceMetadata metadata = mappings.getMappingFor(persistentEntity.getType());
String entityDesc = persistentEntity.getType().isAnnotationPresent(Description.class) ? persistentEntity.getType()
.getAnnotation(Description.class).value() : null;
final JsonSchema jsonSchema = new JsonSchema(persistentEntity.getName(), entityDesc);
persistentEntity.doWithProperties(new PropertyHandler() {
persistentEntity.doWithProperties(new SimplePropertyHandler() {
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.PropertyHandler#doWithPersistentProperty(org.springframework.data.mapping.PersistentProperty)
*/
@Override
public void doWithPersistentProperty(PersistentProperty persistentProperty) {
public void doWithPersistentProperty(PersistentProperty<?> persistentProperty) {
Class<?> propertyType = persistentProperty.getType();
String type = uncapitalize(propertyType.getSimpleName());
boolean notNull = persistentProperty.getField().isAnnotationPresent(NotNull.class)
|| persistentProperty.getGetter().isAnnotationPresent(NotNull.class);
String desc = persistentProperty.getField().isAnnotationPresent(Description.class) ? persistentProperty
.getField().getAnnotation(Description.class).value() : persistentProperty.getGetter().isAnnotationPresent(
Description.class) ? persistentProperty.getGetter().getAnnotation(Description.class).value() : null;
JsonSchema.Property property;
if (persistentProperty.isCollectionLike()) {
property = new JsonSchema.ArrayProperty("array", desc, notNull);
} else {
property = new JsonSchema.Property(type, desc, notNull);
}
boolean notNull = persistentProperty.isAnnotationPresent(NotNull.class);
Description descriptionAnnotation = persistentProperty.findAnnotation(Description.class);
String desc = descriptionAnnotation == null ? null : descriptionAnnotation.value();
JsonSchema.Property property = persistentProperty.isCollectionLike() ? new JsonSchema.ArrayProperty("array",
desc, notNull) : new JsonSchema.Property(type, desc, notNull);
jsonSchema.addProperty(persistentProperty.getName(), property);
}
});
final List<Link> links = new ArrayList<Link>();
persistentEntity.doWithAssociations(new AssociationHandler() {
persistentEntity.doWithAssociations(new SimpleAssociationHandler() {
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.AssociationHandler#doWithAssociation(org.springframework.data.mapping.Association)
*/
@Override
public void doWithAssociation(Association association) {
public void doWithAssociation(Association<? extends PersistentProperty<?>> association) {
PersistentProperty persistentProperty = association.getInverse();
PersistentProperty<?> persistentProperty = association.getInverse();
if (!metadata.isExported(persistentProperty)) {
return;