Skip to content

Commit 50a1212

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 998bd1f commit 50a1212

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

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1411,6 +1411,14 @@ public KeyMapper(String key,
14111411
this.currentIndex = 0;
14121412
}
14131413

1414+
String nextToken() {
1415+
return pathParts.get(currentIndex+1);
1416+
}
1417+
1418+
boolean hasNexToken() {
1419+
return pathParts.size() > currentIndex+1;
1420+
}
1421+
14141422
/**
14151423
* Maps the property name while retaining potential positional operator {@literal $}.
14161424
*
@@ -1420,31 +1428,25 @@ public KeyMapper(String key,
14201428
protected String mapPropertyName(MongoPersistentProperty property) {
14211429

14221430
StringBuilder mappedName = new StringBuilder(PropertyToFieldNameConverter.INSTANCE.convert(property));
1431+
if(!hasNexToken()) {
1432+
return mappedName.toString();
1433+
}
14231434

1424-
boolean inspect = iterator.hasNext();
1425-
1426-
while (inspect) {
1427-
1428-
String partial = iterator.next();
1429-
currentIndex++;
1430-
1431-
boolean isPositional = isPositionalParameter(partial) && property.isCollectionLike();
1432-
if (property.isMap() && currentPropertyRoot.equals(partial) && iterator.hasNext()) {
1433-
partial = iterator.next();
1434-
currentIndex++;
1435-
}
1436-
1437-
if (isPositional || property.isMap() && !currentPropertyRoot.equals(partial)) {
1438-
mappedName.append(".").append(partial);
1439-
}
1435+
String nextToken = nextToken();
1436+
if(isPositionalParameter(nextToken)) {
14401437

1441-
inspect = isPositional && iterator.hasNext();
1438+
mappedName.append(".").append(nextToken);
1439+
currentIndex+=2;
1440+
return mappedName.toString();
14421441
}
14431442

1444-
if (currentIndex + 1 < pathParts.size()) {
1445-
currentIndex++;
1446-
currentPropertyRoot = pathParts.get(currentIndex);
1443+
if(property.isMap()) {
1444+
1445+
mappedName.append(".").append(nextToken);
1446+
currentIndex+=2;
1447+
return mappedName.toString();
14471448
}
1449+
currentIndex++;
14481450
return mappedName.toString();
14491451
}
14501452

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

Lines changed: 46 additions & 0 deletions
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)