From d575c37c7bfad192e922ca5948e3ed713bb449f5 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Thu, 26 Jan 2017 07:42:35 +0100 Subject: [PATCH] DATAREST-944 - Moved MappedProperties to separate class. This should ease backports from upstream branches. --- .../rest/webmvc/json/DomainObjectReader.java | 133 --------------- .../rest/webmvc/json/MappedProperties.java | 159 ++++++++++++++++++ .../json/MappedPropertiesUnitTests.java | 1 - 3 files changed, 159 insertions(+), 134 deletions(-) create mode 100644 spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappedProperties.java diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/DomainObjectReader.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/DomainObjectReader.java index cbe585ce4..f71788a65 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/DomainObjectReader.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/DomainObjectReader.java @@ -23,13 +23,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; -import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Set; import org.springframework.beans.PropertyAccessor; import org.springframework.beans.PropertyAccessorFactory; @@ -49,12 +45,8 @@ import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; -import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.introspect.BasicClassIntrospector; -import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; -import com.fasterxml.jackson.databind.introspect.ClassIntrospector; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -581,129 +573,4 @@ public class DomainObjectReader { return value.getClass().equals(type.getType()) ? type : ClassTypeInformation.from(value.getClass()); } - - /** - * Simple value object to capture a mapping of Jackson mapped field names and {@link PersistentProperty} instances. - * - * @author Oliver Gierke - * @author Mark Paluch - */ - static class MappedProperties { - - private static final ClassIntrospector INTROSPECTOR = new BasicClassIntrospector(); - - private final Map, BeanPropertyDefinition> propertyToFieldName; - private final Map> fieldNameToProperty; - private final Set unmappedProperties; - - /** - * Creates a new {@link MappedProperties} instance for the given {@link PersistentEntity} and - * {@link BeanDescription}. - * - * @param entity must not be {@literal null}. - * @param description must not be {@literal null}. - */ - private MappedProperties(PersistentEntity entity, BeanDescription description) { - - Assert.notNull(entity, "Entity must not be null!"); - Assert.notNull(description, "BeanDescription must not be null!"); - - this.propertyToFieldName = new HashMap, BeanPropertyDefinition>(); - this.fieldNameToProperty = new HashMap>(); - this.unmappedProperties = new HashSet(); - - for (BeanPropertyDefinition property : description.findProperties()) { - - PersistentProperty persistentProperty = entity.getPersistentProperty(property.getInternalName()); - - if (persistentProperty != null) { - propertyToFieldName.put(persistentProperty, property); - fieldNameToProperty.put(property.getName(), persistentProperty); - } else { - unmappedProperties.add(property); - } - } - } - - /** - * Creates {@link MappedProperties} for the given {@link PersistentEntity}. - * - * @param entity must not be {@literal null}. - * @param mapper must not be {@literal null}. - * @return - */ - public static MappedProperties fromJacksonProperties(PersistentEntity entity, ObjectMapper mapper) { - - BeanDescription description = INTROSPECTOR.forDeserialization(mapper.getDeserializationConfig(), - mapper.constructType(entity.getType()), mapper.getDeserializationConfig()); - - return new MappedProperties(entity, description); - } - - /** - * @param property must not be {@literal null} - * @return the mapped name for the {@link PersistentProperty} - */ - public String getMappedName(PersistentProperty property) { - - Assert.notNull(property, "PersistentProperty must not be null!"); - - return propertyToFieldName.get(property).getName(); - } - - /** - * @param fieldName must not be empty or {@literal null}. - * @return {@literal true} if the field name resolves to a {@literal PersistentProperty}. - */ - public boolean hasPersistentPropertyForField(String fieldName) { - - Assert.hasText(fieldName, "Field name must not be null or empty!"); - - return fieldNameToProperty.containsKey(fieldName); - } - - /** - * @param fieldName must not be empty or {@literal null}. - * @return the {@link PersistentProperty} backing the field with the field name. - */ - public PersistentProperty getPersistentProperty(String fieldName) { - - Assert.hasText(fieldName, "Field name must not be null or empty!"); - - return fieldNameToProperty.get(fieldName); - } - - /** - * Returns all properties only known to Jackson. - * - * @return the names of all properties that are not known to Spring Data but appear in the Jackson metamodel. - */ - public Iterable getSpringDataUnmappedProperties() { - - if (unmappedProperties.isEmpty()) { - return Collections.emptySet(); - } - - List result = new ArrayList(unmappedProperties.size()); - - for (BeanPropertyDefinition definitions : unmappedProperties) { - result.add(definitions.getInternalName()); - } - - return result; - } - - /** - * Returns whether the given {@link PersistentProperty} is mapped, i.e. known to both Jackson and Spring Data. - * - * @param property must not be {@literal null}. - * @return - */ - public boolean isMappedProperty(PersistentProperty property) { - - Assert.notNull(property, "PersistentProperty must not be null!"); - - return propertyToFieldName.containsKey(property); - } - } } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappedProperties.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappedProperties.java new file mode 100644 index 000000000..d1880d310 --- /dev/null +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappedProperties.java @@ -0,0 +1,159 @@ +/* + * Copyright 2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.rest.webmvc.json; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.springframework.data.mapping.PersistentEntity; +import org.springframework.data.mapping.PersistentProperty; +import org.springframework.util.Assert; + +import com.fasterxml.jackson.databind.BeanDescription; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.introspect.BasicClassIntrospector; +import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; +import com.fasterxml.jackson.databind.introspect.ClassIntrospector; + +/** + * Simple value object to capture a mapping of Jackson mapped field names and {@link PersistentProperty} instances. + * + * @author Oliver Gierke + * @author Mark Paluch + */ +class MappedProperties { + + private static final ClassIntrospector INTROSPECTOR = new BasicClassIntrospector(); + + private final Map, BeanPropertyDefinition> propertyToFieldName; + private final Map> fieldNameToProperty; + private final Set unmappedProperties; + + /** + * Creates a new {@link MappedProperties} instance for the given {@link PersistentEntity} and + * {@link BeanDescription}. + * + * @param entity must not be {@literal null}. + * @param description must not be {@literal null}. + */ + private MappedProperties(PersistentEntity entity, BeanDescription description) { + + Assert.notNull(entity, "Entity must not be null!"); + Assert.notNull(description, "BeanDescription must not be null!"); + + this.propertyToFieldName = new HashMap, BeanPropertyDefinition>(); + this.fieldNameToProperty = new HashMap>(); + this.unmappedProperties = new HashSet(); + + for (BeanPropertyDefinition property : description.findProperties()) { + + PersistentProperty persistentProperty = entity.getPersistentProperty(property.getInternalName()); + + if (persistentProperty != null) { + propertyToFieldName.put(persistentProperty, property); + fieldNameToProperty.put(property.getName(), persistentProperty); + } else { + unmappedProperties.add(property); + } + } + } + + /** + * Creates {@link MappedProperties} for the given {@link PersistentEntity}. + * + * @param entity must not be {@literal null}. + * @param mapper must not be {@literal null}. + * @return + */ + public static MappedProperties fromJacksonProperties(PersistentEntity entity, ObjectMapper mapper) { + + BeanDescription description = INTROSPECTOR.forDeserialization(mapper.getDeserializationConfig(), + mapper.constructType(entity.getType()), mapper.getDeserializationConfig()); + + return new MappedProperties(entity, description); + } + + /** + * @param property must not be {@literal null} + * @return the mapped name for the {@link PersistentProperty} + */ + public String getMappedName(PersistentProperty property) { + + Assert.notNull(property, "PersistentProperty must not be null!"); + + return propertyToFieldName.get(property).getName(); + } + + /** + * @param fieldName must not be empty or {@literal null}. + * @return {@literal true} if the field name resolves to a {@literal PersistentProperty}. + */ + public boolean hasPersistentPropertyForField(String fieldName) { + + Assert.hasText(fieldName, "Field name must not be null or empty!"); + + return fieldNameToProperty.containsKey(fieldName); + } + + /** + * @param fieldName must not be empty or {@literal null}. + * @return the {@link PersistentProperty} backing the field with the field name. + */ + public PersistentProperty getPersistentProperty(String fieldName) { + + Assert.hasText(fieldName, "Field name must not be null or empty!"); + + return fieldNameToProperty.get(fieldName); + } + + /** + * Returns all properties only known to Jackson. + * + * @return the names of all properties that are not known to Spring Data but appear in the Jackson metamodel. + */ + public Iterable getSpringDataUnmappedProperties() { + + if (unmappedProperties.isEmpty()) { + return Collections.emptySet(); + } + + List result = new ArrayList(unmappedProperties.size()); + + for (BeanPropertyDefinition definitions : unmappedProperties) { + result.add(definitions.getInternalName()); + } + + return result; + } + + /** + * Returns whether the given {@link PersistentProperty} is mapped, i.e. known to both Jackson and Spring Data. + * + * @param property must not be {@literal null}. + * @return + */ + public boolean isMappedProperty(PersistentProperty property) { + + Assert.notNull(property, "PersistentProperty must not be null!"); + + return propertyToFieldName.containsKey(property); + } +} \ No newline at end of file diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/MappedPropertiesUnitTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/MappedPropertiesUnitTests.java index 38767d554..c11c052e0 100644 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/MappedPropertiesUnitTests.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/MappedPropertiesUnitTests.java @@ -22,7 +22,6 @@ import org.junit.Test; import org.springframework.data.annotation.Transient; import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentEntity; import org.springframework.data.keyvalue.core.mapping.context.KeyValueMappingContext; -import org.springframework.data.rest.webmvc.json.DomainObjectReader.MappedProperties; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty;