Skip to content

Commit aeeac56

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 e9c15eb commit aeeac56

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
@@ -1398,6 +1398,14 @@ public KeyMapper(String key,
13981398
this.currentIndex = 0;
13991399
}
14001400

1401+
String nextToken() {
1402+
return pathParts.get(currentIndex+1);
1403+
}
1404+
1405+
boolean hasNexToken() {
1406+
return pathParts.size() > currentIndex+1;
1407+
}
1408+
14011409
/**
14021410
* Maps the property name while retaining potential positional operator {@literal $}.
14031411
*
@@ -1407,31 +1415,25 @@ public KeyMapper(String key,
14071415
protected String mapPropertyName(MongoPersistentProperty property) {
14081416

14091417
StringBuilder mappedName = new StringBuilder(PropertyToFieldNameConverter.INSTANCE.convert(property));
1418+
if(!hasNexToken()) {
1419+
return mappedName.toString();
1420+
}
14101421

1411-
boolean inspect = iterator.hasNext();
1412-
1413-
while (inspect) {
1414-
1415-
String partial = iterator.next();
1416-
currentIndex++;
1417-
1418-
boolean isPositional = isPositionalParameter(partial) && property.isCollectionLike();
1419-
if (property.isMap() && currentPropertyRoot.equals(partial) && iterator.hasNext()) {
1420-
partial = iterator.next();
1421-
currentIndex++;
1422-
}
1423-
1424-
if (isPositional || property.isMap() && !currentPropertyRoot.equals(partial)) {
1425-
mappedName.append(".").append(partial);
1426-
}
1422+
String nextToken = nextToken();
1423+
if(isPositionalParameter(nextToken)) {
14271424

1428-
inspect = isPositional && iterator.hasNext();
1425+
mappedName.append(".").append(nextToken);
1426+
currentIndex+=2;
1427+
return mappedName.toString();
14291428
}
14301429

1431-
if (currentIndex + 1 < pathParts.size()) {
1432-
currentIndex++;
1433-
currentPropertyRoot = pathParts.get(currentIndex);
1430+
if(property.isMap()) {
1431+
1432+
mappedName.append(".").append(nextToken);
1433+
currentIndex+=2;
1434+
return mappedName.toString();
14341435
}
1436+
currentIndex++;
14351437
return mappedName.toString();
14361438
}
14371439

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

+46
Original file line numberDiff line numberDiff line change
@@ -1309,6 +1309,36 @@ void updateListWithDocuRefOnProperty() {
13091309
assertThat(mappedUpdate).isEqualTo(new org.bson.Document("$set",new org.bson.Document("customers", Arrays.asList("c-name"))));
13101310
}
13111311

1312+
@Test // GH-3921
1313+
void mapNumericKeyInPathHavingComplexMapValyeTypes() {
1314+
1315+
Update update = new Update().set("testInnerData.testMap.1.intValue", "4");
1316+
Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(),
1317+
context.getPersistentEntity(TestData.class));
1318+
1319+
assertThat(mappedUpdate).isEqualTo(new org.bson.Document("$set",new org.bson.Document("testInnerData.testMap.1.intValue","4")));
1320+
}
1321+
1322+
@Test // GH-3921
1323+
void mapNumericKeyInPathNotMatchingExistingProperties() {
1324+
1325+
Update update = new Update().set("testInnerData.imaginaryMap.1.nonExistingProperty", "4");
1326+
Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(),
1327+
context.getPersistentEntity(TestData.class));
1328+
1329+
assertThat(mappedUpdate).isEqualTo(new org.bson.Document("$set",new org.bson.Document("testInnerData.imaginaryMap.1.noExistingProperty","4")));
1330+
}
1331+
1332+
@Test // GH-3921
1333+
void mapNumericKeyInPathPartiallyMatchingExistingProperties() {
1334+
1335+
Update update = new Update().set("testInnerData.testMap.1.nonExistingProperty.2.someValue", "4");
1336+
Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(),
1337+
context.getPersistentEntity(TestData.class));
1338+
1339+
assertThat(mappedUpdate).isEqualTo(new org.bson.Document("$set",new org.bson.Document("testInnerData.testMap.1.nonExistingProperty.2.someValue","4")));
1340+
}
1341+
13121342
static class DomainTypeWrappingConcreteyTypeHavingListOfInterfaceTypeAttributes {
13131343
ListModelWrapper concreteTypeWithListAttributeOfInterfaceType;
13141344
}
@@ -1710,4 +1740,20 @@ static class WithDocumentReference {
17101740
private List<Sample> samples;
17111741
}
17121742

1743+
@Data
1744+
private static class TestData {
1745+
@Id
1746+
private String id;
1747+
private TestInnerData testInnerData;
1748+
}
1749+
1750+
@Data
1751+
private static class TestInnerData {
1752+
private Map<Integer, TestValue> testMap;
1753+
}
1754+
1755+
@Data
1756+
private static class TestValue {
1757+
private int intValue;
1758+
}
17131759
}

0 commit comments

Comments
 (0)