Skip to content

Commit f71b38b

Browse files
committed
DATAMONGO-1768 - Polishing.
Extend javadocs. Make methods static/reorder methods where possible. Formatting. Original pull request: #496.
1 parent c4af78d commit f71b38b

File tree

2 files changed

+103
-93
lines changed

2 files changed

+103
-93
lines changed

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

Lines changed: 99 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,25 @@
5050
import com.mongodb.DBObject;
5151

5252
/**
53+
* Mapper from {@link Example} to a query {@link DBObject}.
54+
*
5355
* @author Christoph Strobl
5456
* @author Mark Paluch
5557
* @since 1.8
58+
* @see Example
59+
* @see org.springframework.data.domain.ExampleMatcher
5660
*/
5761
public class MongoExampleMapper {
5862

5963
private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
6064
private final MongoConverter converter;
6165
private final Map<StringMatcher, Type> stringMatcherPartMapping = new HashMap<StringMatcher, Type>();
6266

67+
/**
68+
* Create a new {@link MongoTypeMapper} given {@link MongoConverter}.
69+
*
70+
* @param converter must not be {@literal null}.
71+
*/
6372
public MongoExampleMapper(MongoConverter converter) {
6473

6574
this.converter = converter;
@@ -101,8 +110,10 @@ public DBObject getMappedExample(Example<?> example, MongoPersistentEntity<?> en
101110

102111
DBObject reference = (DBObject) converter.convertToMongoType(example.getProbe());
103112

104-
if (entity.hasIdProperty() && ClassUtils.isAssignable(entity.getType(), example.getProbeType())) {
105-
if (entity.getIdentifierAccessor(example.getProbe()).getIdentifier() == null) {reference.removeField(entity.getIdProperty().getFieldName());}
113+
if (entity.hasIdProperty() && ClassUtils.isAssignable(entity.getType(), example.getProbeType())) {
114+
if (entity.getIdentifierAccessor(example.getProbe()).getIdentifier() == null) {
115+
reference.removeField(entity.getIdProperty().getFieldName());
116+
}
106117
}
107118

108119
ExampleMatcherAccessor matcherAccessor = new ExampleMatcherAccessor(example.getMatcher());
@@ -116,28 +127,63 @@ public DBObject getMappedExample(Example<?> example, MongoPersistentEntity<?> en
116127
return updateTypeRestrictions(result, example);
117128
}
118129

119-
private static DBObject orConcatenate(DBObject source) {
120-
121-
List<DBObject> foo = new ArrayList<DBObject>(source.keySet().size());
130+
private void applyPropertySpecs(String path, DBObject source, Class<?> probeType,
131+
ExampleMatcherAccessor exampleSpecAccessor) {
122132

123-
for (String key : source.keySet()) {
124-
foo.add(new BasicDBObject(key, source.get(key)));
133+
if (!(source instanceof BasicDBObject)) {
134+
return;
125135
}
126136

127-
return new BasicDBObject("$or", foo);
128-
}
137+
Iterator<Map.Entry<String, Object>> iter = ((BasicDBObject) source).entrySet().iterator();
129138

130-
private Set<Class<?>> getTypesToMatch(Example<?> example) {
139+
while (iter.hasNext()) {
131140

132-
Set<Class<?>> types = new HashSet<Class<?>>();
141+
Map.Entry<String, Object> entry = iter.next();
142+
String propertyPath = StringUtils.hasText(path) ? path + "." + entry.getKey() : entry.getKey();
143+
String mappedPropertyPath = getMappedPropertyPath(propertyPath, probeType);
133144

134-
for (TypeInformation<?> reference : mappingContext.getManagedTypes()) {
135-
if (example.getProbeType().isAssignableFrom(reference.getType())) {
136-
types.add(reference.getType());
145+
if (isEmptyIdProperty(entry)) {
146+
iter.remove();
147+
continue;
137148
}
138-
}
139149

140-
return types;
150+
if (exampleSpecAccessor.isIgnoredPath(propertyPath) || exampleSpecAccessor.isIgnoredPath(mappedPropertyPath)) {
151+
iter.remove();
152+
continue;
153+
}
154+
155+
StringMatcher stringMatcher = exampleSpecAccessor.getDefaultStringMatcher();
156+
Object value = entry.getValue();
157+
boolean ignoreCase = exampleSpecAccessor.isIgnoreCaseEnabled();
158+
159+
if (exampleSpecAccessor.hasPropertySpecifiers()) {
160+
161+
mappedPropertyPath = exampleSpecAccessor.hasPropertySpecifier(propertyPath) ? propertyPath
162+
: getMappedPropertyPath(propertyPath, probeType);
163+
164+
stringMatcher = exampleSpecAccessor.getStringMatcherForPath(mappedPropertyPath);
165+
ignoreCase = exampleSpecAccessor.isIgnoreCaseForPath(mappedPropertyPath);
166+
}
167+
168+
// TODO: should a PropertySpecifier outrule the later on string matching?
169+
if (exampleSpecAccessor.hasPropertySpecifier(mappedPropertyPath)) {
170+
171+
PropertyValueTransformer valueTransformer = exampleSpecAccessor.getValueTransformerForPath(mappedPropertyPath);
172+
value = valueTransformer.convert(value);
173+
if (value == null) {
174+
iter.remove();
175+
continue;
176+
}
177+
178+
entry.setValue(value);
179+
}
180+
181+
if (entry.getValue() instanceof String) {
182+
applyStringMatcher(entry, stringMatcher, ignoreCase);
183+
} else if (entry.getValue() instanceof BasicDBObject) {
184+
applyPropertySpecs(propertyPath, (BasicDBObject) entry.getValue(), probeType, exampleSpecAccessor);
185+
}
186+
}
141187
}
142188

143189
private String getMappedPropertyPath(String path, Class<?> probeType) {
@@ -171,6 +217,7 @@ public void doWithPersistentProperty(MongoPersistentProperty property) {
171217
if (stack.isEmpty()) {
172218
return "";
173219
}
220+
174221
prop = stack.pop();
175222
}
176223

@@ -184,69 +231,57 @@ public void doWithPersistentProperty(MongoPersistentProperty property) {
184231
}
185232

186233
return StringUtils.collectionToDelimitedString(resultParts, ".");
187-
188234
}
189235

190-
private void applyPropertySpecs(String path, DBObject source, Class<?> probeType,
191-
ExampleMatcherAccessor exampleSpecAccessor) {
192-
193-
if (!(source instanceof BasicDBObject)) {
194-
return;
195-
}
196-
197-
Iterator<Map.Entry<String, Object>> iter = ((BasicDBObject) source).entrySet().iterator();
236+
private DBObject updateTypeRestrictions(DBObject query, Example example) {
198237

199-
while (iter.hasNext()) {
238+
DBObject result = new BasicDBObject();
200239

201-
Map.Entry<String, Object> entry = iter.next();
202-
String propertyPath = StringUtils.hasText(path) ? path + "." + entry.getKey() : entry.getKey();
203-
String mappedPropertyPath = getMappedPropertyPath(propertyPath, probeType);
240+
if (isTypeRestricting(example.getMatcher())) {
204241

205-
if (isEmptyIdProperty(entry)) {
206-
iter.remove();
207-
continue;
208-
}
242+
result.putAll(query);
243+
this.converter.getTypeMapper().writeTypeRestrictions(result, getTypesToMatch(example));
244+
return result;
245+
}
209246

210-
if (exampleSpecAccessor.isIgnoredPath(propertyPath) || exampleSpecAccessor.isIgnoredPath(mappedPropertyPath)) {
211-
iter.remove();
212-
continue;
247+
for (String key : query.keySet()) {
248+
if (!this.converter.getTypeMapper().isTypeKey(key)) {
249+
result.put(key, query.get(key));
213250
}
251+
}
214252

215-
StringMatcher stringMatcher = exampleSpecAccessor.getDefaultStringMatcher();
216-
Object value = entry.getValue();
217-
boolean ignoreCase = exampleSpecAccessor.isIgnoreCaseEnabled();
253+
return result;
254+
}
218255

219-
if (exampleSpecAccessor.hasPropertySpecifiers()) {
256+
private boolean isTypeRestricting(ExampleMatcher matcher) {
220257

221-
mappedPropertyPath = exampleSpecAccessor.hasPropertySpecifier(propertyPath) ? propertyPath
222-
: getMappedPropertyPath(propertyPath, probeType);
258+
if (matcher.getIgnoredPaths().isEmpty()) {
259+
return true;
260+
}
223261

224-
stringMatcher = exampleSpecAccessor.getStringMatcherForPath(mappedPropertyPath);
225-
ignoreCase = exampleSpecAccessor.isIgnoreCaseForPath(mappedPropertyPath);
262+
for (String path : matcher.getIgnoredPaths()) {
263+
if (this.converter.getTypeMapper().isTypeKey(path)) {
264+
return false;
226265
}
266+
}
227267

228-
// TODO: should a PropertySpecifier outrule the later on string matching?
229-
if (exampleSpecAccessor.hasPropertySpecifier(mappedPropertyPath)) {
268+
return true;
269+
}
230270

231-
PropertyValueTransformer valueTransformer = exampleSpecAccessor.getValueTransformerForPath(mappedPropertyPath);
232-
value = valueTransformer.convert(value);
233-
if (value == null) {
234-
iter.remove();
235-
continue;
236-
}
271+
private Set<Class<?>> getTypesToMatch(Example<?> example) {
237272

238-
entry.setValue(value);
239-
}
273+
Set<Class<?>> types = new HashSet<Class<?>>();
240274

241-
if (entry.getValue() instanceof String) {
242-
applyStringMatcher(entry, stringMatcher, ignoreCase);
243-
} else if (entry.getValue() instanceof BasicDBObject) {
244-
applyPropertySpecs(propertyPath, (BasicDBObject) entry.getValue(), probeType, exampleSpecAccessor);
275+
for (TypeInformation<?> reference : mappingContext.getManagedTypes()) {
276+
if (example.getProbeType().isAssignableFrom(reference.getType())) {
277+
types.add(reference.getType());
245278
}
246279
}
280+
281+
return types;
247282
}
248283

249-
private boolean isEmptyIdProperty(Entry<String, Object> entry) {
284+
private static boolean isEmptyIdProperty(Entry<String, Object> entry) {
250285
return entry.getKey().equals("_id") && entry.getValue() == null;
251286
}
252287

@@ -273,38 +308,14 @@ private void applyStringMatcher(Map.Entry<String, Object> entry, StringMatcher s
273308
}
274309
}
275310

276-
private DBObject updateTypeRestrictions(DBObject query, Example example) {
277-
278-
DBObject result = new BasicDBObject();
279-
280-
if (isTypeRestricting(example.getMatcher())) {
281-
282-
result.putAll(query);
283-
this.converter.getTypeMapper().writeTypeRestrictions(result, getTypesToMatch(example));
284-
return result;
285-
}
286-
287-
for (String key : query.keySet()) {
288-
if (!this.converter.getTypeMapper().isTypeKey(key)) {
289-
result.put(key, query.get(key));
290-
}
291-
}
292-
293-
return result;
294-
}
295-
296-
private boolean isTypeRestricting(ExampleMatcher matcher) {
311+
private static DBObject orConcatenate(DBObject source) {
297312

298-
if (matcher.getIgnoredPaths().isEmpty()) {
299-
return true;
300-
}
313+
List<DBObject> or = new ArrayList<DBObject>(source.keySet().size());
301314

302-
for (String path : matcher.getIgnoredPaths()) {
303-
if (this.converter.getTypeMapper().isTypeKey(path)) {
304-
return false;
305-
}
315+
for (String key : source.keySet()) {
316+
or.add(new BasicDBObject(key, source.get(key)));
306317
}
307318

308-
return true;
319+
return new BasicDBObject("$or", or);
309320
}
310321
}

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ public void exampleShouldBeMappedWhenContainingDBRef() {
289289
DBObject dbo = mapper.getMappedExample(of(probe), context.getPersistentEntity(WithDBRef.class));
290290
com.mongodb.DBRef reference = getTypedValue(dbo, "referenceDocument", com.mongodb.DBRef.class);
291291

292-
assertThat(reference.getId(), Is.<Object>is("200"));
292+
assertThat(reference.getId(), Is.<Object> is("200"));
293293
assertThat(reference.getCollectionName(), is("refDoc"));
294294
}
295295

@@ -312,8 +312,8 @@ public void exampleShouldBeMappedCorrectlyWhenContainingLegacyPoint() {
312312

313313
DBObject dbo = mapper.getMappedExample(of(probe), context.getPersistentEntity(WithDBRef.class));
314314

315-
assertThat(dbo.get("legacyPoint.x"), Is.<Object>is(10D));
316-
assertThat(dbo.get("legacyPoint.y"), Is.<Object>is(20D));
315+
assertThat(dbo.get("legacyPoint.x"), Is.<Object> is(10D));
316+
assertThat(dbo.get("legacyPoint.y"), Is.<Object> is(20D));
317317
}
318318

319319
@Test // DATAMONGO-1245
@@ -434,8 +434,7 @@ public void allowIgnoringTypeRestrictionBySettingUpTypeKeyAsAnIgnoredPath() {
434434
probe.flatDoc = new FlatDocument();
435435
probe.flatDoc.stringValue = "conflux";
436436

437-
DBObject dbo = mapper
438-
.getMappedExample(Example.of(probe, ExampleMatcher.matching().withIgnorePaths("_class")));
437+
DBObject dbo = mapper.getMappedExample(Example.of(probe, ExampleMatcher.matching().withIgnorePaths("_class")));
439438

440439
assertThat(dbo, isBsonObject().notContaining("_class"));
441440
}

0 commit comments

Comments
 (0)