From 05baa851d8c59675412611c67213979a20677e11 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Wed, 8 Aug 2012 18:56:18 +0200 Subject: [PATCH] DATAMONGO-502 - QueryMapper now translates property names into field names. --- .../mongodb/core/convert/QueryMapper.java | 32 +++++++++++++- .../core/convert/QueryMapperUnitTests.java | 42 ++++++++++++++++++- 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index 440ba1702..170b6b104 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -25,6 +25,10 @@ import org.bson.types.ObjectId; import org.springframework.core.convert.ConversionException; import org.springframework.core.convert.ConversionService; import org.springframework.data.mapping.PersistentEntity; +import org.springframework.data.mapping.PropertyPath; +import org.springframework.data.mapping.PropertyReferenceException; +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.util.Assert; @@ -46,6 +50,7 @@ public class QueryMapper { private final ConversionService conversionService; private final MongoConverter converter; + private final MappingContext, MongoPersistentProperty> mappingContext; /** * Creates a new {@link QueryMapper} with the given {@link MongoConverter}. @@ -53,9 +58,12 @@ public class QueryMapper { * @param converter must not be {@literal null}. */ public QueryMapper(MongoConverter converter) { + Assert.notNull(converter); + this.conversionService = converter.getConversionService(); this.converter = converter; + this.mappingContext = converter.getMappingContext(); } /** @@ -72,7 +80,7 @@ public class QueryMapper { for (String key : query.keySet()) { - String newKey = key; + String newKey = determineKey(key, entity); Object value = query.get(key); if (isIdKey(key, entity)) { @@ -111,6 +119,28 @@ public class QueryMapper { return newDbo; } + /** + * Returns the translated key assuming the given one is a propert (path) reference. + * + * @param key the source key + * @param entity the base entity + * @return the translated key + */ + private String determineKey(String key, MongoPersistentEntity entity) { + + if (entity == null) { + return key; + } + + try { + PropertyPath path = PropertyPath.from(key, entity.getTypeInformation()); + PersistentPropertyPath propertyPath = mappingContext.getPersistentPropertyPath(path); + return propertyPath.toDotPath(MongoPersistentProperty.PropertyToFieldNameConverter.INSTANCE); + } catch (PropertyReferenceException e) { + return key; + } + } + /** * Retriggers mapping if the given source is a {@link DBObject} or simply invokes the * diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index c1c294596..ae7cf0ebd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -17,9 +17,9 @@ package org.springframework.data.mongodb.core.convert; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; +import static org.springframework.data.mongodb.core.DBObjectUtils.*; import static org.springframework.data.mongodb.core.query.Criteria.*; import static org.springframework.data.mongodb.core.query.Query.*; -import static org.springframework.data.mongodb.core.DBObjectUtils.*; import java.math.BigInteger; import java.util.ArrayList; @@ -35,6 +35,7 @@ import org.mockito.runners.MockitoJUnitRunner; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.core.Person; +import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.query.BasicQuery; @@ -253,6 +254,39 @@ public class QueryMapperUnitTests { assertThat(criterias.get("foo"), is(nullValue())); } + @Test + public void translatesPropertyReferenceCorrectly() { + + Query query = query(where("field").is(new CustomizedField())); + DBObject result = mapper + .getMappedObject(query.getQueryObject(), context.getPersistentEntity(CustomizedField.class)); + + assertThat(result.containsField("foo"), is(true)); + assertThat(result.keySet().size(), is(1)); + } + + @Test + public void translatesNestedPropertyReferenceCorrectly() { + + Query query = query(where("field.field").is(new CustomizedField())); + DBObject result = mapper + .getMappedObject(query.getQueryObject(), context.getPersistentEntity(CustomizedField.class)); + + assertThat(result.containsField("foo.foo"), is(true)); + assertThat(result.keySet().size(), is(1)); + } + + @Test + public void returnsOriginalKeyIfNoPropertyReference() { + + Query query = query(where("bar").is(new CustomizedField())); + DBObject result = mapper + .getMappedObject(query.getQueryObject(), context.getPersistentEntity(CustomizedField.class)); + + assertThat(result.containsField("bar"), is(true)); + assertThat(result.keySet().size(), is(1)); + } + class IdWrapper { Object id; } @@ -283,4 +317,10 @@ public class QueryMapperUnitTests { String id; List publishers = new ArrayList(); } + + class CustomizedField { + + @Field("foo") + CustomizedField field; + } }