Skip to content

Commit f00e8ed

Browse files
christophstroblmp911de
authored andcommitted
Use index instead of iterator to map position and map keys for updates.
This commit removes usage of the iterator and replaces map key and positional parameter mappings with an index based token lookup. Closes #3921 Original pull request: #3930.
1 parent 34a35bd commit f00e8ed

File tree

2 files changed

+68
-20
lines changed

2 files changed

+68
-20
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java

+22-20
Original file line numberDiff line numberDiff line change
@@ -1388,6 +1388,14 @@ public KeyMapper(String key,
13881388
this.currentIndex = 0;
13891389
}
13901390

1391+
String nextToken() {
1392+
return pathParts.get(currentIndex+1);
1393+
}
1394+
1395+
boolean hasNexToken() {
1396+
return pathParts.size() > currentIndex+1;
1397+
}
1398+
13911399
/**
13921400
* Maps the property name while retaining potential positional operator {@literal $}.
13931401
*
@@ -1397,31 +1405,25 @@ public KeyMapper(String key,
13971405
protected String mapPropertyName(MongoPersistentProperty property) {
13981406

13991407
StringBuilder mappedName = new StringBuilder(PropertyToFieldNameConverter.INSTANCE.convert(property));
1408+
if(!hasNexToken()) {
1409+
return mappedName.toString();
1410+
}
14001411

1401-
boolean inspect = iterator.hasNext();
1402-
1403-
while (inspect) {
1404-
1405-
String partial = iterator.next();
1406-
currentIndex++;
1407-
1408-
boolean isPositional = isPositionalParameter(partial) && property.isCollectionLike() ;
1409-
if(property.isMap() && currentPropertyRoot.equals(partial) && iterator.hasNext()){
1410-
partial = iterator.next();
1411-
currentIndex++;
1412-
}
1413-
1414-
if (isPositional || property.isMap() && !currentPropertyRoot.equals(partial)) {
1415-
mappedName.append(".").append(partial);
1416-
}
1412+
String nextToken = nextToken();
1413+
if(isPositionalParameter(nextToken)) {
14171414

1418-
inspect = isPositional && iterator.hasNext();
1415+
mappedName.append(".").append(nextToken);
1416+
currentIndex+=2;
1417+
return mappedName.toString();
14191418
}
14201419

1421-
if(currentIndex + 1 < pathParts.size()) {
1422-
currentIndex++;
1423-
currentPropertyRoot = pathParts.get(currentIndex);
1420+
if(property.isMap()) {
1421+
1422+
mappedName.append(".").append(nextToken);
1423+
currentIndex+=2;
1424+
return mappedName.toString();
14241425
}
1426+
currentIndex++;
14251427
return mappedName.toString();
14261428
}
14271429

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java

+46
Original file line numberDiff line numberDiff line change
@@ -1251,6 +1251,36 @@ void multipleKeysStartingWithANumberInNestedPath() {
12511251
assertThat(mappedUpdate).isEqualTo("{\"$set\": {\"intKeyedMap.1a.map.0b\": \"testing\"}}");
12521252
}
12531253

1254+
@Test // GH-3921
1255+
void mapNumericKeyInPathHavingComplexMapValyeTypes() {
1256+
1257+
Update update = new Update().set("testInnerData.testMap.1.intValue", "4");
1258+
Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(),
1259+
context.getPersistentEntity(TestData.class));
1260+
1261+
assertThat(mappedUpdate).isEqualTo(new org.bson.Document("$set",new org.bson.Document("testInnerData.testMap.1.intValue","4")));
1262+
}
1263+
1264+
@Test // GH-3921
1265+
void mapNumericKeyInPathNotMatchingExistingProperties() {
1266+
1267+
Update update = new Update().set("testInnerData.imaginaryMap.1.nonExistingProperty", "4");
1268+
Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(),
1269+
context.getPersistentEntity(TestData.class));
1270+
1271+
assertThat(mappedUpdate).isEqualTo(new org.bson.Document("$set",new org.bson.Document("testInnerData.imaginaryMap.1.noExistingProperty","4")));
1272+
}
1273+
1274+
@Test // GH-3921
1275+
void mapNumericKeyInPathPartiallyMatchingExistingProperties() {
1276+
1277+
Update update = new Update().set("testInnerData.testMap.1.nonExistingProperty.2.someValue", "4");
1278+
Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(),
1279+
context.getPersistentEntity(TestData.class));
1280+
1281+
assertThat(mappedUpdate).isEqualTo(new org.bson.Document("$set",new org.bson.Document("testInnerData.testMap.1.nonExistingProperty.2.someValue","4")));
1282+
}
1283+
12541284
static class DomainTypeWrappingConcreteyTypeHavingListOfInterfaceTypeAttributes {
12551285
ListModelWrapper concreteTypeWithListAttributeOfInterfaceType;
12561286
}
@@ -1621,4 +1651,20 @@ static class EntityWithNestedMap {
16211651
Map<String, Map<String, Map<String, Object>>> levelOne;
16221652
}
16231653

1654+
@Data
1655+
private static class TestData {
1656+
@Id
1657+
private String id;
1658+
private TestInnerData testInnerData;
1659+
}
1660+
1661+
@Data
1662+
private static class TestInnerData {
1663+
private Map<Integer, TestValue> testMap;
1664+
}
1665+
1666+
@Data
1667+
private static class TestValue {
1668+
private int intValue;
1669+
}
16241670
}

0 commit comments

Comments
 (0)