Browse Source

DATACMNS-76 - Adapt changes of Spring Data Commons.

pull/1/head
Oliver Gierke 14 years ago
parent
commit
6b40a27c92
  1. 16
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java
  2. 98
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ConfigurableTypeMapper.java
  3. 122
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultMongoTypeMapper.java
  4. 147
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultTypeMapper.java
  5. 86
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java
  6. 23
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java
  7. 40
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoReader.java
  8. 30
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoTypeMapper.java
  9. 12
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoWriter.java
  10. 6
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/TypeKeyAware.java
  11. 60
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/TypeMapper.java
  12. 18
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessor.java
  13. 109
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/ConfigurableTypeMapperUnitTests.java
  14. 124
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultMongoTypeMapperUnitTests.java
  15. 40
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultTypeMapperUnitTests.java
  16. 12
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java
  17. 6
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java

16
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java

@ -1,7 +1,9 @@
/* /*
* Copyright 2010-2011 the original author or authors. * Copyright 2010-2011 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under t
import org.springframework.data.convert.EntityReader;
he Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
@ -58,13 +60,13 @@ import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.authentication.UserCredentials; import org.springframework.data.authentication.UserCredentials;
import org.springframework.data.convert.EntityReader;
import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.model.BeanWrapper; import org.springframework.data.mapping.model.BeanWrapper;
import org.springframework.data.mapping.model.MappingException; import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.core.convert.MongoReader;
import org.springframework.data.mongodb.core.convert.MongoWriter; import org.springframework.data.mongodb.core.convert.MongoWriter;
import org.springframework.data.mongodb.core.geo.Distance; import org.springframework.data.mongodb.core.geo.Distance;
import org.springframework.data.mongodb.core.geo.GeoResult; import org.springframework.data.mongodb.core.geo.GeoResult;
@ -1029,7 +1031,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
* @return the List of converted objects. * @return the List of converted objects.
*/ */
protected <T> T doFindOne(String collectionName, DBObject query, DBObject fields, Class<T> entityClass) { protected <T> T doFindOne(String collectionName, DBObject query, DBObject fields, Class<T> entityClass) {
MongoReader<? super T> readerToUse = this.mongoConverter; EntityReader<? super T, DBObject> readerToUse = this.mongoConverter;
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass); MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
DBObject mappedQuery = mapper.getMappedObject(query, entity); DBObject mappedQuery = mapper.getMappedObject(query, entity);
@ -1088,7 +1090,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
LOGGER.debug("find using query: " + query + " fields: " + fields + " for class: " + entityClass LOGGER.debug("find using query: " + query + " fields: " + fields + " for class: " + entityClass
+ " in collection: " + collectionName); + " in collection: " + collectionName);
} }
MongoReader<? super T> readerToUse = this.mongoConverter; EntityReader<? super T, DBObject> readerToUse = this.mongoConverter;
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass); MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
return executeFindMultiInternal(new FindCallback(mapper.getMappedObject(query, entity), fields), null, return executeFindMultiInternal(new FindCallback(mapper.getMappedObject(query, entity), fields), null,
new ReadDbObjectCallback<T>(readerToUse, entityClass), collectionName); new ReadDbObjectCallback<T>(readerToUse, entityClass), collectionName);
@ -1123,7 +1125,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
*/ */
protected <T> T doFindAndRemove(String collectionName, DBObject query, DBObject fields, DBObject sort, protected <T> T doFindAndRemove(String collectionName, DBObject query, DBObject fields, DBObject sort,
Class<T> entityClass) { Class<T> entityClass) {
MongoReader<? super T> readerToUse = this.mongoConverter; EntityReader<? super T, DBObject> readerToUse = this.mongoConverter;
if (LOGGER.isDebugEnabled()) { if (LOGGER.isDebugEnabled()) {
LOGGER.debug("findAndRemove using query: " + query + " fields: " + fields + " sort: " + sort + " for class: " LOGGER.debug("findAndRemove using query: " + query + " fields: " + fields + " sort: " + sort + " for class: "
+ entityClass + " in collection: " + collectionName); + entityClass + " in collection: " + collectionName);
@ -1472,10 +1474,10 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
*/ */
private class ReadDbObjectCallback<T> implements DbObjectCallback<T> { private class ReadDbObjectCallback<T> implements DbObjectCallback<T> {
private final MongoReader<? super T> reader; private final EntityReader<? super T, DBObject> reader;
private final Class<T> type; private final Class<T> type;
public ReadDbObjectCallback(MongoReader<? super T> reader, Class<T> type) { public ReadDbObjectCallback(EntityReader<? super T, DBObject> reader, Class<T> type) {
Assert.notNull(reader); Assert.notNull(reader);
Assert.notNull(type); Assert.notNull(type);
this.reader = reader; this.reader = reader;

98
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ConfigurableTypeMapper.java

@ -1,98 +0,0 @@
/*
* Copyright 2011 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.mongodb.core.convert;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
/**
* {@link TypeMapper} allowing to configure a {@link Map} containing {@link Class} to {@link String} mappings that will
* be used to map the values found under the configured type key (see {@link DefaultTypeMapper#setTypeKey(String)}. This
* allows declarative type mapping in a Spring config file for example.
*
* @author Oliver Gierke
*/
public class ConfigurableTypeMapper extends DefaultTypeMapper {
private final Map<TypeInformation<?>, String> typeMap;
private boolean handleUnmappedClasses = false;
/**
* Creates a new {@link ConfigurableTypeMapper} for the given type map.
*
* @param sourceTypeMap must not be {@literal null}.
*/
public ConfigurableTypeMapper(Map<? extends Class<?>, String> sourceTypeMap) {
Assert.notNull(sourceTypeMap);
this.typeMap = new HashMap<TypeInformation<?>, String>(sourceTypeMap.size());
for (Entry<? extends Class<?>, String> entry : sourceTypeMap.entrySet()) {
TypeInformation<?> key = ClassTypeInformation.from(entry.getKey());
String value = entry.getValue();
if (typeMap.containsValue(value)) {
throw new IllegalArgumentException(String.format(
"Detected mapping ambiguity! String %s cannot be mapped to more than one type!", value));
}
this.typeMap.put(key, value);
}
}
/**
* Configures whether to try to handle unmapped classes by simply writing the class' name or loading the class as
* specified in the superclass. Defaults to {@literal false}.
*
* @param handleUnmappedClasses the handleUnmappedClasses to set
*/
public void setHandleUnmappedClasses(boolean handleUnmappedClasses) {
this.handleUnmappedClasses = handleUnmappedClasses;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.DefaultTypeMapper#getTypeInformation(java.lang.String)
*/
@Override
protected TypeInformation<?> getTypeInformation(String value) {
for (Entry<TypeInformation<?>, String> entry : typeMap.entrySet()) {
if (entry.getValue().equals(value)) {
return entry.getKey();
}
}
return handleUnmappedClasses ? super.getTypeInformation(value) : null;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.DefaultTypeMapper#getTypeString(org.springframework.data.util.TypeInformation)
*/
@Override
protected String getTypeString(TypeInformation<?> typeInformation) {
String key = typeMap.get(typeInformation);
return key != null ? key : handleUnmappedClasses ? super.getTypeString(typeInformation) : null;
}
}

122
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultMongoTypeMapper.java

@ -0,0 +1,122 @@
/*
* Copyright 2011 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.mongodb.core.convert;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.springframework.data.convert.SimpleTypeInformationMapper;
import org.springframework.data.convert.DefaultTypeMapper;
import org.springframework.data.convert.TypeAliasAccessor;
import org.springframework.data.convert.TypeInformationMapper;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import com.mongodb.BasicDBList;
import com.mongodb.DBObject;
/**
* Default implementation of {@link MongoTypeMapper} allowing configuration of the key to lookup and store type
* information in {@link DBObject}. The key defaults to {@link #DEFAULT_TYPE_KEY}. Actual type-to-{@link String}
* conversion and back is done in {@link #getTypeString(TypeInformation)} or {@link #getTypeInformation(String)}
* respectively.
*
* @author Oliver Gierke
*/
public class DefaultMongoTypeMapper extends DefaultTypeMapper<DBObject> implements MongoTypeMapper {
public static final String DEFAULT_TYPE_KEY = "_class";
@SuppressWarnings("rawtypes")
private static final TypeInformation<List> LIST_TYPE_INFO = ClassTypeInformation.from(List.class);
@SuppressWarnings("rawtypes")
private static final TypeInformation<Map> MAP_TYPE_INFO = ClassTypeInformation.from(Map.class);
private String typeKey = DEFAULT_TYPE_KEY;
public DefaultMongoTypeMapper() {
this(DEFAULT_TYPE_KEY, Arrays.asList(SimpleTypeInformationMapper.INSTANCE));
}
public DefaultMongoTypeMapper(String typeKey) {
super(new DBObjectTypeAliasAccessor(typeKey));
this.typeKey = typeKey;
}
public DefaultMongoTypeMapper(String typeKey, MappingContext<? extends PersistentEntity<?,?>, ?> mappingContext) {
super(new DBObjectTypeAliasAccessor(typeKey), mappingContext, Arrays.asList(SimpleTypeInformationMapper.INSTANCE));
this.typeKey = typeKey;
}
public DefaultMongoTypeMapper(String typeKey, List<? extends TypeInformationMapper> mappers) {
super(new DBObjectTypeAliasAccessor(typeKey), mappers);
this.typeKey = typeKey;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.MongoTypeMapper#isTypeKey(java.lang.String)
*/
public boolean isTypeKey(String key) {
return typeKey == null ? false : typeKey.equals(key);
}
/* (non-Javadoc)
* @see org.springframework.data.convert.DefaultTypeMapper#getFallbackTypeFor(java.lang.Object)
*/
@Override
protected TypeInformation<?> getFallbackTypeFor(DBObject source) {
return source instanceof BasicDBList ? LIST_TYPE_INFO : MAP_TYPE_INFO;
}
/**
*
* @author Oliver Gierke
*/
public static final class DBObjectTypeAliasAccessor implements TypeAliasAccessor<DBObject> {
private final String typeKey;
public DBObjectTypeAliasAccessor(String typeKey) {
this.typeKey = typeKey;
}
/*
* (non-Javadoc)
* @see org.springframework.data.convert.TypeAliasAccessor#readAliasFrom(java.lang.Object)
*/
public Object readAliasFrom(DBObject source) {
if (source instanceof BasicDBList) {
return null;
}
return source.get(typeKey);
}
/*
* (non-Javadoc)
* @see org.springframework.data.convert.TypeAliasAccessor#writeTypeTo(java.lang.Object, java.lang.Object)
*/
public void writeTypeTo(DBObject sink, Object alias) {
if (typeKey != null) {
sink.put(typeKey, alias);
}
}
}
}

147
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultTypeMapper.java

@ -1,147 +0,0 @@
/*
* Copyright 2011 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.mongodb.core.convert;
import java.util.List;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import com.mongodb.BasicDBList;
import com.mongodb.DBObject;
/**
* Default implementation of {@link TypeMapper} allowing configuration of the key to lookup and store type information
* in {@link DBObject}. The key defaults to {@link #DEFAULT_TYPE_KEY}. Actual type-to-{@link String} conversion and back
* is done in {@link #getTypeString(TypeInformation)} or {@link #getTypeInformation(String)} respectively.
*
* @author Oliver Gierke
*/
public class DefaultTypeMapper implements TypeMapper {
public static final String DEFAULT_TYPE_KEY = "_class";
@SuppressWarnings("rawtypes")
private static final TypeInformation<List> LIST_TYPE_INFORMATION = ClassTypeInformation.from(List.class);
private String typeKey = DEFAULT_TYPE_KEY;
/**
* Sets the key to store the type information under. If set to {@literal null} no type information will be stored in
* the document.
*
* @param typeKey the typeKey to set
*/
public void setTypeKey(String typeKey) {
this.typeKey = typeKey;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.TypeMapper#isTypeKey(java.lang.String)
*/
public boolean isTypeKey(String key) {
return typeKey == null ? false : typeKey.equals(key);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.TypeMapper#readType(com.mongodb.DBObject)
*/
public TypeInformation<?> readType(DBObject dbObject) {
if (dbObject instanceof BasicDBList) {
return LIST_TYPE_INFORMATION;
}
if (typeKey == null) {
return null;
}
Object classToBeUsed = dbObject.get(typeKey);
if (classToBeUsed == null) {
return null;
}
return getTypeInformation(classToBeUsed.toString());
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.TypeMapper#writeType(java.lang.Class, com.mongodb.DBObject)
*/
public void writeType(Class<?> type, DBObject dbObject) {
writeType(ClassTypeInformation.from(type), dbObject);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.TypeMapper#writeType(java.lang.Class, com.mongodb.DBObject)
*/
public void writeType(TypeInformation<?> info, DBObject dbObject) {
Assert.notNull(info);
if (typeKey == null) {
return;
}
String string = getTypeString(info);
if (string != null) {
dbObject.put(typeKey, getTypeString(info));
}
}
/**
* Turn the given type information into the String representation that shall be stored inside the {@link DBObject}. If
* the returned String is {@literal null} no type information will be stored. Default implementation simply returns
* the fully-qualified class name.
*
* @param typeInformation must not be {@literal null}.
* @return the String representation to be stored or {@literal null} if no type information shall be stored.
*/
protected String getTypeString(TypeInformation<?> typeInformation) {
return typeInformation.getType().getName();
}
/**
* Returns the {@link TypeInformation} that shall be used when the given {@link String} value is found as type hint.
* The default implementation will simply interpret the given value as fully-qualified class name and try to load the
* class. Will return {@literal null} in case the given {@link String} is empty. Will not be called in case no
* {@link String} was found for the configured type key at all.
*
* @param value the type to load, must not be {@literal null}.
* @return the type to be used for the given {@link String} representation or {@literal null} if nothing found or the
* class cannot be loaded.
*/
protected TypeInformation<?> getTypeInformation(String value) {
if (!StringUtils.hasText(value)) {
return null;
}
try {
return ClassTypeInformation.from(ClassUtils.forName(value, null));
} catch (ClassNotFoundException e) {
return null;
}
}
}

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

@ -29,11 +29,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBObject;
import com.mongodb.DBRef;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.bson.types.ObjectId; import org.bson.types.ObjectId;
@ -44,6 +39,7 @@ import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.core.CollectionFactory; import org.springframework.core.CollectionFactory;
import org.springframework.core.convert.ConversionException; import org.springframework.core.convert.ConversionException;
import org.springframework.core.convert.support.ConversionServiceFactory; import org.springframework.core.convert.support.ConversionServiceFactory;
import org.springframework.data.convert.TypeMapper;
import org.springframework.data.mapping.Association; import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.AssociationHandler; import org.springframework.data.mapping.AssociationHandler;
import org.springframework.data.mapping.PreferredConstructor; import org.springframework.data.mapping.PreferredConstructor;
@ -65,6 +61,12 @@ import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBObject;
import com.mongodb.DBRef;
/** /**
* {@link MongoConverter} that uses a {@link MappingContext} to do sophisticated mapping of domain objects to * {@link MongoConverter} that uses a {@link MappingContext} to do sophisticated mapping of domain objects to
* {@link DBObject}. * {@link DBObject}.
@ -73,7 +75,7 @@ import org.springframework.util.StringUtils;
* @author Jon Brisbin * @author Jon Brisbin
*/ */
public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware, public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware,
TypeMapperProvider { TypeKeyAware {
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
private static final TypeInformation<Map> MAP_TYPE_INFORMATION = ClassTypeInformation.from(Map.class); private static final TypeInformation<Map> MAP_TYPE_INFORMATION = ClassTypeInformation.from(Map.class);
@ -87,7 +89,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
protected final MongoDbFactory mongoDbFactory; protected final MongoDbFactory mongoDbFactory;
protected ApplicationContext applicationContext; protected ApplicationContext applicationContext;
protected boolean useFieldAccessOnly = true; protected boolean useFieldAccessOnly = true;
protected TypeMapper typeMapper = new DefaultTypeMapper(); protected MongoTypeMapper typeMapper;
/** /**
* Creates a new {@link MappingMongoConverter} given the new {@link MongoDbFactory} and {@link MappingContext}. * Creates a new {@link MappingMongoConverter} given the new {@link MongoDbFactory} and {@link MappingContext}.
@ -105,30 +108,32 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
this.mongoDbFactory = mongoDbFactory; this.mongoDbFactory = mongoDbFactory;
this.mappingContext = mappingContext; this.mappingContext = mappingContext;
this.typeMapper = new DefaultMongoTypeMapper(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, mappingContext);
} }
/** /**
* Configures the {@link TypeMapper} to be used to add type information to {@link DBObject}s created by the converter * Configures the {@link MongoTypeMapper} to be used to add type information to {@link DBObject}s created by the
* and how to lookup type information from {@link DBObject}s when reading them. Uses a {@link DefaultTypeMapper} by * converter and how to lookup type information from {@link DBObject}s when reading them. Uses a
* default. Setting this to {@literal null} will reset the {@link TypeMapper} to the default one. * {@link DefaultMongoTypeMapper} by default. Setting this to {@literal null} will reset the {@link TypeMapper} to the
* default one.
* *
* @param typeMapper the typeMapper to set * @param typeMapper the typeMapper to set
*/ */
public void setTypeMapper(TypeMapper typeMapper) { public void setTypeMapper(MongoTypeMapper typeMapper) {
this.typeMapper = typeMapper == null ? new DefaultTypeMapper() : typeMapper; this.typeMapper = typeMapper == null ? new DefaultMongoTypeMapper(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, mappingContext) : typeMapper;
} }
/* /*
* (non-Javadoc) * (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.MongoConverter#getTypeMapper() * @see org.springframework.data.mongodb.core.convert.TypeKeyAware#isTypeKey(java.lang.String)
*/ */
public TypeMapper getTypeMapper() { public boolean isTypeKey(String key) {
return this.typeMapper; return typeMapper.isTypeKey(key);
} }
/* /*
* (non-Javadoc) * (non-Javadoc)
* @see org.springframework.data.mongodb.core.core.convert.MongoConverter#getMappingContext() * @see org.springframework.data.convert.EntityConverter#getMappingContext()
*/ */
public MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> getMappingContext() { public MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> getMappingContext() {
return mappingContext; return mappingContext;
@ -168,7 +173,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
return null; return null;
} }
TypeInformation<? extends S> typeToUse = getMoreConcreteTargetType(dbo, type); TypeInformation<? extends S> typeToUse = typeMapper.readType(dbo, type);
Class<? extends S> rawType = typeToUse.getType(); Class<? extends S> rawType = typeToUse.getType();
if (conversions.hasCustomReadTarget(dbo.getClass(), rawType)) { if (conversions.hasCustomReadTarget(dbo.getClass(), rawType)) {
@ -733,7 +738,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
(BasicDBList) sourceValue); (BasicDBList) sourceValue);
} }
TypeInformation<?> toType = findTypeToBeUsed((DBObject) sourceValue); TypeInformation<?> toType = typeMapper.readType((DBObject) sourceValue);
// It's a complex object, have to read it in // It's a complex object, have to read it in
if (toType != null) { if (toType != null) {
@ -791,7 +796,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
Assert.notNull(dbObject); Assert.notNull(dbObject);
Class<?> mapType = getMoreConcreteTargetType(dbObject, type).getType(); Class<?> mapType = typeMapper.readType(dbObject, type).getType();
Map<Object, Object> map = CollectionFactory.createMap(mapType, dbObject.keySet().size()); Map<Object, Object> map = CollectionFactory.createMap(mapType, dbObject.keySet().size());
Map<String, Object> sourceMap = dbObject.toMap(); Map<String, Object> sourceMap = dbObject.toMap();
@ -822,49 +827,6 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
return map; return map;
} }
/**
* Returns the type to be used to convert the DBObject given to. Will return {@literal null} if there's not type hint
* found in the {@link DBObject} or the type hint found can't be converted into a {@link Class} as the type might not
* be available.
*
* @param dbObject
* @return the type to be used for converting the given {@link DBObject} into or {@literal null} if there's no type
* found.
*/
protected TypeInformation<?> findTypeToBeUsed(DBObject dbObject) {
return typeMapper.readType(dbObject);
}
private Class<?> getDefaultedTypeToBeUsed(DBObject dbObject) {
TypeInformation<?> result = findTypeToBeUsed(dbObject);
if (result != null) {
return result.getType();
}
return dbObject instanceof BasicDBList ? List.class : Map.class;
}
/**
* Inspects the a custom class definition stored inside the given {@link DBObject} and returns that in case it's a
* subtype of the given basic one.
*
* @param dbObject
* @param basicType
* @return
*/
@SuppressWarnings("unchecked")
private <S> TypeInformation<? extends S> getMoreConcreteTargetType(DBObject dbObject, TypeInformation<S> basicType) {
Class<?> documentsTargetType = getDefaultedTypeToBeUsed(dbObject);
Class<S> rawType = basicType == null ? null : basicType.getType();
boolean isMoreConcreteCustomType = rawType == null ? true : rawType.isAssignableFrom(documentsTargetType)
&& !rawType.equals(documentsTargetType);
return isMoreConcreteCustomType ? (TypeInformation<? extends S>) ClassTypeInformation.from(documentsTargetType)
: basicType;
}
protected <T> List<?> unwrapList(BasicDBList dbList, TypeInformation<T> targetType) { protected <T> List<?> unwrapList(BasicDBList dbList, TypeInformation<T> targetType) {
List<Object> rootList = new ArrayList<Object>(); List<Object> rootList = new ArrayList<Object>();
for (int i = 0; i < dbList.size(); i++) { for (int i = 0; i < dbList.size(); i++) {

23
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java

@ -15,29 +15,20 @@
*/ */
package org.springframework.data.mongodb.core.convert; package org.springframework.data.mongodb.core.convert;
import org.springframework.core.convert.ConversionService; import org.springframework.data.convert.EntityConverter;
import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.convert.EntityReader;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import com.mongodb.DBObject;
/** /**
* Central Mongo specific converter interface which combines {@link MongoWriter} and {@link MongoReader}. * Central Mongo specific converter interface which combines {@link MongoWriter} and {@link MongoReader}.
* *
* @author Oliver Gierke * @author Oliver Gierke
*/ */
public interface MongoConverter extends MongoWriter<Object>, MongoReader<Object> { public interface MongoConverter extends
EntityConverter<MongoPersistentEntity<?>, MongoPersistentProperty, Object, DBObject>, MongoWriter<Object>,
/** EntityReader<Object, DBObject> {
* Returns the underlying {@link MappingContext} used by the converter.
*
* @return never {@literal null}
*/
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> getMappingContext();
/**
* Returns the underlying {@link ConversionService} used by the converter.
*
* @return never {@literal null}.
*/
ConversionService getConversionService();
} }

40
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoReader.java

@ -1,40 +0,0 @@
/*
* Copyright 2010-2011 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.mongodb.core.convert;
import com.mongodb.DBObject;
/**
* A MongoWriter is responsible for converting a native MongoDB DBObject to an object of type T.
*
* @param <T> the type of the object to convert from a DBObject
* @author Mark Pollack
* @author Thomas Risberg
* @author Oliver Gierke
*/
public interface MongoReader<T> {
/**
* Ready from the native MongoDB DBObject representation to an instance of the class T. The given type has to be the
* starting point for marshalling the {@link DBObject} into it. So in case there's no real valid data inside
* {@link DBObject} for the given type, just return an empty instance of the given type.
*
* @param clazz the type of the return value. Will never be {@literal null}.
* @param dbo the {@link DBObject} to convert into a domain object. Might be {@literal null}.
* @return the converted object. Might be {@literal null}.
*/
<S extends T> S read(Class<S> clazz, DBObject dbo);
}

30
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoTypeMapper.java

@ -0,0 +1,30 @@
/*
* Copyright 2011 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.mongodb.core.convert;
import org.springframework.data.convert.TypeMapper;
import com.mongodb.DBObject;
/**
* Combining interface to express Mongo specific {@link TypeMapper} implementations will be {@link TypeKeyAware} as
* well.
*
* @author Oliver Gierke
*/
public interface MongoTypeMapper extends TypeMapper<DBObject>, TypeKeyAware {
}

12
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoWriter.java

@ -15,6 +15,8 @@
*/ */
package org.springframework.data.mongodb.core.convert; package org.springframework.data.mongodb.core.convert;
import org.springframework.data.convert.EntityWriter;
import com.mongodb.DBObject; import com.mongodb.DBObject;
/** /**
@ -25,15 +27,7 @@ import com.mongodb.DBObject;
* @author Thomas Risberg * @author Thomas Risberg
* @author Oliver Gierke * @author Oliver Gierke
*/ */
public interface MongoWriter<T> { public interface MongoWriter<T> extends EntityWriter<T, DBObject> {
/**
* Write the given object of type T to the native MongoDB object representation DBObject.
*
* @param t The object to convert to a DBObject
* @param dbo The DBObject to use for writing.
*/
void write(T t, DBObject dbo);
/** /**
* Converts the given object into one Mongo will be able to store natively. If the given object can already be stored * Converts the given object into one Mongo will be able to store natively. If the given object can already be stored

6
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/TypeMapperProvider.java → spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/TypeKeyAware.java

@ -15,17 +15,19 @@
*/ */
package org.springframework.data.mongodb.core.convert; package org.springframework.data.mongodb.core.convert;
import org.springframework.data.convert.TypeMapper;
/** /**
* Interfaces for components being able to provide a {@link TypeMapper}. * Interfaces for components being able to provide a {@link TypeMapper}.
* *
* @author Oliver Gierke * @author Oliver Gierke
*/ */
public interface TypeMapperProvider { public interface TypeKeyAware {
/** /**
* Returns the {@link TypeMapper}. * Returns the {@link TypeMapper}.
* *
* @return the {@link TypeMapper} or {@literal null} if none available. * @return the {@link TypeMapper} or {@literal null} if none available.
*/ */
TypeMapper getTypeMapper(); boolean isTypeKey(String key);
} }

60
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/TypeMapper.java

@ -1,60 +0,0 @@
/*
* Copyright 2011 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.mongodb.core.convert;
import org.springframework.data.util.TypeInformation;
import com.mongodb.DBObject;
/**
* Interface to define strategies how to store type information in a {@link DBObject}.
*
* @author Oliver Gierke
*/
public interface TypeMapper {
/**
* Returns whether the given key is the key being used as type key.
*
* @param key
* @return
*/
boolean isTypeKey(String key);
/**
* Reads the {@link TypeInformation} from the given {@link DBObject}.
*
* @param dbObject must not be {@literal null}.
* @return
*/
TypeInformation<?> readType(DBObject dbObject);
/**
* Writes type information for the given type into the given {@link DBObject}.
*
* @param type must not be {@literal null}.
* @param dbObject must not be {@literal null}.
*/
void writeType(Class<?> type, DBObject dbObject);
/**
* Writes type information for the given {@link TypeInformation} into the given {@link DBObject}.
*
* @param type must not be {@literal null}.
* @param dbObject must not be {@literal null}.
*/
void writeType(TypeInformation<?> type, DBObject dbObject);
}

18
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessor.java

@ -20,8 +20,7 @@ import java.util.Iterator;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.convert.MongoWriter; import org.springframework.data.mongodb.core.convert.MongoWriter;
import org.springframework.data.mongodb.core.convert.TypeMapper; import org.springframework.data.mongodb.core.convert.TypeKeyAware;
import org.springframework.data.mongodb.core.convert.TypeMapperProvider;
import org.springframework.data.mongodb.core.geo.Distance; import org.springframework.data.mongodb.core.geo.Distance;
import org.springframework.data.mongodb.core.geo.Point; import org.springframework.data.mongodb.core.geo.Point;
import org.springframework.data.repository.query.ParameterAccessor; import org.springframework.data.repository.query.ParameterAccessor;
@ -107,12 +106,11 @@ public class ConvertingParameterAccessor implements MongoParameterAccessor {
*/ */
private Object getConvertedValue(Object value) { private Object getConvertedValue(Object value) {
if (!(writer instanceof TypeMapperProvider)) { if (!(writer instanceof TypeKeyAware)) {
return value; return value;
} }
TypeMapper mapper = ((TypeMapperProvider) writer).getTypeMapper(); return removeTypeInfoRecursively(writer.convertToMongoType(value), ((TypeKeyAware) writer));
return removeTypeInfoRecursively(writer.convertToMongoType(value), mapper);
} }
/** /**
@ -121,9 +119,9 @@ public class ConvertingParameterAccessor implements MongoParameterAccessor {
* @param object * @param object
* @return * @return
*/ */
private Object removeTypeInfoRecursively(Object object, TypeMapper mapper) { private Object removeTypeInfoRecursively(Object object, TypeKeyAware typeKeyAware) {
if (!(object instanceof DBObject) || mapper == null) { if (!(object instanceof DBObject) || typeKeyAware == null) {
return object; return object;
} }
@ -131,17 +129,17 @@ public class ConvertingParameterAccessor implements MongoParameterAccessor {
String keyToRemove = null; String keyToRemove = null;
for (String key : dbObject.keySet()) { for (String key : dbObject.keySet()) {
if (mapper.isTypeKey(key)) { if (typeKeyAware.isTypeKey(key)) {
keyToRemove = key; keyToRemove = key;
} }
Object value = dbObject.get(key); Object value = dbObject.get(key);
if (value instanceof BasicDBList) { if (value instanceof BasicDBList) {
for (Object element : (BasicDBList) value) { for (Object element : (BasicDBList) value) {
removeTypeInfoRecursively(element, mapper); removeTypeInfoRecursively(element, typeKeyAware);
} }
} else { } else {
removeTypeInfoRecursively(value, mapper); removeTypeInfoRecursively(value, typeKeyAware);
} }
} }

109
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/ConfigurableTypeMapperUnitTests.java

@ -1,109 +0,0 @@
/*
* Copyright 2011 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.mongodb.core.convert;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.springframework.data.util.TypeInformation;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* Unit tests for {@link ConfigurableTypeMapper}.
*
* @author Oliver Gierke
*/
public class ConfigurableTypeMapperUnitTests {
ConfigurableTypeMapper mapper;
@Before
public void setUp() {
mapper = new ConfigurableTypeMapper(Collections.singletonMap(String.class, "1"));
}
@Test(expected = IllegalArgumentException.class)
public void rejectsNullTypeMap() {
new ConfigurableTypeMapper(null);
}
@Test(expected = IllegalArgumentException.class)
public void rejectsNonBijectionalMap() {
Map<Class<?>, String> map = new HashMap<Class<?>, String>();
map.put(String.class, "1");
map.put(Object.class, "1");
new ConfigurableTypeMapper(map);
}
@Test
public void writesMapKeyForType() {
writesTypeToField(new BasicDBObject(), String.class, "1");
writesTypeToField(new BasicDBObject(), Object.class, null);
}
@Test
public void writesClassNamesForUnmappedValuesIfConfigured() {
mapper.setHandleUnmappedClasses(true);
writesTypeToField(new BasicDBObject(), String.class, "1");
writesTypeToField(new BasicDBObject(), Object.class, Object.class.getName());
}
@Test
public void readsTypeForMapKey() {
readsTypeFromField(new BasicDBObject(DefaultTypeMapper.DEFAULT_TYPE_KEY, "1"), String.class);
readsTypeFromField(new BasicDBObject(DefaultTypeMapper.DEFAULT_TYPE_KEY, "unmapped"), null);
}
@Test
public void readsTypeLoadingClassesForUnmappedTypesIfConfigured() {
mapper.setHandleUnmappedClasses(true);
readsTypeFromField(new BasicDBObject(DefaultTypeMapper.DEFAULT_TYPE_KEY, "1"), String.class);
readsTypeFromField(new BasicDBObject(DefaultTypeMapper.DEFAULT_TYPE_KEY, Object.class.getName()), Object.class);
}
private void readsTypeFromField(DBObject dbObject, Class<?> type) {
TypeInformation<?> typeInfo = mapper.readType(dbObject);
if (type != null) {
assertThat(typeInfo, is(notNullValue()));
assertThat(typeInfo.getType(), is(typeCompatibleWith(type)));
} else {
assertThat(typeInfo, is(nullValue()));
}
}
private void writesTypeToField(DBObject dbObject, Class<?> type, Object value) {
mapper.writeType(type, dbObject);
if (value == null) {
assertThat(dbObject.keySet().isEmpty(), is(true));
} else {
assertThat(dbObject.containsField(DefaultTypeMapper.DEFAULT_TYPE_KEY), is(true));
assertThat(dbObject.get(DefaultTypeMapper.DEFAULT_TYPE_KEY), is(value));
}
}
}

124
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultMongoTypeMapperUnitTests.java

@ -0,0 +1,124 @@
/*
* Copyright 2011 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.mongodb.core.convert;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
import org.springframework.data.convert.SimpleTypeInformationMapper;
import org.springframework.data.convert.ConfigurableTypeInformationMapper;
import org.springframework.data.util.TypeInformation;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* Unit tests for {@link ConfigurableTypeMapper}.
*
* @author Oliver Gierke
*/
public class DefaultMongoTypeMapperUnitTests {
ConfigurableTypeInformationMapper configurableTypeInformationMapper;
SimpleTypeInformationMapper simpleTypeInformationMapper;
DefaultMongoTypeMapper typeMapper;
@Before
public void setUp() {
configurableTypeInformationMapper = new ConfigurableTypeInformationMapper(Collections.singletonMap(String.class, "1"));
simpleTypeInformationMapper = SimpleTypeInformationMapper.INSTANCE;
typeMapper = new DefaultMongoTypeMapper(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, Arrays.asList(
configurableTypeInformationMapper));
}
@Test
public void defaultInstanceWritesClasses() {
typeMapper = new DefaultMongoTypeMapper();
writesTypeToField(new BasicDBObject(), String.class, String.class.getName());
}
@Test
public void defaultInstanceReadsClasses() {
typeMapper = new DefaultMongoTypeMapper();
DBObject dbObject = new BasicDBObject(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, String.class.getName());
readsTypeFromField(dbObject, String.class);
}
@Test
public void writesMapKeyForType() {
writesTypeToField(new BasicDBObject(), String.class, "1");
writesTypeToField(new BasicDBObject(), Object.class, null);
}
@Test
public void writesClassNamesForUnmappedValuesIfConfigured() {
typeMapper = new DefaultMongoTypeMapper(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, Arrays.asList(
configurableTypeInformationMapper, simpleTypeInformationMapper));
writesTypeToField(new BasicDBObject(), String.class, "1");
writesTypeToField(new BasicDBObject(), Object.class, Object.class.getName());
}
@Test
public void readsTypeForMapKey() {
readsTypeFromField(new BasicDBObject(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, "1"), String.class);
readsTypeFromField(new BasicDBObject(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, "unmapped"), null);
}
@Test
public void readsTypeLoadingClassesForUnmappedTypesIfConfigured() {
typeMapper = new DefaultMongoTypeMapper(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, Arrays.asList(
configurableTypeInformationMapper, simpleTypeInformationMapper));
readsTypeFromField(new BasicDBObject(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, "1"), String.class);
readsTypeFromField(new BasicDBObject(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, Object.class.getName()), Object.class);
}
private void readsTypeFromField(DBObject dbObject, Class<?> type) {
TypeInformation<?> typeInfo = typeMapper.readType(dbObject);
if (type != null) {
assertThat(typeInfo, is(notNullValue()));
assertThat(typeInfo.getType(), is(typeCompatibleWith(type)));
} else {
assertThat(typeInfo, is(nullValue()));
}
}
private void writesTypeToField(DBObject dbObject, Class<?> type, Object value) {
typeMapper.writeType(type, dbObject);
if (value == null) {
assertThat(dbObject.keySet().isEmpty(), is(true));
} else {
assertThat(dbObject.containsField(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY), is(true));
assertThat(dbObject.get(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY), is(value));
}
}
}

40
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultTypeMapperUnitTests.java

@ -15,10 +15,8 @@
*/ */
package org.springframework.data.mongodb.core.convert; package org.springframework.data.mongodb.core.convert;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.util.List;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -29,81 +27,81 @@ import com.mongodb.BasicDBObject;
import com.mongodb.DBObject; import com.mongodb.DBObject;
/** /**
* Unit tests for {@link DefaultTypeMapper}. * Unit tests for {@link DefaultMongoTypeMapper}.
* *
* @author Oliver Gierke * @author Oliver Gierke
*/ */
public class DefaultTypeMapperUnitTests { public class DefaultTypeMapperUnitTests {
DefaultTypeMapper mapper; DefaultMongoTypeMapper mapper;
@Before @Before
public void setUp() { public void setUp() {
mapper = new DefaultTypeMapper(); mapper = new DefaultMongoTypeMapper();
} }
@Test @Test
public void addsFullyQualifiedClassNameUnderDefaultKeyByDefault() { public void addsFullyQualifiedClassNameUnderDefaultKeyByDefault() {
writesTypeToField(DefaultTypeMapper.DEFAULT_TYPE_KEY, new BasicDBObject(), String.class); writesTypeToField(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, new BasicDBObject(), String.class);
} }
@Test @Test
public void writesTypeToCustomFieldIfConfigured() { public void writesTypeToCustomFieldIfConfigured() {
mapper.setTypeKey("_custom"); mapper = new DefaultMongoTypeMapper("_custom");
writesTypeToField("_custom", new BasicDBObject(), String.class); writesTypeToField("_custom", new BasicDBObject(), String.class);
} }
@Test @Test
public void doesNotWriteTypeInformationInCaseKeyIsSetToNull() { public void doesNotWriteTypeInformationInCaseKeyIsSetToNull() {
mapper.setTypeKey(null); mapper = new DefaultMongoTypeMapper(null);
writesTypeToField(null, new BasicDBObject(), String.class); writesTypeToField(null, new BasicDBObject(), String.class);
} }
@Test @Test
public void readsTypeFromDefaultKeyByDefault() { public void readsTypeFromDefaultKeyByDefault() {
readsTypeFromField(new BasicDBObject(DefaultTypeMapper.DEFAULT_TYPE_KEY, String.class.getName()), String.class); readsTypeFromField(new BasicDBObject(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, String.class.getName()), String.class);
} }
@Test @Test
public void readsTypeFromCustomFieldConfigured() { public void readsTypeFromCustomFieldConfigured() {
mapper.setTypeKey("_custom"); mapper = new DefaultMongoTypeMapper("_custom");
readsTypeFromField(new BasicDBObject("_custom", String.class.getName()), String.class); readsTypeFromField(new BasicDBObject("_custom", String.class.getName()), String.class);
} }
@Test @Test
public void returnsListForBasicDBLists() { public void returnsListForBasicDBLists() {
readsTypeFromField(new BasicDBList(), List.class); readsTypeFromField(new BasicDBList(), null);
} }
@Test @Test
public void returnsNullIfNoTypeInfoInDBObject() { public void returnsNullIfNoTypeInfoInDBObject() {
readsTypeFromField(new BasicDBObject(), null); readsTypeFromField(new BasicDBObject(), null);
readsTypeFromField(new BasicDBObject(DefaultTypeMapper.DEFAULT_TYPE_KEY, ""), null); readsTypeFromField(new BasicDBObject(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, ""), null);
} }
@Test @Test
public void returnsNullIfClassCannotBeLoaded() { public void returnsNullIfClassCannotBeLoaded() {
readsTypeFromField(new BasicDBObject(DefaultTypeMapper.DEFAULT_TYPE_KEY, "fooBar"), null); readsTypeFromField(new BasicDBObject(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, "fooBar"), null);
} }
@Test @Test
public void returnsNullIfTypeKeySetToNull() { public void returnsNullIfTypeKeySetToNull() {
mapper.setTypeKey(null); mapper = new DefaultMongoTypeMapper(null);
readsTypeFromField(new BasicDBObject(DefaultTypeMapper.DEFAULT_TYPE_KEY, String.class), null); readsTypeFromField(new BasicDBObject(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, String.class), null);
} }
@Test @Test
public void returnsCorrectTypeKey() { public void returnsCorrectTypeKey() {
assertThat(mapper.isTypeKey(DefaultTypeMapper.DEFAULT_TYPE_KEY), is(true)); assertThat(mapper.isTypeKey(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY), is(true));
mapper.setTypeKey("_custom"); mapper = new DefaultMongoTypeMapper("_custom");
assertThat(mapper.isTypeKey("_custom"), is(true)); assertThat(mapper.isTypeKey("_custom"), is(true));
assertThat(mapper.isTypeKey(DefaultTypeMapper.DEFAULT_TYPE_KEY), is(false)); assertThat(mapper.isTypeKey(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY), is(false));
mapper.setTypeKey(null); mapper = new DefaultMongoTypeMapper(null);
assertThat(mapper.isTypeKey("_custom"), is(false)); assertThat(mapper.isTypeKey("_custom"), is(false));
assertThat(mapper.isTypeKey(DefaultTypeMapper.DEFAULT_TYPE_KEY), is(false)); assertThat(mapper.isTypeKey(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY), is(false));
} }
private void readsTypeFromField(DBObject dbObject, Class<?> type) { private void readsTypeFromField(DBObject dbObject, Class<?> type) {

12
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java

@ -153,7 +153,7 @@ public class MappingMongoConverterUnitTests {
DBObject dbObject = new BasicDBObject(); DBObject dbObject = new BasicDBObject();
dbObject.put("birthDate", new LocalDate()); dbObject.put("birthDate", new LocalDate());
dbObject.put(DefaultTypeMapper.DEFAULT_TYPE_KEY, Person.class.getName()); dbObject.put(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, Person.class.getName());
assertThat(converter.read(Contact.class, dbObject), is(Person.class)); assertThat(converter.read(Contact.class, dbObject), is(Person.class));
} }
@ -166,7 +166,7 @@ public class MappingMongoConverterUnitTests {
DBObject dbObject = new BasicDBObject(); DBObject dbObject = new BasicDBObject();
dbObject.put("birthDate", new LocalDate()); dbObject.put("birthDate", new LocalDate());
dbObject.put(DefaultTypeMapper.DEFAULT_TYPE_KEY, Person.class.getName()); dbObject.put(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, Person.class.getName());
assertThat(converter.read(BirthDateContainer.class, dbObject), is(BirthDateContainer.class)); assertThat(converter.read(BirthDateContainer.class, dbObject), is(BirthDateContainer.class));
} }
@ -180,8 +180,8 @@ public class MappingMongoConverterUnitTests {
DBObject result = new BasicDBObject(); DBObject result = new BasicDBObject();
converter.write(person, result); converter.write(person, result);
assertThat(result.containsField(DefaultTypeMapper.DEFAULT_TYPE_KEY), is(true)); assertThat(result.containsField(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY), is(true));
assertThat(result.get(DefaultTypeMapper.DEFAULT_TYPE_KEY).toString(), is(Person.class.getName())); assertThat(result.get(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY).toString(), is(Person.class.getName()));
} }
/** /**
@ -295,7 +295,7 @@ public class MappingMongoConverterUnitTests {
BasicDBList contacts = (BasicDBList) result; BasicDBList contacts = (BasicDBList) result;
DBObject personDbObject = (DBObject) contacts.get(0); DBObject personDbObject = (DBObject) contacts.get(0);
assertThat(personDbObject.get("foo").toString(), is("Oliver")); assertThat(personDbObject.get("foo").toString(), is("Oliver"));
assertThat((String) personDbObject.get(DefaultTypeMapper.DEFAULT_TYPE_KEY), is(Person.class.getName())); assertThat((String) personDbObject.get(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY), is(Person.class.getName()));
} }
/** /**
@ -304,7 +304,7 @@ public class MappingMongoConverterUnitTests {
@Test @Test
public void readsCollectionWithInterfaceCorrectly() { public void readsCollectionWithInterfaceCorrectly() {
BasicDBObject person = new BasicDBObject(DefaultTypeMapper.DEFAULT_TYPE_KEY, Person.class.getName()); BasicDBObject person = new BasicDBObject(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, Person.class.getName());
person.put("foo", "Oliver"); person.put("foo", "Oliver");
BasicDBList contacts = new BasicDBList(); BasicDBList contacts = new BasicDBList();

6
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java

@ -28,7 +28,7 @@ import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner; import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.convert.DefaultTypeMapper; import org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
@ -95,7 +95,7 @@ public class StringBasedMongoQueryUnitTests {
DBObject dbObject = new BasicDBObject(); DBObject dbObject = new BasicDBObject();
converter.write(address, dbObject); converter.write(address, dbObject);
dbObject.removeField(DefaultTypeMapper.DEFAULT_TYPE_KEY); dbObject.removeField(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY);
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor); org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor);
BasicDBObject queryObject = new BasicDBObject("address", dbObject); BasicDBObject queryObject = new BasicDBObject("address", dbObject);
@ -116,7 +116,7 @@ public class StringBasedMongoQueryUnitTests {
DBObject addressDbObject = new BasicDBObject(); DBObject addressDbObject = new BasicDBObject();
converter.write(address, addressDbObject); converter.write(address, addressDbObject);
addressDbObject.removeField(DefaultTypeMapper.DEFAULT_TYPE_KEY); addressDbObject.removeField(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY);
DBObject reference = new BasicDBObject("address", addressDbObject); DBObject reference = new BasicDBObject("address", addressDbObject);
reference.put("lastname", "Matthews"); reference.put("lastname", "Matthews");

Loading…
Cancel
Save