DATACMNS-34 - Adapted refactorings in Spring Data Commons regarding PersistenceConstructor discovery.

This commit is contained in:
Oliver Gierke
2011-05-09 17:09:21 +02:00
parent d5c625dc2a
commit 965f9fd260
20 changed files with 295 additions and 218 deletions

View File

@@ -55,6 +55,7 @@ import org.springframework.data.document.mongodb.convert.MongoConverter;
import org.springframework.data.document.mongodb.convert.SimpleMongoConverter;
import org.springframework.data.document.mongodb.index.IndexDefinition;
import org.springframework.data.document.mongodb.mapping.MongoPersistentEntity;
import org.springframework.data.document.mongodb.mapping.MongoPersistentProperty;
import org.springframework.data.document.mongodb.mapping.event.AfterConvertEvent;
import org.springframework.data.document.mongodb.mapping.event.AfterLoadEvent;
import org.springframework.data.document.mongodb.mapping.event.AfterSaveEvent;
@@ -67,8 +68,6 @@ import org.springframework.data.document.mongodb.query.Update;
import org.springframework.data.mapping.MappingBeanHelper;
import org.springframework.data.mapping.model.MappingContext;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.model.PersistentEntity;
import org.springframework.data.mapping.model.PersistentProperty;
import org.springframework.jca.cci.core.ConnectionCallback;
import org.springframework.util.Assert;
@@ -99,7 +98,7 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
private WriteResultChecking writeResultChecking = WriteResultChecking.NONE;
private final MongoConverter mongoConverter;
private final MappingContext<MongoPersistentEntity<?>> mappingContext;
private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
private final Mongo mongo;
private final MongoExceptionTranslator exceptionTranslator = new MongoExceptionTranslator();
private final QueryMapper mapper;
@@ -140,7 +139,6 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
* @param writeConcern
* @param writeResultChecking
*/
@SuppressWarnings({"unchecked"})
MongoTemplate(Mongo mongo, String databaseName, MongoConverter mongoConverter, WriteConcern writeConcern, WriteResultChecking writeResultChecking) {
Assert.notNull(mongo);
@@ -817,7 +815,7 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
throw new InvalidDataAccessApiUsageException("Query passed in to remove can't be null");
}
final DBObject queryObject = query.getQueryObject();
final PersistentEntity<?> entity = getPersistentEntity(targetClass);
final MongoPersistentEntity<?> entity = getPersistentEntity(targetClass);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("remove using query: " + queryObject + " in collection: " + collectionName);
}
@@ -905,7 +903,7 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
*/
protected <T> T doFindOne(String collectionName, DBObject query, DBObject fields, Class<T> targetClass) {
MongoReader<? super T> readerToUse = this.mongoConverter;
PersistentEntity<?> entity = mappingContext.getPersistentEntity(targetClass);
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(targetClass);
DBObject mappedQuery = mapper.getMappedObject(query, entity);
return execute(new FindOneCallback(mappedQuery, fields),
@@ -933,7 +931,7 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
* @return the List of converted objects.
*/
protected <T> List<T> doFind(String collectionName, DBObject query, DBObject fields, Class<T> targetClass, CursorPreparer preparer) {
PersistentEntity<?> entity = mappingContext.getPersistentEntity(targetClass);
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(targetClass);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("find using query: " + query + " fields: " + fields + " for class: " + targetClass + " in collection: " + collectionName);
}
@@ -960,7 +958,7 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
LOGGER.debug("find using query: " + query + " fields: " + fields + " for class: " + targetClass + " in collection: " + collectionName);
}
MongoReader<? super T> readerToUse = this.mongoConverter;
PersistentEntity<?> entity = mappingContext.getPersistentEntity(targetClass);
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(targetClass);
return executeEach(new FindCallback(mapper.getMappedObject(query, entity), fields),
null,
new ReadDbObjectCallback<T>(readerToUse, targetClass),
@@ -1000,7 +998,7 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("findAndRemove using query: " + query + " fields: " + fields + " sort: " + sort + " for class: " + targetClass + " in collection: " + collectionName);
}
PersistentEntity<?> entity = mappingContext.getPersistentEntity(targetClass);
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(targetClass);
return execute(new FindAndRemoveCallback(mapper.getMappedObject(query, entity), fields, sort),
new ReadDbObjectCallback<T>(readerToUse, targetClass),
collectionName);
@@ -1008,8 +1006,8 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
protected Object getIdValue(Object object) {
PersistentEntity<?> entity = mappingContext.getPersistentEntity(object.getClass());
PersistentProperty idProp = entity.getIdProperty();
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(object.getClass());
MongoPersistentProperty idProp = entity.getIdProperty();
if (idProp == null) {
throw new MappingException("No id property found for object of type " + entity.getType().getName());
@@ -1036,7 +1034,7 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
return;
}
PersistentProperty idProp = getIdPropertyFor(savedObject.getClass());
MongoPersistentProperty idProp = getIdPropertyFor(savedObject.getClass());
if (idProp == null) {
return;
@@ -1133,11 +1131,11 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
}
}
private PersistentEntity<?> getPersistentEntity(Class<?> type) {
private MongoPersistentEntity<?> getPersistentEntity(Class<?> type) {
return type == null ? null : mappingContext.getPersistentEntity(type);
}
private PersistentProperty getIdPropertyFor(Class<?> type) {
private MongoPersistentProperty getIdPropertyFor(Class<?> type) {
return mappingContext.getPersistentEntity(type).getIdProperty();
}

View File

@@ -28,8 +28,11 @@ import org.springframework.data.document.mongodb.MongoTemplate;
import org.springframework.data.document.mongodb.convert.MappingMongoConverter;
import org.springframework.data.document.mongodb.mapping.Document;
import org.springframework.data.document.mongodb.mapping.MongoMappingContext;
import org.springframework.data.document.mongodb.mapping.MongoPersistentEntity;
import org.springframework.data.document.mongodb.mapping.MongoPersistentEntityIndexCreator;
import org.springframework.data.document.mongodb.mapping.MongoPersistentProperty;
import org.springframework.data.mapping.context.MappingContextAwareBeanPostProcessor;
import org.springframework.data.mapping.model.MappingContext;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;

View File

@@ -54,17 +54,17 @@ import org.springframework.core.convert.converter.ConverterFactory;
import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair;
import org.springframework.core.convert.support.ConversionServiceFactory;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.document.mongodb.mapping.BasicMongoPersistentEntity;
import org.springframework.data.document.mongodb.mapping.MongoPersistentEntity;
import org.springframework.data.document.mongodb.mapping.MongoPersistentProperty;
import org.springframework.data.mapping.AssociationHandler;
import org.springframework.data.mapping.MappingBeanHelper;
import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.mapping.model.Association;
import org.springframework.data.mapping.model.MappingContext;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.model.PersistentEntity;
import org.springframework.data.mapping.model.PersistentProperty;
import org.springframework.data.mapping.model.PreferredConstructor;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
@@ -86,7 +86,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
protected final GenericConversionService conversionService = ConversionServiceFactory.createDefaultConversionService();
protected final Set<ConvertiblePair> customTypeMapping = new HashSet<ConvertiblePair>();
protected final MappingContext<BasicMongoPersistentEntity<?>> mappingContext;
protected final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
protected SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
protected ApplicationContext applicationContext;
protected boolean useFieldAccessOnly = true;
@@ -98,7 +98,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
*
* @param mappingContext
*/
public MappingMongoConverter(MappingContext<BasicMongoPersistentEntity<?>> mappingContext) {
public MappingMongoConverter(MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
this.mappingContext = mappingContext;
this.conversionService.removeConvertible(Object.class, String.class);
}
@@ -147,7 +147,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
return null;
}
public MappingContext<BasicMongoPersistentEntity<?>> getMappingContext() {
public MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> getMappingContext() {
return mappingContext;
}
@@ -175,50 +175,55 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
return conversionService.convert(id, ObjectId.class);
}
@SuppressWarnings({"unchecked", "rawtypes"})
public <S extends Object> S read(Class<S> clazz, final DBObject dbo) {
if (null == dbo) {
return null;
}
return read(ClassTypeInformation.from(clazz), dbo);
}
@SuppressWarnings("unchecked")
protected <S extends Object> S read(TypeInformation<S> type, DBObject dbo) {
if (null == dbo) {
return null;
}
Class<?> customTarget = getCustomTarget(clazz, DBObject.class);
Class<S> rawType = type.getType();
Class<?> customTarget = getCustomTarget(rawType, DBObject.class);
if (customTarget != null) {
return conversionService.convert(dbo, clazz);
}
if (customTarget != null) {
return conversionService.convert(dbo, rawType);
}
if ((clazz.isArray()
|| (clazz.isAssignableFrom(Collection.class)
|| clazz.isAssignableFrom(List.class)))
&& dbo instanceof BasicDBList) {
List l = new ArrayList<S>();
BasicDBList dbList = (BasicDBList) dbo;
for (Object o : dbList) {
if (o instanceof DBObject) {
Object newObj = read(clazz.getComponentType(), (DBObject) o);
if (newObj.getClass().isAssignableFrom(clazz.getComponentType())) {
l.add(newObj);
} else {
l.add(conversionService.convert(newObj, clazz.getComponentType()));
}
} else {
l.add(o);
}
}
return conversionService.convert(l, clazz);
}
if (type.isCollectionLike() && dbo instanceof BasicDBList) {
List<Object> l = new ArrayList<Object>();
BasicDBList dbList = (BasicDBList) dbo;
for (Object o : dbList) {
if (o instanceof DBObject) {
Object newObj = read(type.getComponentType(), (DBObject) o);
Class<?> rawComponentType = type.getComponentType().getType();
if (newObj.getClass().isAssignableFrom(rawComponentType)) {
l.add(newObj);
} else {
l.add(conversionService.convert(newObj, rawComponentType));
}
} else {
l.add(o);
}
}
return conversionService.convert(l, rawType);
}
// Retrieve persistent entity info
PersistentEntity<S> persistentEntity = (PersistentEntity<S>) mappingContext.getPersistentEntity(clazz);
if (persistentEntity == null) {
throw new MappingException("No mapping metadata found for " + clazz.getName());
}
// Retrieve persistent entity info
MongoPersistentEntity<S> persistentEntity = (MongoPersistentEntity<S>) mappingContext.getPersistentEntity(type);
if (persistentEntity == null) {
throw new MappingException("No mapping metadata found for " + rawType.getName());
}
return read(persistentEntity, dbo);
return read(persistentEntity, dbo);
}
private <S extends Object> S read(PersistentEntity<S> entity, final DBObject dbo) {
private <S extends Object> S read(final MongoPersistentEntity<S> entity, final DBObject dbo) {
final StandardEvaluationContext spelCtx = new StandardEvaluationContext();
if (null != applicationContext) {
@@ -232,11 +237,15 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
final List<String> ctorParamNames = new ArrayList<String>();
final MongoPersistentProperty idProperty = entity.getIdProperty();
final S instance = constructInstance(entity, new PreferredConstructor.ParameterValueProvider() {
public Object getParameterValue(PreferredConstructor.Parameter parameter) {
@SuppressWarnings("unchecked")
public <T> T getParameterValue(PreferredConstructor.Parameter<T> parameter) {
String name = parameter.getName();
Class<?> type = parameter.getType();
Object obj = dbo.get(name);
TypeInformation<T> type = parameter.getType();
Class<T> rawType = parameter.getRawType();
String key = idProperty == null ? name : idProperty.getName().equals(name) ? idProperty.getKey() : name;
Object obj = dbo.get(key);
ctorParamNames.add(name);
if (obj instanceof DBRef) {
@@ -244,42 +253,33 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
} else if (obj instanceof BasicDBList) {
BasicDBList objAsDbList = (BasicDBList) obj;
List<?> l = unwrapList(objAsDbList, type);
return conversionService.convert(l, parameter.getRawType());
return conversionService.convert(l, rawType);
} else if (obj instanceof DBObject) {
return read(type, ((DBObject) obj));
} else if (null != obj && obj.getClass().isAssignableFrom(type)) {
return obj;
} else if (null != obj && obj.getClass().isAssignableFrom(rawType)) {
return (T) obj;
} else if (null != obj) {
return conversionService.convert(obj, type);
return conversionService.convert(obj, rawType);
}
return null;
}
}, spelCtx);
// Set the ID
PersistentProperty idProperty = entity.getIdProperty();
if (dbo.containsField("_id") && null != idProperty) {
Object idObj = dbo.get("_id");
try {
setProperty(instance, idProperty, idObj, useFieldAccessOnly);
} catch (IllegalAccessException e) {
throw new MappingException(e.getMessage(), e);
} catch (InvocationTargetException e) {
throw new MappingException(e.getMessage(), e);
}
}
// Set properties not already set in the constructor
entity.doWithProperties(new PropertyHandler() {
public void doWithPersistentProperty(PersistentProperty prop) {
if (ctorParamNames.contains(prop.getName())) {
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
public void doWithPersistentProperty(MongoPersistentProperty prop) {
boolean isConstructorProperty = ctorParamNames.contains(prop.getName());
boolean hasValueForProperty = dbo.containsField(prop.getKey());
if (!hasValueForProperty || isConstructorProperty) {
return;
}
Object obj = getValueInternal(prop, dbo, spelCtx, prop.getSpelExpression());
try {
setProperty(instance, prop, obj, useFieldAccessOnly);
setProperty(instance, prop, obj, useFieldAccessOnly);
} catch (IllegalAccessException e) {
throw new MappingException(e.getMessage(), e);
} catch (InvocationTargetException e) {
@@ -289,9 +289,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
});
// Handle associations
entity.doWithAssociations(new AssociationHandler() {
public void doWithAssociation(Association association) {
PersistentProperty inverseProp = association.getInverse();
entity.doWithAssociations(new AssociationHandler<MongoPersistentProperty>() {
public void doWithAssociation(Association<MongoPersistentProperty> association) {
MongoPersistentProperty inverseProp = association.getInverse();
Object obj = getValueInternal(inverseProp, dbo, spelCtx, inverseProp.getSpelExpression());
try {
setProperty(instance, inverseProp, obj);
@@ -325,11 +325,11 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
return;
}
PersistentEntity<?> entity = mappingContext.getPersistentEntity(obj.getClass());
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(obj.getClass());
write(obj, dbo, entity);
}
protected void write(final Object obj, final DBObject dbo, PersistentEntity<?> entity) {
protected void write(final Object obj, final DBObject dbo, MongoPersistentEntity<?> entity) {
if (obj == null) {
return;
@@ -340,7 +340,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
// Write the ID
final PersistentProperty idProperty = entity.getIdProperty();
final MongoPersistentProperty idProperty = entity.getIdProperty();
if (!dbo.containsField("_id") && null != idProperty) {
Object idObj;
try {
@@ -361,8 +361,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
// Write the properties
entity.doWithProperties(new PropertyHandler() {
public void doWithPersistentProperty(PersistentProperty prop) {
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
public void doWithPersistentProperty(MongoPersistentProperty prop) {
String name = prop.getName();
Class<?> type = prop.getType();
Object propertyObj;
@@ -383,9 +383,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
});
entity.doWithAssociations(new AssociationHandler() {
public void doWithAssociation(Association association) {
PersistentProperty inverseProp = association.getInverse();
entity.doWithAssociations(new AssociationHandler<MongoPersistentProperty>() {
public void doWithAssociation(Association<MongoPersistentProperty> association) {
MongoPersistentProperty inverseProp = association.getInverse();
Class<?> type = inverseProp.getType();
Object propertyObj;
try {
@@ -429,7 +429,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
@SuppressWarnings({"unchecked"})
protected void writePropertyInternal(PersistentProperty prop, Object obj, DBObject dbo) {
protected void writePropertyInternal(MongoPersistentProperty prop, Object obj, DBObject dbo) {
org.springframework.data.document.mongodb.mapping.DBRef dbref = prop.getField()
.getAnnotation(org.springframework.data.document.mongodb.mapping.DBRef.class);
@@ -441,7 +441,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
if (type.isArray()) {
coll = new ArrayList<Object>();
for (Object o : (Object[]) obj) {
((List) coll).add(o);
((List<Object>) coll).add(o);
}
} else {
coll = (Collection<?>) obj;
@@ -454,9 +454,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
dbList.add(propObjItem);
} else if (propObjItem instanceof List) {
List<?> propObjColl = (List<?>) propObjItem;
ClassTypeInformation typeInfo = new ClassTypeInformation(propObjItem.getClass());
TypeInformation<?> typeInfo = ClassTypeInformation.from(propObjItem.getClass());
while (typeInfo.isCollectionLike()) {
typeInfo = new ClassTypeInformation(typeInfo.getComponentType().getType());
typeInfo = typeInfo.getComponentType();
}
if (isSimpleType(typeInfo.getType())) {
dbList.add(propObjColl);
@@ -540,12 +540,12 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
protected DBRef createDBRef(Object target, org.springframework.data.document.mongodb.mapping.DBRef dbref) {
PersistentEntity<?> targetEntity = mappingContext.getPersistentEntity(target.getClass());
MongoPersistentEntity<?> targetEntity = mappingContext.getPersistentEntity(target.getClass());
if (null == targetEntity || null == targetEntity.getIdProperty()) {
return null;
}
PersistentProperty idProperty = targetEntity.getIdProperty();
MongoPersistentProperty idProperty = targetEntity.getIdProperty();
ObjectId id = null;
try {
id = getProperty(target, idProperty, ObjectId.class, useFieldAccessOnly);
@@ -573,22 +573,21 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
@SuppressWarnings({"unchecked"})
protected Object getValueInternal(PersistentProperty prop, DBObject dbo, StandardEvaluationContext ctx, String spelExpr) {
String name = prop.getName();
Class<?> propertyType = prop.getType();
protected Object getValueInternal(MongoPersistentProperty prop, DBObject dbo, StandardEvaluationContext ctx, String spelExpr) {
Object o;
if (null != spelExpr) {
Expression x = spelExpressionParser.parseExpression(spelExpr);
o = x.getValue(ctx);
} else {
Object dbObj = dbo.get(name);
Object dbObj = dbo.get(prop.getKey());
if (dbObj == null) {
return null;
}
Class<?> propertyType = prop.getType();
Class<?> customTarget = getCustomTarget(dbObj.getClass(), propertyType);
if (customTarget != null) {
@@ -675,12 +674,12 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
}
protected <T> List<?> unwrapList(BasicDBList dbList, Class<T> targetType) {
protected <T> List<?> unwrapList(BasicDBList dbList, TypeInformation<T> targetType) {
List<Object> rootList = new LinkedList<Object>();
for (int i = 0; i < dbList.size(); i++) {
Object obj = dbList.get(i);
if (obj instanceof BasicDBList) {
rootList.add(unwrapList((BasicDBList) obj, targetType));
rootList.add(unwrapList((BasicDBList) obj, targetType.getComponentType()));
} else if (obj instanceof DBObject) {
rootList.add(read(targetType, (DBObject) obj));
} else {

View File

@@ -19,6 +19,8 @@ import com.mongodb.BasicDBList;
import org.bson.types.ObjectId;
import org.springframework.data.document.mongodb.MongoReader;
import org.springframework.data.document.mongodb.MongoWriter;
import org.springframework.data.document.mongodb.mapping.MongoPersistentEntity;
import org.springframework.data.document.mongodb.mapping.MongoPersistentProperty;
import org.springframework.data.mapping.model.MappingContext;
@@ -43,7 +45,7 @@ public interface MongoConverter extends MongoWriter<Object>, MongoReader<Object>
*/
public ObjectId convertObjectId(Object id);
MappingContext getMappingContext();
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> getMappingContext();
Object maybeConvertObject(Object obj);

View File

@@ -30,7 +30,6 @@ import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -57,6 +56,7 @@ import org.springframework.core.convert.support.ConversionServiceFactory;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.document.mongodb.MongoPropertyDescriptors.MongoPropertyDescriptor;
import org.springframework.data.document.mongodb.mapping.MongoPersistentEntity;
import org.springframework.data.document.mongodb.mapping.MongoPersistentProperty;
import org.springframework.data.document.mongodb.mapping.SimpleMongoMappingContext;
import org.springframework.data.mapping.model.MappingContext;
import org.springframework.util.Assert;
@@ -126,7 +126,7 @@ public class SimpleMongoConverter extends AbstractMongoConverter implements Init
}
private final GenericConversionService conversionService;
private final MappingContext<? extends MongoPersistentEntity<?>> mappingContext;
private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
/**
* Creates a {@link SimpleMongoConverter}.
@@ -140,7 +140,7 @@ public class SimpleMongoConverter extends AbstractMongoConverter implements Init
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.convert.MongoConverter#getMappingContext()
*/
public MappingContext<? extends MongoPersistentEntity<?>> getMappingContext() {
public MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> getMappingContext() {
return mappingContext;
}

View File

@@ -30,7 +30,7 @@ import org.springframework.util.StringUtils;
* @author Jon Brisbin <jbrisbin@vmware.com>
* @author Oliver Gierke
*/
public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T> implements MongoPersistentEntity<T> {
public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, MongoPersistentProperty> implements MongoPersistentEntity<T> {
private final String collection;
private final boolean isRootEntity;
@@ -41,7 +41,7 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T> impl
*
* @param typeInformation
*/
public BasicMongoPersistentEntity(TypeInformation typeInformation) {
public BasicMongoPersistentEntity(TypeInformation<T> typeInformation) {
super(typeInformation);
@@ -73,7 +73,7 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T> impl
@Override
public void verify() {
if (isRootEntity && idProperty == null) {
throw new MappingException(String.format("Root entity %s has to have an id property!", type.getName()));
throw new MappingException(String.format("Root entity %s has to have an id property!", getType().getName()));
}
}
}

View File

@@ -0,0 +1,103 @@
/*
* Copyright (c) 2011 by the original author(s).
*
* 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.document.mongodb.mapping;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.math.BigInteger;
import java.util.HashSet;
import java.util.Set;
import org.bson.types.ObjectId;
import org.springframework.data.mapping.AnnotationBasedPersistentProperty;
import org.springframework.data.mapping.model.Association;
import com.mongodb.DBObject;
/**
* Mongo specific
* {@link org.springframework.data.mapping.model.PersistentProperty}
* implementation.
*
* @author Oliver Gierke
*/
public class BasicMongoPersistentProperty extends AnnotationBasedPersistentProperty<MongoPersistentProperty> implements MongoPersistentProperty {
private static final Set<Class<?>> SUPPORTED_ID_TYPES = new HashSet<Class<?>>();
private static final Set<String> SUPPORTED_ID_PROPERTY_NAMES = new HashSet<String>();
static {
SUPPORTED_ID_TYPES.add(ObjectId.class);
SUPPORTED_ID_TYPES.add(String.class);
SUPPORTED_ID_TYPES.add(BigInteger.class);
SUPPORTED_ID_PROPERTY_NAMES.add("id");
SUPPORTED_ID_PROPERTY_NAMES.add("_id");
}
/**
* Creates a new {@link BasicMongoPersistentProperty}.
*
* @param field
* @param propertyDescriptor
* @param owningTypeInformation
*/
public BasicMongoPersistentProperty(Field field,
PropertyDescriptor propertyDescriptor, MongoPersistentEntity<?> owner) {
super(field, propertyDescriptor, owner);
}
/* (non-Javadoc)
* @see org.springframework.data.mapping.FooBasicPersistentProperty#isAssociation()
*/
@Override
public boolean isAssociation() {
return field.isAnnotationPresent(DBRef.class) || super.isAssociation();
}
/**
* Also considers fields as id that are of supported id type and name.
*
* @see #SUPPORTED_ID_PROPERTY_NAMES
* @see #SUPPORTED_ID_TYPES
*/
@Override
public boolean isIdProperty() {
if (super.isIdProperty()) {
return true;
}
return SUPPORTED_ID_TYPES.contains(field.getType())
&& SUPPORTED_ID_PROPERTY_NAMES.contains(field.getName());
}
/**
* Returns the key to be used to store the value of the property inside a Mongo {@link DBObject}.
*
* @return
*/
public String getKey() {
return isIdProperty() ? "_id" : getName();
}
/* (non-Javadoc)
* @see org.springframework.data.mapping.AbstractPersistentProperty#createAssociation()
*/
@Override
protected Association<MongoPersistentProperty> createAssociation() {
return new Association<MongoPersistentProperty>(this, null);
}
}

View File

@@ -30,7 +30,6 @@ import org.springframework.data.util.TypeInformation;
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class MongoMappingContext extends AbstractMappingContext<BasicMongoPersistentEntity<?>, MongoPersistentProperty> {
public MongoMappingContext() {
augmentSimpleTypes();
}
@@ -46,15 +45,14 @@ public class MongoMappingContext extends AbstractMappingContext<BasicMongoPersis
@Override
public MongoPersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor, BasicMongoPersistentEntity<?> owner) {
return new MongoPersistentProperty(field, descriptor, owner);
return new BasicMongoPersistentProperty(field, descriptor, owner);
}
/* (non-Javadoc)
* @see org.springframework.data.mapping.BasicMappingContext#createPersistentEntity(org.springframework.data.util.TypeInformation, org.springframework.data.mapping.model.MappingContext)
*/
@Override
@SuppressWarnings("rawtypes")
protected BasicMongoPersistentEntity<?> createPersistentEntity(TypeInformation typeInformation) {
return new BasicMongoPersistentEntity(typeInformation);
protected <T> BasicMongoPersistentEntity<T> createPersistentEntity(TypeInformation<T> typeInformation) {
return new BasicMongoPersistentEntity<T>(typeInformation);
}
}

View File

@@ -6,7 +6,7 @@ import org.springframework.data.mapping.model.PersistentEntity;
*
* @author Oliver Gierke
*/
public interface MongoPersistentEntity<T> extends PersistentEntity<T> {
public interface MongoPersistentEntity<T> extends PersistentEntity<T, MongoPersistentProperty> {
String getCollection();
}

View File

@@ -15,14 +15,7 @@
*/
package org.springframework.data.document.mongodb.mapping;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.math.BigInteger;
import java.util.HashSet;
import java.util.Set;
import org.bson.types.ObjectId;
import org.springframework.data.mapping.AnnotationBasedPersistentProperty;
import org.springframework.data.mapping.model.PersistentProperty;
/**
* Mongo specific
@@ -31,53 +24,6 @@ import org.springframework.data.mapping.AnnotationBasedPersistentProperty;
*
* @author Oliver Gierke
*/
public class MongoPersistentProperty extends AnnotationBasedPersistentProperty {
private static final Set<Class<?>> SUPPORTED_ID_TYPES = new HashSet<Class<?>>();
private static final Set<String> SUPPORTED_ID_PROPERTY_NAMES = new HashSet<String>();
static {
SUPPORTED_ID_TYPES.add(ObjectId.class);
SUPPORTED_ID_TYPES.add(String.class);
SUPPORTED_ID_TYPES.add(BigInteger.class);
SUPPORTED_ID_PROPERTY_NAMES.add("id");
SUPPORTED_ID_PROPERTY_NAMES.add("_id");
}
/**
* Creates a new {@link MongoPersistentProperty}.
*
* @param field
* @param propertyDescriptor
* @param owningTypeInformation
*/
public MongoPersistentProperty(Field field,
PropertyDescriptor propertyDescriptor, MongoPersistentEntity<?> owner) {
super(field, propertyDescriptor, owner);
}
/* (non-Javadoc)
* @see org.springframework.data.mapping.FooBasicPersistentProperty#isAssociation()
*/
@Override
public boolean isAssociation() {
return field.isAnnotationPresent(DBRef.class) || super.isAssociation();
}
/**
* Also considers fields as id that are of supported id type and name.
*
* @see #SUPPORTED_ID_PROPERTY_NAMES
* @see #SUPPORTED_ID_TYPES
*/
@Override
public boolean isIdProperty() {
if (super.isIdProperty()) {
return true;
}
return SUPPORTED_ID_TYPES.contains(field.getType())
&& SUPPORTED_ID_PROPERTY_NAMES.contains(field.getName());
}
public interface MongoPersistentProperty extends PersistentProperty<MongoPersistentProperty> {
String getKey();
}

View File

@@ -1,3 +1,18 @@
/*
* Copyright (c) 2011 by the original author(s).
*
* 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.document.mongodb.mapping;
import java.beans.PropertyDescriptor;
@@ -8,21 +23,21 @@ import java.util.List;
import org.springframework.data.mapping.AbstractMappingContext;
import org.springframework.data.mapping.BasicPersistentEntity;
import org.springframework.data.mapping.AbstractPersistentProperty;
import org.springframework.data.mapping.model.Association;
import org.springframework.data.util.TypeInformation;
/**
*
* @author Oliver Gierke
*/
public class SimpleMongoMappingContext extends AbstractMappingContext<SimpleMongoMappingContext.SimpleMongoPersistentEntity<?>, SimpleMongoMappingContext.SimplePersistentProperty> {
public class SimpleMongoMappingContext extends AbstractMappingContext<SimpleMongoMappingContext.SimpleMongoPersistentEntity<?>, MongoPersistentProperty> {
/* (non-Javadoc)
* @see org.springframework.data.mapping.BasicMappingContext#createPersistentEntity(org.springframework.data.util.TypeInformation)
*/
@Override
@SuppressWarnings("rawtypes")
protected SimpleMongoPersistentEntity<?> createPersistentEntity(TypeInformation typeInformation) {
return new SimpleMongoPersistentEntity(typeInformation);
protected <T> SimpleMongoPersistentEntity<T> createPersistentEntity(TypeInformation<T> typeInformation) {
return new SimpleMongoPersistentEntity<T>(typeInformation);
}
/* (non-Javadoc)
@@ -33,7 +48,7 @@ public class SimpleMongoMappingContext extends AbstractMappingContext<SimpleMong
return new SimplePersistentProperty(field, descriptor, owner);
}
static class SimplePersistentProperty extends AbstractPersistentProperty {
static class SimplePersistentProperty extends AbstractPersistentProperty<MongoPersistentProperty> implements MongoPersistentProperty {
private static final List<String> ID_FIELD_NAMES = Arrays.asList("id", "_id");
@@ -44,7 +59,7 @@ public class SimpleMongoMappingContext extends AbstractMappingContext<SimpleMong
* @param propertyDescriptor
* @param information
*/
public SimplePersistentProperty(Field field, PropertyDescriptor propertyDescriptor, SimpleMongoPersistentEntity<?> owner) {
public SimplePersistentProperty(Field field, PropertyDescriptor propertyDescriptor, MongoPersistentEntity<?> owner) {
super(field, propertyDescriptor, owner);
}
@@ -54,14 +69,29 @@ public class SimpleMongoMappingContext extends AbstractMappingContext<SimpleMong
public boolean isIdProperty() {
return ID_FIELD_NAMES.contains(field.getName());
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.mapping.MongoPersistentProperty#getKey()
*/
public String getKey() {
return isIdProperty() ? "_id" : getName();
}
/* (non-Javadoc)
* @see org.springframework.data.mapping.AbstractPersistentProperty#createAssociation()
*/
@Override
protected Association<MongoPersistentProperty> createAssociation() {
return new Association<MongoPersistentProperty>(this, null);
}
}
static class SimpleMongoPersistentEntity<T> extends BasicPersistentEntity<T> implements MongoPersistentEntity<T> {
static class SimpleMongoPersistentEntity<T> extends BasicPersistentEntity<T, MongoPersistentProperty> implements MongoPersistentEntity<T> {
/**
* @param information
*/
public SimpleMongoPersistentEntity(TypeInformation information) {
public SimpleMongoPersistentEntity(TypeInformation<T> information) {
super(information);
}
@@ -69,7 +99,7 @@ public class SimpleMongoMappingContext extends AbstractMappingContext<SimpleMong
* @see org.springframework.data.document.mongodb.mapping.MongoPersistentEntity#getCollection()
*/
public String getCollection() {
return type.getSimpleName();
return getType().getSimpleName();
}
}
}

View File

@@ -23,6 +23,7 @@ import com.mongodb.DBObject;
import org.bson.types.ObjectId;
import org.springframework.core.convert.ConversionFailedException;
import org.springframework.data.document.mongodb.convert.MongoConverter;
import org.springframework.data.document.mongodb.mapping.MongoPersistentEntity;
import org.springframework.data.mapping.model.PersistentEntity;
import org.springframework.util.Assert;
@@ -54,7 +55,7 @@ public class QueryMapper {
* @param entity
* @return
*/
public DBObject getMappedObject(DBObject query, PersistentEntity<?> entity) {
public DBObject getMappedObject(DBObject query, MongoPersistentEntity<?> entity) {
String idKey = null;
if (null != entity && entity.getIdProperty() != null) {
idKey = entity.getIdProperty().getName();

View File

@@ -32,8 +32,6 @@ import org.springframework.data.repository.query.ParameterAccessor;
* @author Oliver Gierke
*/
public class ConvertingParameterAccessor implements ParameterAccessor {
// private static final Set<Class<?>> TYPES_NOT_TO_CONVERT = new HashSet<Class<?>>(Arrays.asList(Circle.class, Box.class))
private final MongoWriter<Object> writer;
private final ParameterAccessor delegate;
@@ -92,7 +90,7 @@ public class ConvertingParameterAccessor implements ParameterAccessor {
private Object getConvertedValue(Object value) {
DBObject result = new BasicDBObject();
writer.write(value.getClass().isEnum() ? new EnumValueHolder((Enum<?>) value) : new ValueHolder(value), result);
writer.write(new ValueHolder(value), result);
return ((DBObject) result.get("value")).get("value");
}
@@ -172,23 +170,6 @@ public class ConvertingParameterAccessor implements ParameterAccessor {
}
}
private static class EnumValueHolder {
private Enum<?> value;
public EnumValueHolder(Enum<?> value) {
this.value = value;
}
/**
* @return the value
*/
@SuppressWarnings("unused")
public Enum<?> getValue() {
return value;
}
}
/**
* Custom {@link Iterator} that adds a method to access elements in a converted manner.
*

View File

@@ -29,6 +29,7 @@ import org.springframework.data.document.mongodb.MongoOperations;
import org.springframework.data.document.mongodb.MongoPropertyDescriptors.MongoPropertyDescriptor;
import org.springframework.data.document.mongodb.MongoTemplate;
import org.springframework.data.document.mongodb.mapping.MongoPersistentEntity;
import org.springframework.data.document.mongodb.mapping.MongoPersistentProperty;
import org.springframework.data.document.mongodb.query.Index;
import org.springframework.data.document.mongodb.query.Order;
import org.springframework.data.domain.Sort;
@@ -55,7 +56,7 @@ public class MongoRepositoryFactoryBean<T extends MongoRepository<S, ID>, S, ID
RepositoryFactoryBeanSupport<T, S, ID> {
private MongoTemplate template;
private MappingContext<MongoPersistentEntity<?>> mappingContext;
private MappingContext<MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
/**
* Configures the {@link MongoTemplate} to be used.
@@ -72,7 +73,7 @@ public class MongoRepositoryFactoryBean<T extends MongoRepository<S, ID>, S, ID
*
* @param mappingContext the mappingContext to set
*/
public void setMappingContext(MappingContext<MongoPersistentEntity<?>> mappingContext) {
public void setMappingContext(MappingContext<MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
this.mappingContext = mappingContext;
}
@@ -122,7 +123,7 @@ public class MongoRepositoryFactoryBean<T extends MongoRepository<S, ID>, S, ID
* @param template must not be {@literal null}
* @param mappingContext
*/
public MongoRepositoryFactory(MongoTemplate template, MappingContext<MongoPersistentEntity<?>> mappingContext) {
public MongoRepositoryFactory(MongoTemplate template, MappingContext<MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
Assert.notNull(template);
Assert.notNull(mappingContext);
@@ -246,9 +247,9 @@ public class MongoRepositoryFactoryBean<T extends MongoRepository<S, ID>, S, ID
*/
static class EntityInformationCreator {
private final MappingContext<MongoPersistentEntity<?>> mappingContext;
private final MappingContext<MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
public EntityInformationCreator(MappingContext<MongoPersistentEntity<?>> mappingContext) {
public EntityInformationCreator(MappingContext<MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
Assert.notNull(mappingContext);
this.mappingContext = mappingContext;
}

View File

@@ -32,8 +32,9 @@ import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.dao.DataAccessException;
import org.springframework.data.document.mongodb.convert.AbstractMongoConverter;
import org.springframework.data.document.mongodb.convert.MongoConverter;
import org.springframework.data.document.mongodb.mapping.MongoPersistentEntity;
import org.springframework.data.document.mongodb.mapping.MongoPersistentProperty;
import org.springframework.data.mapping.model.MappingContext;
import org.springframework.data.mapping.model.PersistentEntity;
/**
* Abstract base class for unit tests to specify behaviour we expect from {@link MongoOperations}. Subclasses return
@@ -78,7 +79,7 @@ public abstract class MongoOperationsUnitTests {
return null;
}
public MappingContext<PersistentEntity<?>> getMappingContext() {
public MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> getMappingContext() {
return null;
}
};

View File

@@ -21,6 +21,7 @@ import org.springframework.data.document.analytics.Parameters;
import org.springframework.data.document.mongodb.MongoTemplate;
import org.springframework.data.document.mongodb.convert.AbstractMongoConverter;
import org.springframework.data.document.mongodb.mapping.MongoPersistentEntity;
import org.springframework.data.document.mongodb.mapping.MongoPersistentProperty;
import org.springframework.data.document.mongodb.query.BasicQuery;
import org.springframework.data.mapping.model.MappingContext;
@@ -53,7 +54,7 @@ public class MvcAnalyticsTests {
return null;
}
public MappingContext<? extends MongoPersistentEntity<?>> getMappingContext() {
public MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> getMappingContext() {
return null;
}

View File

@@ -20,6 +20,8 @@ import static org.mockito.Mockito.*;
import java.util.Arrays;
import java.util.HashSet;
import org.hamcrest.CoreMatchers;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -28,6 +30,7 @@ import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.annotation.Id;
import org.springframework.data.document.mongodb.mapping.MongoMappingContext;
import org.springframework.data.document.mongodb.mapping.MongoMappingContext;
import org.springframework.data.document.mongodb.mapping.MongoPersistentEntity;
import com.mongodb.BasicDBObject;
@@ -101,6 +104,14 @@ public class CustomConvertersUnitTests {
converter.read(Bar.class, new BasicDBObject());
verify(dbObjectToBarConverter).convert(any(DBObject.class));
}
@Test
public void foo() {
DBObject dbObject = new BasicDBObject();
dbObject.put("foo", null);
Assert.assertThat(dbObject.containsField("foo"), CoreMatchers.is(true));
}
public static class Foo {
@Id

View File

@@ -17,6 +17,7 @@
package org.springframework.data.document.mongodb.mapping;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.PersistenceConstructor;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
@@ -32,6 +33,7 @@ public class PersonCustomIdName extends BasePerson {
this.firstName = firstName;
}
@PersistenceConstructor
public PersonCustomIdName(Integer ssn, String firstName, String lastName) {
this.ssn = ssn;
this.firstName = firstName;

View File

@@ -26,9 +26,8 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.data.document.mongodb.convert.MongoConverter;
import org.springframework.data.mapping.model.PersistentEntity;
import org.springframework.data.mapping.model.PersistentProperty;
import org.springframework.data.document.mongodb.mapping.MongoPersistentEntity;
import org.springframework.data.document.mongodb.mapping.MongoPersistentProperty;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
@@ -45,9 +44,9 @@ public class QueryMapperUnitTests {
@Mock
MongoConverter converter;
@Mock
PersistentEntity<?> entity;
MongoPersistentEntity<?> entity;
@Mock
PersistentProperty property;
MongoPersistentProperty property;
@Before
public void setUp() {

View File

@@ -26,6 +26,7 @@ import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.data.document.mongodb.MongoTemplate;
import org.springframework.data.document.mongodb.mapping.MongoPersistentEntity;
import org.springframework.data.document.mongodb.mapping.MongoPersistentProperty;
import org.springframework.data.document.mongodb.repository.MongoRepositoryFactoryBean.MongoRepositoryFactory;
import org.springframework.data.mapping.model.MappingContext;
@@ -41,7 +42,7 @@ public class MongoRepositoryFactoryUnitTests {
MongoTemplate template;
@Mock
MappingContext<MongoPersistentEntity<?>> mappingContext;
MappingContext<MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
@Mock
@SuppressWarnings("rawtypes")