Browse Source

DATAMONGO-1210 - Polishing.

Moved getTypeHint(…) method to Field class.

Original pull request: #292.
pull/299/merge
Oliver Gierke 11 years ago
parent
commit
ea5bd5f7d3
  1. 93
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java
  2. 37
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java
  3. 28
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java
  4. 26
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java

93
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java

@ -136,8 +136,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App @@ -136,8 +136,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
* @param typeMapper the typeMapper to set
*/
public void setTypeMapper(MongoTypeMapper typeMapper) {
this.typeMapper = typeMapper == null ? new DefaultMongoTypeMapper(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY,
mappingContext) : typeMapper;
this.typeMapper = typeMapper == null
? new DefaultMongoTypeMapper(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, mappingContext) : typeMapper;
}
/*
@ -238,7 +238,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App @@ -238,7 +238,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
PersistentEntityParameterValueProvider<MongoPersistentProperty> parameterProvider = new PersistentEntityParameterValueProvider<MongoPersistentProperty>(
entity, provider, path.getCurrentObject());
return new ConverterAwareSpELExpressionParameterValueProvider(evaluator, conversionService, parameterProvider, path);
return new ConverterAwareSpELExpressionParameterValueProvider(evaluator, conversionService, parameterProvider,
path);
}
private <S extends Object> S read(final MongoPersistentEntity<S> entity, final DBObject dbo, final ObjectPath path) {
@ -510,8 +511,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App @@ -510,8 +511,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
: new BasicDBObject();
addCustomTypeKeyIfNecessary(ClassTypeInformation.from(prop.getRawType()), obj, propDbObj);
MongoPersistentEntity<?> entity = isSubtype(prop.getType(), obj.getClass()) ? mappingContext
.getPersistentEntity(obj.getClass()) : mappingContext.getPersistentEntity(type);
MongoPersistentEntity<?> entity = isSubtype(prop.getType(), obj.getClass())
? mappingContext.getPersistentEntity(obj.getClass()) : mappingContext.getPersistentEntity(type);
writeInternal(obj, propDbObj, entity);
accessor.put(prop, propDbObj);
@ -700,8 +701,10 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App @@ -700,8 +701,10 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
if (mapKeyDotReplacement == null) {
throw new MappingException(String.format("Map key %s contains dots but no replacement was configured! Make "
+ "sure map keys don't contain dots in the first place or configure an appropriate replacement!", source));
throw new MappingException(String.format(
"Map key %s contains dots but no replacement was configured! Make "
+ "sure map keys don't contain dots in the first place or configure an appropriate replacement!",
source));
}
return source.replaceAll("\\.", mapKeyDotReplacement);
@ -719,8 +722,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App @@ -719,8 +722,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
return (String) key;
}
return conversions.hasCustomWriteTarget(key.getClass(), String.class) ? (String) getPotentiallyConvertedSimpleWrite(key)
: key.toString();
return conversions.hasCustomWriteTarget(key.getClass(), String.class)
? (String) getPotentiallyConvertedSimpleWrite(key) : key.toString();
}
/**
@ -889,16 +892,16 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App @@ -889,16 +892,16 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
Class<?> rawComponentType = componentType == null ? null : componentType.getType();
collectionType = Collection.class.isAssignableFrom(collectionType) ? collectionType : List.class;
Collection<Object> items = targetType.getType().isArray() ? new ArrayList<Object>() : CollectionFactory
.createCollection(collectionType, rawComponentType, sourceValue.size());
Collection<Object> items = targetType.getType().isArray() ? new ArrayList<Object>()
: CollectionFactory.createCollection(collectionType, rawComponentType, sourceValue.size());
for (int i = 0; i < sourceValue.size(); i++) {
Object dbObjItem = sourceValue.get(i);
if (dbObjItem instanceof DBRef) {
items.add(DBRef.class.equals(rawComponentType) ? dbObjItem : read(componentType, readRef((DBRef) dbObjItem),
path));
items.add(
DBRef.class.equals(rawComponentType) ? dbObjItem : read(componentType, readRef((DBRef) dbObjItem), path));
} else if (dbObjItem instanceof DBObject) {
items.add(read(componentType, (DBObject) dbObjItem, path));
} else {
@ -1016,14 +1019,14 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App @@ -1016,14 +1019,14 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
this.write(obj, newDbo);
if (typeInformation == null) {
return removeTypeInfoRecursively(newDbo);
return removeTypeInfo(newDbo, true);
}
if (typeInformation.getType().equals(NestedDocument.class)) {
return removeTypeInfo(newDbo);
return removeTypeInfo(newDbo, false);
}
return !obj.getClass().equals(typeInformation.getType()) ? newDbo : removeTypeInfoRecursively(newDbo);
return !obj.getClass().equals(typeInformation.getType()) ? newDbo : removeTypeInfo(newDbo, true);
}
public BasicDBList maybeConvertList(Iterable<?> source, TypeInformation<?> typeInformation) {
@ -1037,12 +1040,13 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App @@ -1037,12 +1040,13 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
/**
* Removes only the type information from the root document.
* Removes the type information from the entire conversion result.
*
* @param object
* @param recursively whether to apply the removal recursively
* @return
*/
private Object removeTypeInfo(Object object) {
private Object removeTypeInfo(Object object, boolean recursively) {
if (!(object instanceof DBObject)) {
return object;
@ -1050,47 +1054,29 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App @@ -1050,47 +1054,29 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
DBObject dbObject = (DBObject) object;
String keyToRemove = null;
for (String key : dbObject.keySet()) {
if (typeMapper.isTypeKey(key)) {
keyToRemove = key;
}
}
if (recursively) {
if (keyToRemove != null) {
dbObject.removeField(keyToRemove);
}
Object value = dbObject.get(key);
return dbObject;
}
/**
* Removes the type information from the entire conversion result.
*
* @param object
* @return
*/
private Object removeTypeInfoRecursively(Object object) {
if (!(object instanceof DBObject)) {
return object;
}
DBObject dbObject = (DBObject) object;
String keyToRemove = null;
for (String key : dbObject.keySet()) {
if (value instanceof BasicDBList) {
for (Object element : (BasicDBList) value) {
removeTypeInfo(element, recursively);
}
} else {
removeTypeInfo(value, recursively);
}
}
if (typeMapper.isTypeKey(key)) {
keyToRemove = key;
}
Object value = dbObject.get(key);
if (value instanceof BasicDBList) {
for (Object element : (BasicDBList) value) {
removeTypeInfoRecursively(element);
if (!recursively) {
break;
}
} else {
removeTypeInfoRecursively(value);
}
}
@ -1154,8 +1140,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App @@ -1154,8 +1140,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
*
* @author Oliver Gierke
*/
private class ConverterAwareSpELExpressionParameterValueProvider extends
SpELExpressionParameterValueProvider<MongoPersistentProperty> {
private class ConverterAwareSpELExpressionParameterValueProvider
extends SpELExpressionParameterValueProvider<MongoPersistentProperty> {
private final ObjectPath path;
@ -1167,7 +1153,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App @@ -1167,7 +1153,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
* @param delegate must not be {@literal null}.
*/
public ConverterAwareSpELExpressionParameterValueProvider(SpELExpressionEvaluator evaluator,
ConversionService conversionService, ParameterValueProvider<MongoPersistentProperty> delegate, ObjectPath path) {
ConversionService conversionService, ParameterValueProvider<MongoPersistentProperty> delegate,
ObjectPath path) {
super(evaluator, conversionService, delegate);
this.path = path;

37
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java

@ -34,10 +34,13 @@ import org.springframework.data.mapping.PropertyReferenceException; @@ -34,10 +34,13 @@ import org.springframework.data.mapping.PropertyReferenceException;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.context.PersistentPropertyPath;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter.NestedDocument;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty.PropertyToFieldNameConverter;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import com.mongodb.BasicDBList;
@ -58,6 +61,7 @@ public class QueryMapper { @@ -58,6 +61,7 @@ public class QueryMapper {
private static final List<String> DEFAULT_ID_NAMES = Arrays.asList("id", "_id");
private static final DBObject META_TEXT_SCORE = new BasicDBObject("$meta", "textScore");
static final ClassTypeInformation<?> NESTED_DOCUMENT = ClassTypeInformation.from(NestedDocument.class);
private enum MetaMapping {
FORCE, WHEN_PRESENT, IGNORE;
@ -250,8 +254,8 @@ public class QueryMapper { @@ -250,8 +254,8 @@ public class QueryMapper {
boolean needsAssociationConversion = property.isAssociation() && !keyword.isExists();
Object value = keyword.getValue();
Object convertedValue = needsAssociationConversion ? convertAssociation(value, property) : getMappedValue(
property.with(keyword.getKey()), value);
Object convertedValue = needsAssociationConversion ? convertAssociation(value, property)
: getMappedValue(property.with(keyword.getKey()), value);
return new BasicDBObject(keyword.key, convertedValue);
}
@ -473,8 +477,8 @@ public class QueryMapper { @@ -473,8 +477,8 @@ public class QueryMapper {
}
try {
return conversionService.canConvert(id.getClass(), ObjectId.class) ? conversionService
.convert(id, ObjectId.class) : delegateConvertToMongoType(id, null);
return conversionService.canConvert(id.getClass(), ObjectId.class) ? conversionService.convert(id, ObjectId.class)
: delegateConvertToMongoType(id, null);
} catch (ConversionException o_O) {
return delegateConvertToMongoType(id, null);
}
@ -667,6 +671,10 @@ public class QueryMapper { @@ -667,6 +671,10 @@ public class QueryMapper {
public Association<MongoPersistentProperty> getAssociation() {
return null;
}
public TypeInformation<?> getTypeHint() {
return ClassTypeInformation.OBJECT;
}
}
/**
@ -872,6 +880,27 @@ public class QueryMapper { @@ -872,6 +880,27 @@ public class QueryMapper {
protected Converter<MongoPersistentProperty, String> getAssociationConverter() {
return new AssociationConverter(getAssociation());
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.QueryMapper.Field#getTypeHint()
*/
@Override
public TypeInformation<?> getTypeHint() {
MongoPersistentProperty property = getProperty();
if (property == null) {
return super.getTypeHint();
}
if (property.getActualType().isInterface()
|| java.lang.reflect.Modifier.isAbstract(property.getActualType().getModifiers())) {
return ClassTypeInformation.OBJECT;
}
return NESTED_DOCUMENT;
}
}
/**

28
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java

@ -22,7 +22,6 @@ import java.util.Map.Entry; @@ -22,7 +22,6 @@ import java.util.Map.Entry;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter.NestedDocument;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty.PropertyToFieldNameConverter;
@ -45,7 +44,6 @@ import com.mongodb.DBObject; @@ -45,7 +44,6 @@ import com.mongodb.DBObject;
*/
public class UpdateMapper extends QueryMapper {
private static final ClassTypeInformation<?> NESTED_DOCUMENT = ClassTypeInformation.from(NestedDocument.class);
private final MongoConverter converter;
/**
@ -68,8 +66,8 @@ public class UpdateMapper extends QueryMapper { @@ -68,8 +66,8 @@ public class UpdateMapper extends QueryMapper {
*/
@Override
protected Object delegateConvertToMongoType(Object source, MongoPersistentEntity<?> entity) {
return entity == null ? super.delegateConvertToMongoType(source, null) : converter.convertToMongoType(source,
getTypeHintForEntity(entity));
return entity == null ? super.delegateConvertToMongoType(source, null)
: converter.convertToMongoType(source, getTypeHintForEntity(entity));
}
/*
@ -137,22 +135,10 @@ public class UpdateMapper extends QueryMapper { @@ -137,22 +135,10 @@ public class UpdateMapper extends QueryMapper {
private DBObject getMappedValue(Field field, Modifier modifier) {
Object value = converter.convertToMongoType(modifier.getValue(), getTypeHintForField(field));
return new BasicDBObject(modifier.getKey(), value);
}
private TypeInformation<?> getTypeHintForField(Field field) {
if (field == null || field.getProperty() == null) {
return ClassTypeInformation.OBJECT;
}
TypeInformation<?> typeHint = field == null ? ClassTypeInformation.OBJECT : field.getTypeHint();
if (field.getProperty().getActualType().isInterface()
|| java.lang.reflect.Modifier.isAbstract(field.getProperty().getActualType().getModifiers())) {
return ClassTypeInformation.OBJECT;
}
return NESTED_DOCUMENT;
Object value = converter.convertToMongoType(modifier.getValue(), typeHint);
return new BasicDBObject(modifier.getKey(), value);
}
private TypeInformation<?> getTypeHintForEntity(MongoPersistentEntity<?> entity) {
@ -177,8 +163,8 @@ public class UpdateMapper extends QueryMapper { @@ -177,8 +163,8 @@ public class UpdateMapper extends QueryMapper {
protected Field createPropertyField(MongoPersistentEntity<?> entity, String key,
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
return entity == null ? super.createPropertyField(entity, key, mappingContext) : //
new MetadataBackedUpdateField(entity, key, mappingContext);
return entity == null ? super.createPropertyField(entity, key, mappingContext)
: new MetadataBackedUpdateField(entity, key, mappingContext);
}
/**

26
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java

@ -430,8 +430,8 @@ public class UpdateMapperUnitTests { @@ -430,8 +430,8 @@ public class UpdateMapperUnitTests {
public void rendersNestedDbRefCorrectly() {
Update update = new Update().pull("nested.dbRefAnnotatedList.id", "2");
DBObject mappedObject = mapper
.getMappedObject(update.getUpdateObject(), context.getPersistentEntity(Wrapper.class));
DBObject mappedObject = mapper.getMappedObject(update.getUpdateObject(),
context.getPersistentEntity(Wrapper.class));
DBObject pullClause = getAsDBObject(mappedObject, "$pull");
assertThat(pullClause.containsField("mapped.dbRefAnnotatedList"), is(true));
@ -660,8 +660,7 @@ public class UpdateMapperUnitTests { @@ -660,8 +660,7 @@ public class UpdateMapperUnitTests {
assertThat(mappedUpdate,
isBsonObject().notContaining("$addToSet.listHoldingConcretyTypeWithInterfaceTypeAttribute.$each.[0]._class"));
assertThat(
mappedUpdate,
assertThat(mappedUpdate,
isBsonObject().containing(
"$addToSet.listHoldingConcretyTypeWithInterfaceTypeAttribute.$each.[0].interfaceType._class",
ModelImpl.class.getName()));
@ -681,10 +680,8 @@ public class UpdateMapperUnitTests { @@ -681,10 +680,8 @@ public class UpdateMapperUnitTests {
context.getPersistentEntity(DomainTypeWrappingConcreteyTypeHavingListOfInterfaceTypeAttributes.class));
assertThat(mappedUpdate, isBsonObject().notContaining("$set.concreteTypeWithListAttributeOfInterfaceType._class"));
assertThat(
mappedUpdate,
isBsonObject().containing("$set.concreteTypeWithListAttributeOfInterfaceType.models.[0]._class",
ModelImpl.class.getName()));
assertThat(mappedUpdate, isBsonObject()
.containing("$set.concreteTypeWithListAttributeOfInterfaceType.models.[0]._class", ModelImpl.class.getName()));
}
static class DomainTypeWrappingConcreteyTypeHavingListOfInterfaceTypeAttributes {
@ -735,7 +732,7 @@ public class UpdateMapperUnitTests { @@ -735,7 +732,7 @@ public class UpdateMapperUnitTests {
private @Id String id;
@org.springframework.data.mongodb.core.mapping.DBRef//
@org.springframework.data.mongodb.core.mapping.DBRef //
private InterfaceDocumentDefinitionWithoutId referencedDocument;
public String getId() {
@ -796,10 +793,10 @@ public class UpdateMapperUnitTests { @@ -796,10 +793,10 @@ public class UpdateMapperUnitTests {
String id;
@Field("aliased")//
@Field("aliased") //
List<? extends AbstractChildClass> list;
@Field//
@Field //
List<Model> listOfInterface;
public ParentClass(String id, List<? extends AbstractChildClass> list) {
@ -861,10 +858,10 @@ public class UpdateMapperUnitTests { @@ -861,10 +858,10 @@ public class UpdateMapperUnitTests {
@Id public String id;
@org.springframework.data.mongodb.core.mapping.DBRef//
@org.springframework.data.mongodb.core.mapping.DBRef //
public List<Entity> dbRefAnnotatedList;
@org.springframework.data.mongodb.core.mapping.DBRef//
@org.springframework.data.mongodb.core.mapping.DBRef //
public Entity dbRefProperty;
}
@ -884,13 +881,12 @@ public class UpdateMapperUnitTests { @@ -884,13 +881,12 @@ public class UpdateMapperUnitTests {
}
static class NestedDocument {
String name;
public NestedDocument(String name) {
super();
this.name = name;
}
}
}

Loading…
Cancel
Save