DATAMONGO-383 - Adapt new EntityInstantiator API of Spring Data Commons.
This commit is contained in:
@@ -19,7 +19,7 @@
|
|||||||
<org.springframework.version.30>3.0.7.RELEASE</org.springframework.version.30>
|
<org.springframework.version.30>3.0.7.RELEASE</org.springframework.version.30>
|
||||||
<org.springframework.version.40>4.0.0.RELEASE</org.springframework.version.40>
|
<org.springframework.version.40>4.0.0.RELEASE</org.springframework.version.40>
|
||||||
<org.springframework.version.range>[${org.springframework.version.30}, ${org.springframework.version.40})</org.springframework.version.range>
|
<org.springframework.version.range>[${org.springframework.version.30}, ${org.springframework.version.40})</org.springframework.version.range>
|
||||||
<data.commons.version>1.2.0.RELEASE</data.commons.version>
|
<data.commons.version>1.3.0.BUILD-SNAPSHOT</data.commons.version>
|
||||||
<aspectj.version>1.6.11.RELEASE</aspectj.version>
|
<aspectj.version>1.6.11.RELEASE</aspectj.version>
|
||||||
</properties>
|
</properties>
|
||||||
<profiles>
|
<profiles>
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import org.springframework.beans.factory.InitializingBean;
|
|||||||
import org.springframework.core.convert.ConversionService;
|
import org.springframework.core.convert.ConversionService;
|
||||||
import org.springframework.core.convert.support.ConversionServiceFactory;
|
import org.springframework.core.convert.support.ConversionServiceFactory;
|
||||||
import org.springframework.core.convert.support.GenericConversionService;
|
import org.springframework.core.convert.support.GenericConversionService;
|
||||||
|
import org.springframework.data.convert.EntityInstantiators;
|
||||||
import org.springframework.data.mongodb.core.convert.MongoConverters.BigIntegerToObjectIdConverter;
|
import org.springframework.data.mongodb.core.convert.MongoConverters.BigIntegerToObjectIdConverter;
|
||||||
import org.springframework.data.mongodb.core.convert.MongoConverters.ObjectIdToBigIntegerConverter;
|
import org.springframework.data.mongodb.core.convert.MongoConverters.ObjectIdToBigIntegerConverter;
|
||||||
import org.springframework.data.mongodb.core.convert.MongoConverters.ObjectIdToStringConverter;
|
import org.springframework.data.mongodb.core.convert.MongoConverters.ObjectIdToStringConverter;
|
||||||
@@ -39,6 +40,7 @@ public abstract class AbstractMongoConverter implements MongoConverter, Initiali
|
|||||||
|
|
||||||
protected final GenericConversionService conversionService;
|
protected final GenericConversionService conversionService;
|
||||||
protected CustomConversions conversions = new CustomConversions();
|
protected CustomConversions conversions = new CustomConversions();
|
||||||
|
protected EntityInstantiators instantiators = new EntityInstantiators();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link AbstractMongoConverter} using the given {@link GenericConversionService}.
|
* Creates a new {@link AbstractMongoConverter} using the given {@link GenericConversionService}.
|
||||||
@@ -60,6 +62,15 @@ public abstract class AbstractMongoConverter implements MongoConverter, Initiali
|
|||||||
this.conversions = conversions;
|
this.conversions = conversions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers {@link EntityInstantiators} to customize entity instantiation.
|
||||||
|
*
|
||||||
|
* @param instantiators
|
||||||
|
*/
|
||||||
|
public void setInstantiators(EntityInstantiators instantiators) {
|
||||||
|
this.instantiators = instantiators == null ? new EntityInstantiators() : instantiators;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers additional converters that will be available when using the {@link ConversionService} directly (e.g. for
|
* Registers additional converters that will be available when using the {@link ConversionService} directly (e.g. for
|
||||||
* id conversion). These converters are not custom conversions as they'd introduce unwanted conversions (e.g.
|
* id conversion). These converters are not custom conversions as they'd introduce unwanted conversions (e.g.
|
||||||
|
|||||||
@@ -1,168 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012 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.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.springframework.data.mapping.PersistentEntity;
|
|
||||||
import org.springframework.data.mapping.PersistentProperty;
|
|
||||||
import org.springframework.data.mapping.PreferredConstructor;
|
|
||||||
import org.springframework.data.mapping.PreferredConstructor.Parameter;
|
|
||||||
import org.springframework.data.mapping.PropertyPath;
|
|
||||||
import org.springframework.data.mapping.context.MappingContext;
|
|
||||||
import org.springframework.data.mapping.context.PersistentPropertyPath;
|
|
||||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
|
||||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
|
||||||
import org.springframework.data.util.TypeInformation;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstraction for a {@link PreferredConstructor} alongside mapping information.
|
|
||||||
*
|
|
||||||
* @author Oliver Gierke
|
|
||||||
*/
|
|
||||||
class MappedConstructor {
|
|
||||||
|
|
||||||
private final Set<MappedConstructor.MappedParameter> parameters;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link MappedConstructor} from the given {@link MongoPersistentEntity} and {@link MappingContext}.
|
|
||||||
*
|
|
||||||
* @param entity must not be {@literal null}.
|
|
||||||
* @param context must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
public MappedConstructor(MongoPersistentEntity<?> entity,
|
|
||||||
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> context) {
|
|
||||||
|
|
||||||
Assert.notNull(entity);
|
|
||||||
Assert.notNull(context);
|
|
||||||
|
|
||||||
this.parameters = new HashSet<MappedConstructor.MappedParameter>();
|
|
||||||
|
|
||||||
for (Parameter<?> parameter : entity.getPreferredConstructor().getParameters()) {
|
|
||||||
parameters.add(new MappedParameter(parameter, entity, context));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the given {@link PersistentProperty} is referenced in a constructor argument of the
|
|
||||||
* {@link PersistentEntity} backing this {@link MappedConstructor}.
|
|
||||||
*
|
|
||||||
* @param property must not be {@literal null}.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean isConstructorParameter(PersistentProperty<?> property) {
|
|
||||||
|
|
||||||
Assert.notNull(property);
|
|
||||||
|
|
||||||
for (MappedConstructor.MappedParameter parameter : parameters) {
|
|
||||||
if (parameter.maps(property)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the {@link MappedParameter} for the given {@link Parameter}.
|
|
||||||
*
|
|
||||||
* @param parameter must not be {@literal null}.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public MappedParameter getFor(Parameter<?> parameter) {
|
|
||||||
|
|
||||||
for (MappedParameter mappedParameter : parameters) {
|
|
||||||
if (mappedParameter.parameter.equals(parameter)) {
|
|
||||||
return mappedParameter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalStateException(String.format("Didn't find a MappedParameter for %s!", parameter.toString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstraction of a {@link Parameter} alongside mapping information.
|
|
||||||
*
|
|
||||||
* @author Oliver Gierke
|
|
||||||
*/
|
|
||||||
static class MappedParameter {
|
|
||||||
|
|
||||||
private final MongoPersistentProperty property;
|
|
||||||
private final Parameter<?> parameter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link MappedParameter} for the given {@link Parameter}, {@link MongoPersistentProperty} and
|
|
||||||
* {@link MappingContext}.
|
|
||||||
*
|
|
||||||
* @param parameter must not be {@literal null}.
|
|
||||||
* @param entity must not be {@literal null}.
|
|
||||||
* @param context must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
public MappedParameter(Parameter<?> parameter, MongoPersistentEntity<?> entity,
|
|
||||||
MappingContext<? extends MongoPersistentEntity<?>, ? extends MongoPersistentProperty> context) {
|
|
||||||
|
|
||||||
Assert.notNull(parameter);
|
|
||||||
Assert.notNull(entity);
|
|
||||||
Assert.notNull(context);
|
|
||||||
|
|
||||||
this.parameter = parameter;
|
|
||||||
|
|
||||||
PropertyPath propertyPath = PropertyPath.from(parameter.getName(), entity.getType());
|
|
||||||
PersistentPropertyPath<? extends MongoPersistentProperty> path = context.getPersistentPropertyPath(propertyPath);
|
|
||||||
this.property = path == null ? null : path.getLeafProperty();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether there is a SpEL expression configured for this parameter.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean hasSpELExpression() {
|
|
||||||
return parameter.getKey() != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the field name to be used to lookup the value which in turn shall be converted into the constructor
|
|
||||||
* parameter.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public String getFieldName() {
|
|
||||||
return property.getFieldName();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the type of the property backing the {@link Parameter}.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public TypeInformation<?> getPropertyTypeInformation() {
|
|
||||||
return property.getTypeInformation();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the given {@link PersistentProperty} is mapped by the parameter.
|
|
||||||
*
|
|
||||||
* @param property
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean maps(PersistentProperty<?> property) {
|
|
||||||
return this.property.equals(property);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.mongodb.core.convert;
|
package org.springframework.data.mongodb.core.convert;
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -30,29 +29,30 @@ import org.apache.commons.logging.LogFactory;
|
|||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationContextAware;
|
import org.springframework.context.ApplicationContextAware;
|
||||||
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.EntityInstantiator;
|
||||||
import org.springframework.data.convert.TypeMapper;
|
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.Parameter;
|
|
||||||
import org.springframework.data.mapping.PropertyHandler;
|
import org.springframework.data.mapping.PropertyHandler;
|
||||||
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.DefaultSpELExpressionEvaluator;
|
||||||
import org.springframework.data.mapping.model.MappingException;
|
import org.springframework.data.mapping.model.MappingException;
|
||||||
import org.springframework.data.mapping.model.ParameterValueProvider;
|
import org.springframework.data.mapping.model.ParameterValueProvider;
|
||||||
import org.springframework.data.mapping.model.SpELAwareParameterValueProvider;
|
import org.springframework.data.mapping.model.PersistentEntityParameterValueProvider;
|
||||||
|
import org.springframework.data.mapping.model.PropertyValueProvider;
|
||||||
|
import org.springframework.data.mapping.model.SpELContext;
|
||||||
|
import org.springframework.data.mapping.model.SpELExpressionEvaluator;
|
||||||
import org.springframework.data.mongodb.MongoDbFactory;
|
import org.springframework.data.mongodb.MongoDbFactory;
|
||||||
import org.springframework.data.mongodb.core.QueryMapper;
|
import org.springframework.data.mongodb.core.QueryMapper;
|
||||||
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 org.springframework.data.util.ClassTypeInformation;
|
import org.springframework.data.util.ClassTypeInformation;
|
||||||
import org.springframework.data.util.TypeInformation;
|
import org.springframework.data.util.TypeInformation;
|
||||||
import org.springframework.expression.Expression;
|
|
||||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
|
||||||
import org.springframework.util.Assert;
|
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;
|
||||||
@@ -82,6 +82,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
protected boolean useFieldAccessOnly = true;
|
protected boolean useFieldAccessOnly = true;
|
||||||
protected MongoTypeMapper typeMapper;
|
protected MongoTypeMapper typeMapper;
|
||||||
|
|
||||||
|
private SpELContext spELContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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}.
|
||||||
*
|
*
|
||||||
@@ -101,6 +103,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
this.mappingContext = mappingContext;
|
this.mappingContext = mappingContext;
|
||||||
this.typeMapper = new DefaultMongoTypeMapper(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, mappingContext);
|
this.typeMapper = new DefaultMongoTypeMapper(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, mappingContext);
|
||||||
this.idMapper = new QueryMapper(this);
|
this.idMapper = new QueryMapper(this);
|
||||||
|
|
||||||
|
this.spELContext = new SpELContext(DBObjectPropertyAccessor.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -140,7 +144,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
||||||
*/
|
*/
|
||||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||||
|
|
||||||
this.applicationContext = applicationContext;
|
this.applicationContext = applicationContext;
|
||||||
|
this.spELContext = new SpELContext(this.spELContext, applicationContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -187,34 +193,39 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
return read(persistentEntity, dbo);
|
return read(persistentEntity, dbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <S extends Object> S read(final MongoPersistentEntity<S> entity, final DBObject dbo) {
|
private ParameterValueProvider<MongoPersistentProperty> getParameterProvider(MongoPersistentEntity<?> entity,
|
||||||
|
DBObject source, DefaultSpELExpressionEvaluator evaluator) {
|
||||||
|
|
||||||
final StandardEvaluationContext spelCtx = new StandardEvaluationContext(dbo);
|
MongoDbPropertyValueProvider provider = new MongoDbPropertyValueProvider(source, evaluator);
|
||||||
spelCtx.addPropertyAccessor(DBObjectPropertyAccessor.INSTANCE);
|
PersistentEntityParameterValueProvider<MongoPersistentProperty> parameterProvider = new PersistentEntityParameterValueProvider<MongoPersistentProperty>(
|
||||||
|
entity, provider);
|
||||||
|
parameterProvider.setSpELEvaluator(evaluator);
|
||||||
|
|
||||||
if (applicationContext != null) {
|
return parameterProvider;
|
||||||
spelCtx.setBeanResolver(new BeanFactoryResolver(applicationContext));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final MappedConstructor constructor = new MappedConstructor(entity, mappingContext);
|
private <S extends Object> S read(final MongoPersistentEntity<S> entity, final DBObject dbo) {
|
||||||
|
|
||||||
SpELAwareParameterValueProvider delegate = new SpELAwareParameterValueProvider(spelExpressionParser, spelCtx);
|
final DefaultSpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(dbo, spELContext);
|
||||||
ParameterValueProvider provider = new DelegatingParameterValueProvider(constructor, dbo, delegate);
|
|
||||||
|
|
||||||
final BeanWrapper<MongoPersistentEntity<S>, S> wrapper = BeanWrapper.create(entity, provider, conversionService);
|
ParameterValueProvider<MongoPersistentProperty> provider = getParameterProvider(entity, dbo, evaluator);
|
||||||
|
EntityInstantiator instantiator = instantiators.getInstantiatorFor(entity);
|
||||||
|
S instance = instantiator.createInstance(entity, provider);
|
||||||
|
|
||||||
|
final BeanWrapper<MongoPersistentEntity<S>, S> wrapper = BeanWrapper.create(instance, conversionService);
|
||||||
|
|
||||||
// Set properties not already set in the constructor
|
// Set properties not already set in the constructor
|
||||||
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
|
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
|
||||||
public void doWithPersistentProperty(MongoPersistentProperty prop) {
|
public void doWithPersistentProperty(MongoPersistentProperty prop) {
|
||||||
|
|
||||||
boolean isConstructorProperty = constructor.isConstructorParameter(prop);
|
boolean isConstructorProperty = entity.isConstructorArgument(prop);
|
||||||
boolean hasValueForProperty = dbo.containsField(prop.getFieldName());
|
boolean hasValueForProperty = dbo.containsField(prop.getFieldName());
|
||||||
|
|
||||||
if (!hasValueForProperty || isConstructorProperty) {
|
if (!hasValueForProperty || isConstructorProperty) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object obj = getValueInternal(prop, dbo, spelCtx, prop.getSpelExpression());
|
Object obj = getValueInternal(prop, dbo, evaluator);
|
||||||
wrapper.setProperty(prop, obj, useFieldAccessOnly);
|
wrapper.setProperty(prop, obj, useFieldAccessOnly);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -223,7 +234,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
entity.doWithAssociations(new AssociationHandler<MongoPersistentProperty>() {
|
entity.doWithAssociations(new AssociationHandler<MongoPersistentProperty>() {
|
||||||
public void doWithAssociation(Association<MongoPersistentProperty> association) {
|
public void doWithAssociation(Association<MongoPersistentProperty> association) {
|
||||||
MongoPersistentProperty inverseProp = association.getInverse();
|
MongoPersistentProperty inverseProp = association.getInverse();
|
||||||
Object obj = getValueInternal(inverseProp, dbo, spelCtx, inverseProp.getSpelExpression());
|
Object obj = getValueInternal(inverseProp, dbo, evaluator);
|
||||||
try {
|
try {
|
||||||
wrapper.setProperty(inverseProp, obj);
|
wrapper.setProperty(inverseProp, obj);
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
@@ -621,58 +632,10 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
return new DBRef(db, collection, idMapper.convertId(id));
|
return new DBRef(db, collection, idMapper.convertId(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
protected Object getValueInternal(MongoPersistentProperty prop, DBObject dbo, SpELExpressionEvaluator eval) {
|
||||||
protected Object getValueInternal(MongoPersistentProperty prop, DBObject dbo, StandardEvaluationContext ctx,
|
|
||||||
String spelExpr) {
|
|
||||||
|
|
||||||
Object o;
|
MongoDbPropertyValueProvider provider = new MongoDbPropertyValueProvider(dbo, spELContext);
|
||||||
if (null != spelExpr) {
|
return provider.getPropertyValue(prop);
|
||||||
Expression x = spelExpressionParser.parseExpression(spelExpr);
|
|
||||||
o = x.getValue(ctx);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
Object sourceValue = dbo.get(prop.getFieldName());
|
|
||||||
|
|
||||||
if (sourceValue == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Class<?> propertyType = prop.getType();
|
|
||||||
|
|
||||||
if (conversions.hasCustomReadTarget(sourceValue.getClass(), propertyType)) {
|
|
||||||
return conversionService.convert(sourceValue, propertyType);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sourceValue instanceof DBRef) {
|
|
||||||
sourceValue = ((DBRef) sourceValue).fetch();
|
|
||||||
}
|
|
||||||
if (sourceValue instanceof DBObject) {
|
|
||||||
if (prop.isMap()) {
|
|
||||||
return readMap(prop.getTypeInformation(), (DBObject) sourceValue);
|
|
||||||
} else if (prop.isArray() && sourceValue instanceof BasicDBObject
|
|
||||||
&& ((DBObject) sourceValue).keySet().size() == 0) {
|
|
||||||
// It's empty
|
|
||||||
return Array.newInstance(prop.getComponentType(), 0);
|
|
||||||
} else if (prop.isCollectionLike() && sourceValue instanceof BasicDBList) {
|
|
||||||
return readCollectionOrArray((TypeInformation<? extends Collection<?>>) prop.getTypeInformation(),
|
|
||||||
(BasicDBList) sourceValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
TypeInformation<?> toType = typeMapper.readType((DBObject) sourceValue);
|
|
||||||
|
|
||||||
// It's a complex object, have to read it in
|
|
||||||
if (toType != null) {
|
|
||||||
// TODO: why do we remove the type?
|
|
||||||
// dbo.removeField(CUSTOM_TYPE_KEY);
|
|
||||||
o = read(toType, (DBObject) sourceValue);
|
|
||||||
} else {
|
|
||||||
o = read(mappingContext.getPersistentEntity(prop.getTypeInformation()), (DBObject) sourceValue);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
o = sourceValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return o;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -858,46 +821,42 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
return dbObject;
|
return dbObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DelegatingParameterValueProvider implements ParameterValueProvider {
|
private class MongoDbPropertyValueProvider implements PropertyValueProvider<MongoPersistentProperty> {
|
||||||
|
|
||||||
private final DBObject source;
|
private final DBObject source;
|
||||||
private final ParameterValueProvider delegate;
|
private final SpELExpressionEvaluator evaluator;
|
||||||
private final MappedConstructor constructor;
|
|
||||||
|
|
||||||
/**
|
public MongoDbPropertyValueProvider(DBObject source, SpELContext factory) {
|
||||||
* {@link ParameterValueProvider} to delegate source object lookup to a {@link SpELAwareParameterValueProvider} in
|
this(source, new DefaultSpELExpressionEvaluator(source, factory));
|
||||||
* case a MappCon
|
}
|
||||||
*
|
|
||||||
* @param constructor must not be {@literal null}.
|
public MongoDbPropertyValueProvider(DBObject source, DefaultSpELExpressionEvaluator evaluator) {
|
||||||
* @param source must not be {@literal null}.
|
|
||||||
* @param delegate must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
public DelegatingParameterValueProvider(MappedConstructor constructor, DBObject source,
|
|
||||||
SpELAwareParameterValueProvider delegate) {
|
|
||||||
|
|
||||||
Assert.notNull(constructor);
|
|
||||||
Assert.notNull(source);
|
Assert.notNull(source);
|
||||||
Assert.notNull(delegate);
|
Assert.notNull(evaluator);
|
||||||
|
|
||||||
this.constructor = constructor;
|
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.delegate = delegate;
|
this.evaluator = evaluator;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.data.mapping.model.ParameterValueProvider#getParameterValue(org.springframework.data.mapping.PreferredConstructor.Parameter)
|
* @see org.springframework.data.convert.PropertyValueProvider#getPropertyValue(org.springframework.data.mapping.PersistentProperty)
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> T getParameterValue(Parameter<T> parameter) {
|
public <T> T getPropertyValue(MongoPersistentProperty property) {
|
||||||
|
|
||||||
MappedConstructor.MappedParameter mappedParameter = constructor.getFor(parameter);
|
String expression = property.getSpelExpression();
|
||||||
Object value = mappedParameter.hasSpELExpression() ? delegate.getParameterValue(parameter) : source
|
TypeInformation<?> type = property.getTypeInformation();
|
||||||
.get(mappedParameter.getFieldName());
|
Object value = expression != null ? evaluator.evaluate(expression) : source.get(property.getFieldName());
|
||||||
|
|
||||||
TypeInformation<?> type = mappedParameter.getPropertyTypeInformation();
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (value instanceof DBRef) {
|
if (conversions.hasCustomReadTarget(value.getClass(), type.getType())) {
|
||||||
|
return (T) conversionService.convert(value, type.getType());
|
||||||
|
} else if (value instanceof DBRef) {
|
||||||
return (T) read(type, ((DBRef) value).fetch());
|
return (T) read(type, ((DBRef) value).fetch());
|
||||||
} else if (value instanceof BasicDBList) {
|
} else if (value instanceof BasicDBList) {
|
||||||
return (T) getPotentiallyConvertedSimpleRead(readCollectionOrArray(type, (BasicDBList) value), type.getType());
|
return (T) getPotentiallyConvertedSimpleRead(readCollectionOrArray(type, (BasicDBList) value), type.getType());
|
||||||
|
|||||||
Reference in New Issue
Block a user