diff --git a/pom.xml b/pom.xml
index 74b7a38a74..50e5a08be3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-mongodb-parent
- 1.8.0.BUILD-SNAPSHOT
+ 1.8.0.DATAMONGO-1269-SNAPSHOT
pom
Spring Data MongoDB
diff --git a/spring-data-mongodb-cross-store/pom.xml b/spring-data-mongodb-cross-store/pom.xml
index 7d18f752fc..a7491f916d 100644
--- a/spring-data-mongodb-cross-store/pom.xml
+++ b/spring-data-mongodb-cross-store/pom.xml
@@ -6,7 +6,7 @@
org.springframework.data
spring-data-mongodb-parent
- 1.8.0.BUILD-SNAPSHOT
+ 1.8.0.DATAMONGO-1269-SNAPSHOT
../pom.xml
@@ -48,7 +48,7 @@
org.springframework.data
spring-data-mongodb
- 1.8.0.BUILD-SNAPSHOT
+ 1.8.0.DATAMONGO-1269-SNAPSHOT
diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml
index 13c0985a6a..ec3d3361fa 100644
--- a/spring-data-mongodb-distribution/pom.xml
+++ b/spring-data-mongodb-distribution/pom.xml
@@ -13,7 +13,7 @@
org.springframework.data
spring-data-mongodb-parent
- 1.8.0.BUILD-SNAPSHOT
+ 1.8.0.DATAMONGO-1269-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb-log4j/pom.xml b/spring-data-mongodb-log4j/pom.xml
index 64d6f7864a..570680c088 100644
--- a/spring-data-mongodb-log4j/pom.xml
+++ b/spring-data-mongodb-log4j/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-mongodb-parent
- 1.8.0.BUILD-SNAPSHOT
+ 1.8.0.DATAMONGO-1269-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml
index 819112059b..b24bb3e1dc 100644
--- a/spring-data-mongodb/pom.xml
+++ b/spring-data-mongodb/pom.xml
@@ -11,7 +11,7 @@
org.springframework.data
spring-data-mongodb-parent
- 1.8.0.BUILD-SNAPSHOT
+ 1.8.0.DATAMONGO-1269-SNAPSHOT
../pom.xml
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 bd5a5ccfec..5ba6ca37cd 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
@@ -867,7 +867,7 @@ private PersistentPropertyPath getPath(String pathExpre
* @return
*/
protected Converter getPropertyConverter() {
- return PropertyToFieldNameConverter.INSTANCE;
+ return new PositionParameterRetainingPropertyKeyConverter(name);
}
/**
@@ -881,6 +881,24 @@ protected Converter getAssociationConverter() {
return new AssociationConverter(getAssociation());
}
+ /**
+ * @author Christoph Strobl
+ * @since 1.8
+ */
+ static class PositionParameterRetainingPropertyKeyConverter implements Converter {
+
+ private final KeyMapper keyMapper;
+
+ PositionParameterRetainingPropertyKeyConverter(String rawKey) {
+ this.keyMapper = new KeyMapper(rawKey);
+ }
+
+ @Override
+ public String convert(MongoPersistentProperty source) {
+ return keyMapper.mapPropertyName(source);
+ }
+ }
+
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.QueryMapper.Field#getTypeHint()
@@ -901,6 +919,63 @@ public TypeInformation> getTypeHint() {
return NESTED_DOCUMENT;
}
+
+ /**
+ * @author Christoph Strobl
+ * @since 1.8
+ */
+ static class KeyMapper {
+
+ Iterator iterator;
+
+ public KeyMapper(String key) {
+
+ this.iterator = Arrays.asList(key.split("\\.")).iterator();
+ this.iterator.next();
+ }
+
+ /**
+ * Maps the property name while retaining potential positional operator {@literal $}.
+ *
+ * @param property
+ * @return
+ */
+ protected String mapPropertyName(MongoPersistentProperty property) {
+
+ String mappedName = PropertyToFieldNameConverter.INSTANCE.convert(property);
+
+ boolean inspect = iterator.hasNext();
+ while (inspect) {
+
+ String partial = iterator.next();
+
+ boolean isPositional = (isPositionalParameter(partial) && (property.isMap() || property.isCollectionLike() || property
+ .isArray()));
+ if (isPositional) {
+ mappedName += "." + partial;
+ }
+
+ inspect = isPositional && iterator.hasNext();
+ }
+
+ return mappedName;
+ }
+
+ boolean isPositionalParameter(String partial) {
+
+ if (partial.equals("$")) {
+ return true;
+ }
+
+ try {
+ Long.valueOf(partial);
+ return true;
+ } catch (NumberFormatException e) {
+ return false;
+ }
+ }
+ }
+
}
/**
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java
index 091a600d7a..ea60fbb7df 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java
@@ -15,8 +15,6 @@
*/
package org.springframework.data.mongodb.core.convert;
-import java.util.Arrays;
-import java.util.Iterator;
import java.util.Map.Entry;
import org.springframework.core.convert.converter.Converter;
@@ -24,13 +22,11 @@
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
-import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty.PropertyToFieldNameConverter;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update.Modifier;
import org.springframework.data.mongodb.core.query.Update.Modifiers;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
-import org.springframework.util.Assert;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
@@ -213,7 +209,7 @@ public String getMappedKey() {
*/
@Override
protected Converter getPropertyConverter() {
- return new UpdatePropertyConverter(key);
+ return new PositionParameterRetainingPropertyKeyConverter(key);
}
/*
@@ -225,99 +221,6 @@ protected Converter getAssociationConverter() {
return new UpdateAssociationConverter(getAssociation(), key);
}
- /**
- * Special mapper handling positional parameter {@literal $} within property names.
- *
- * @author Christoph Strobl
- * @since 1.7
- */
- private static class UpdateKeyMapper {
-
- private final Iterator iterator;
-
- protected UpdateKeyMapper(String rawKey) {
-
- Assert.hasText(rawKey, "Key must not be null or empty!");
-
- this.iterator = Arrays.asList(rawKey.split("\\.")).iterator();
- this.iterator.next();
- }
-
- /**
- * Maps the property name while retaining potential positional operator {@literal $}.
- *
- * @param property
- * @return
- */
- protected String mapPropertyName(MongoPersistentProperty property) {
-
- String mappedName = PropertyToFieldNameConverter.INSTANCE.convert(property);
-
- boolean inspect = iterator.hasNext();
- while (inspect) {
-
- String partial = iterator.next();
-
- boolean isPositional = isPositionalParameter(partial);
- if (isPositional) {
- mappedName += "." + partial;
- }
-
- inspect = isPositional && iterator.hasNext();
- }
-
- return mappedName;
- }
-
- boolean isPositionalParameter(String partial) {
-
- if (partial.equals("$")) {
- return true;
- }
-
- try {
- Long.valueOf(partial);
- return true;
- } catch (NumberFormatException e) {
- return false;
- }
- }
-
- }
-
- /**
- * Special {@link Converter} for {@link MongoPersistentProperty} instances that will concatenate the {@literal $}
- * contained in the source update key.
- *
- * @author Oliver Gierke
- * @author Christoph Strobl
- */
- private static class UpdatePropertyConverter implements Converter {
-
- private final UpdateKeyMapper mapper;
-
- /**
- * Creates a new {@link UpdatePropertyConverter} with the given update key.
- *
- * @param updateKey must not be {@literal null} or empty.
- */
- public UpdatePropertyConverter(String updateKey) {
-
- Assert.hasText(updateKey, "Update key must not be null or empty!");
-
- this.mapper = new UpdateKeyMapper(updateKey);
- }
-
- /*
- * (non-Javadoc)
- * @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
- */
- @Override
- public String convert(MongoPersistentProperty property) {
- return mapper.mapPropertyName(property);
- }
- }
-
/**
* {@link Converter} retaining positional parameter {@literal $} for {@link Association}s.
*
@@ -325,7 +228,7 @@ public String convert(MongoPersistentProperty property) {
*/
protected static class UpdateAssociationConverter extends AssociationConverter {
- private final UpdateKeyMapper mapper;
+ private final KeyMapper mapper;
/**
* Creates a new {@link AssociationConverter} for the given {@link Association}.
@@ -335,7 +238,7 @@ protected static class UpdateAssociationConverter extends AssociationConverter {
public UpdateAssociationConverter(Association association, String key) {
super(association);
- this.mapper = new UpdateKeyMapper(key);
+ this.mapper = new KeyMapper(key);
}
/*
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 b510d7145e..8cf5852b76 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
@@ -790,6 +790,34 @@ public void intersectsShouldUseGeoJsonRepresentationCorrectly() {
assertThat(dbo, isBsonObject().containing("geoJsonPoint.$geoIntersects.$geometry.coordinates"));
}
+ /**
+ * @see DATAMONGO-1269
+ */
+ @Test
+ public void mappingShouldRetainNumericMapKey() {
+
+ Query query = query(where("map.1.stringProperty").is("ba'alzamon"));
+
+ DBObject dbo = mapper.getMappedObject(query.getQueryObject(),
+ context.getPersistentEntity(EntityWithComplexValueTypeMap.class));
+
+ assertThat(dbo.containsField("map.1.stringProperty"), is(true));
+ }
+
+ /**
+ * @see DATAMONGO-1269
+ */
+ @Test
+ public void mappingShouldRetainNumericPositionInList() {
+
+ Query query = query(where("list.1.stringProperty").is("ba'alzamon"));
+
+ DBObject dbo = mapper.getMappedObject(query.getQueryObject(),
+ context.getPersistentEntity(EntityWithComplexValueTypeList.class));
+
+ assertThat(dbo.containsField("list.1.stringProperty"), is(true));
+ }
+
@Document
public class Foo {
@Id private ObjectId id;
@@ -890,4 +918,18 @@ static class ClassWithGeoTypes {
GeoJsonPoint geoJsonPoint;
@Field("geoJsonPointWithNameViaFieldAnnotation") GeoJsonPoint namedGeoJsonPoint;
}
+
+ static class SimpeEntityWithoutId {
+
+ String stringProperty;
+ Integer integerProperty;
+ }
+
+ static class EntityWithComplexValueTypeMap {
+ Map map;
+ }
+
+ static class EntityWithComplexValueTypeList {
+ List list;
+ }
}