|
37 | 37 | import org.springframework.data.convert.TypeMapper;
|
38 | 38 | import org.springframework.data.mapping.Association;
|
39 | 39 | import org.springframework.data.mapping.AssociationHandler;
|
40 |
| -import org.springframework.data.mapping.PreferredConstructor; |
| 40 | +import org.springframework.data.mapping.PreferredConstructor.Parameter; |
41 | 41 | import org.springframework.data.mapping.PropertyHandler;
|
42 | 42 | import org.springframework.data.mapping.context.MappingContext;
|
43 | 43 | import org.springframework.data.mapping.model.BeanWrapper;
|
@@ -189,60 +189,25 @@ protected <S extends Object> S read(TypeInformation<S> type, DBObject dbo) {
|
189 | 189 |
|
190 | 190 | private <S extends Object> S read(final MongoPersistentEntity<S> entity, final DBObject dbo) {
|
191 | 191 |
|
192 |
| - final StandardEvaluationContext spelCtx = new StandardEvaluationContext(); |
193 |
| - if (null != applicationContext) { |
| 192 | + final StandardEvaluationContext spelCtx = new StandardEvaluationContext(dbo); |
| 193 | + spelCtx.addPropertyAccessor(DBObjectPropertyAccessor.INSTANCE); |
| 194 | + |
| 195 | + if (applicationContext != null) { |
194 | 196 | spelCtx.setBeanResolver(new BeanFactoryResolver(applicationContext));
|
195 | 197 | }
|
196 |
| - if (!(dbo instanceof BasicDBList)) { |
197 |
| - String[] keySet = dbo.keySet().toArray(new String[dbo.keySet().size()]); |
198 |
| - for (String key : keySet) { |
199 |
| - spelCtx.setVariable(key, dbo.get(key)); |
200 |
| - } |
201 |
| - } |
202 |
| - |
203 |
| - final List<String> ctorParamNames = new ArrayList<String>(); |
204 |
| - final MongoPersistentProperty idProperty = entity.getIdProperty(); |
205 |
| - |
206 |
| - ParameterValueProvider provider = new SpELAwareParameterValueProvider(spelExpressionParser, spelCtx) { |
207 |
| - @Override |
208 |
| - @SuppressWarnings("unchecked") |
209 |
| - public <T> T getParameterValue(PreferredConstructor.Parameter<T> parameter) { |
210 |
| - |
211 |
| - if (parameter.getKey() != null) { |
212 |
| - return super.getParameterValue(parameter); |
213 |
| - } |
214 | 198 |
|
215 |
| - String name = parameter.getName(); |
216 |
| - TypeInformation<T> type = parameter.getType(); |
217 |
| - Class<T> rawType = parameter.getRawType(); |
218 |
| - String key = idProperty == null ? name : idProperty.getName().equals(name) ? idProperty.getFieldName() : name; |
219 |
| - Object obj = dbo.get(key); |
220 |
| - |
221 |
| - ctorParamNames.add(name); |
222 |
| - if (obj instanceof DBRef) { |
223 |
| - return read(type, ((DBRef) obj).fetch()); |
224 |
| - } else if (obj instanceof BasicDBList) { |
225 |
| - BasicDBList objAsDbList = (BasicDBList) obj; |
226 |
| - return conversionService.convert(readCollectionOrArray(type, objAsDbList), rawType); |
227 |
| - } else if (obj instanceof DBObject) { |
228 |
| - return read(type, ((DBObject) obj)); |
229 |
| - } else if (null != obj && obj.getClass().isAssignableFrom(rawType)) { |
230 |
| - return (T) obj; |
231 |
| - } else if (null != obj) { |
232 |
| - return conversionService.convert(obj, rawType); |
233 |
| - } |
| 199 | + final MappedConstructor constructor = new MappedConstructor(entity, mappingContext); |
234 | 200 |
|
235 |
| - return null; |
236 |
| - } |
237 |
| - }; |
| 201 | + SpELAwareParameterValueProvider delegate = new SpELAwareParameterValueProvider(spelExpressionParser, spelCtx); |
| 202 | + ParameterValueProvider provider = new DelegatingParameterValueProvider(constructor, dbo, delegate); |
238 | 203 |
|
239 | 204 | final BeanWrapper<MongoPersistentEntity<S>, S> wrapper = BeanWrapper.create(entity, provider, conversionService);
|
240 | 205 |
|
241 | 206 | // Set properties not already set in the constructor
|
242 | 207 | entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
|
243 | 208 | public void doWithPersistentProperty(MongoPersistentProperty prop) {
|
244 | 209 |
|
245 |
| - boolean isConstructorProperty = ctorParamNames.contains(prop.getName()); |
| 210 | + boolean isConstructorProperty = constructor.isConstructorParameter(prop); |
246 | 211 | boolean hasValueForProperty = dbo.containsField(prop.getFieldName());
|
247 | 212 |
|
248 | 213 | if (!hasValueForProperty || isConstructorProperty) {
|
@@ -892,4 +857,55 @@ private Object removeTypeInfoRecursively(Object object) {
|
892 | 857 |
|
893 | 858 | return dbObject;
|
894 | 859 | }
|
| 860 | + |
| 861 | + private class DelegatingParameterValueProvider implements ParameterValueProvider { |
| 862 | + |
| 863 | + private final DBObject source; |
| 864 | + private final ParameterValueProvider delegate; |
| 865 | + private final MappedConstructor constructor; |
| 866 | + |
| 867 | + /** |
| 868 | + * {@link ParameterValueProvider} to delegate source object lookup to a {@link SpELAwareParameterValueProvider} in |
| 869 | + * case a MappCon |
| 870 | + * |
| 871 | + * @param constructor must not be {@literal null}. |
| 872 | + * @param source must not be {@literal null}. |
| 873 | + * @param delegate must not be {@literal null}. |
| 874 | + */ |
| 875 | + public DelegatingParameterValueProvider(MappedConstructor constructor, DBObject source, |
| 876 | + SpELAwareParameterValueProvider delegate) { |
| 877 | + |
| 878 | + Assert.notNull(constructor); |
| 879 | + Assert.notNull(source); |
| 880 | + Assert.notNull(delegate); |
| 881 | + |
| 882 | + this.constructor = constructor; |
| 883 | + this.source = source; |
| 884 | + this.delegate = delegate; |
| 885 | + } |
| 886 | + |
| 887 | + /* |
| 888 | + * (non-Javadoc) |
| 889 | + * @see org.springframework.data.mapping.model.ParameterValueProvider#getParameterValue(org.springframework.data.mapping.PreferredConstructor.Parameter) |
| 890 | + */ |
| 891 | + @SuppressWarnings("unchecked") |
| 892 | + public <T> T getParameterValue(Parameter<T> parameter) { |
| 893 | + |
| 894 | + MappedConstructor.MappedParameter mappedParameter = constructor.getFor(parameter); |
| 895 | + Object value = mappedParameter.hasSpELExpression() ? delegate.getParameterValue(parameter) : source |
| 896 | + .get(mappedParameter.getFieldName()); |
| 897 | + |
| 898 | + TypeInformation<?> type = mappedParameter.getPropertyTypeInformation(); |
| 899 | + |
| 900 | + if (value instanceof DBRef) { |
| 901 | + return (T) read(type, ((DBRef) value).fetch()); |
| 902 | + } else if (value instanceof BasicDBList) { |
| 903 | + return (T) getPotentiallyConvertedSimpleRead(readCollectionOrArray(type, (BasicDBList) value), type.getType()); |
| 904 | + } else if (value instanceof DBObject) { |
| 905 | + return (T) read(type, (DBObject) value); |
| 906 | + } else { |
| 907 | + return (T) getPotentiallyConvertedSimpleRead(value, type.getType()); |
| 908 | + } |
| 909 | + } |
| 910 | + } |
895 | 911 | }
|
0 commit comments