Skip to content

Commit 826d00a

Browse files
committed
DATAMONGO-1609 - Hacking.
1 parent ac3f7db commit 826d00a

22 files changed

+471
-473
lines changed

pom.xml

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
<springdata.commons>2.0.0.BUILD-SNAPSHOT</springdata.commons>
3232
<mongo>3.2.2</mongo>
3333
<mongo.reactivestreams>1.2.0</mongo.reactivestreams>
34+
<mockito>2.2.17</mockito>
3435
</properties>
3536

3637
<developers>

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

+102-115
Large diffs are not rendered by default.

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

+20-65
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.util.List;
2525
import java.util.Locale;
2626
import java.util.Map;
27+
import java.util.Optional;
2728
import java.util.Set;
2829
import java.util.concurrent.ConcurrentHashMap;
2930

@@ -43,7 +44,6 @@
4344
import org.springframework.data.convert.WritingConverter;
4445
import org.springframework.data.mapping.model.SimpleTypeHolder;
4546
import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes;
46-
import org.springframework.data.util.CacheValue;
4747
import org.springframework.util.Assert;
4848

4949
/**
@@ -71,9 +71,9 @@ public class CustomConversions {
7171

7272
private final List<Object> converters;
7373

74-
private final Map<ConvertiblePair, CacheValue<Class<?>>> customReadTargetTypes;
75-
private final Map<ConvertiblePair, CacheValue<Class<?>>> customWriteTargetTypes;
76-
private final Map<Class<?>, CacheValue<Class<?>>> rawWriteTargetTypes;
74+
private final Map<ConvertiblePair, Optional<Class<?>>> customReadTargetTypes;
75+
private final Map<ConvertiblePair, Optional<Class<?>>> customWriteTargetTypes;
76+
private final Map<Class<?>, Optional<Class<?>>> rawWriteTargetTypes;
7777

7878
/**
7979
* Creates an empty {@link CustomConversions} object.
@@ -91,12 +91,12 @@ public CustomConversions(List<?> converters) {
9191

9292
Assert.notNull(converters, "List of converters must not be null!");
9393

94-
this.readingPairs = new LinkedHashSet<ConvertiblePair>();
95-
this.writingPairs = new LinkedHashSet<ConvertiblePair>();
96-
this.customSimpleTypes = new HashSet<Class<?>>();
97-
this.customReadTargetTypes = new ConcurrentHashMap<ConvertiblePair, CacheValue<Class<?>>>();
98-
this.customWriteTargetTypes = new ConcurrentHashMap<ConvertiblePair, CacheValue<Class<?>>>();
99-
this.rawWriteTargetTypes = new ConcurrentHashMap<Class<?>, CacheValue<Class<?>>>();
94+
this.readingPairs = new LinkedHashSet<>();
95+
this.writingPairs = new LinkedHashSet<>();
96+
this.customSimpleTypes = new HashSet<>();
97+
this.customReadTargetTypes = new ConcurrentHashMap<>();
98+
this.customWriteTargetTypes = new ConcurrentHashMap<>();
99+
this.rawWriteTargetTypes = new ConcurrentHashMap<>();
100100

101101
List<Object> toRegister = new ArrayList<Object>();
102102

@@ -241,13 +241,8 @@ private void register(ConverterRegistration converterRegistration) {
241241
*/
242242
public Class<?> getCustomWriteTarget(final Class<?> sourceType) {
243243

244-
return getOrCreateAndCache(sourceType, rawWriteTargetTypes, new Producer() {
245-
246-
@Override
247-
public Class<?> get() {
248-
return getCustomTarget(sourceType, null, writingPairs);
249-
}
250-
});
244+
return rawWriteTargetTypes.computeIfAbsent(sourceType, it -> getCustomTarget(sourceType, null, writingPairs))
245+
.orElse(null);
251246
}
252247

253248
/**
@@ -265,14 +260,8 @@ public Class<?> getCustomWriteTarget(final Class<?> sourceType, final Class<?> r
265260
return getCustomWriteTarget(sourceType);
266261
}
267262

268-
return getOrCreateAndCache(new ConvertiblePair(sourceType, requestedTargetType), customWriteTargetTypes,
269-
new Producer() {
270-
271-
@Override
272-
public Class<?> get() {
273-
return getCustomTarget(sourceType, requestedTargetType, writingPairs);
274-
}
275-
});
263+
return customWriteTargetTypes.computeIfAbsent(new ConvertiblePair(sourceType, requestedTargetType),
264+
it -> getCustomTarget(sourceType, requestedTargetType, writingPairs)).orElse(null);
276265
}
277266

278267
/**
@@ -324,14 +313,8 @@ private Class<?> getCustomReadTarget(final Class<?> sourceType, final Class<?> r
324313
return null;
325314
}
326315

327-
return getOrCreateAndCache(new ConvertiblePair(sourceType, requestedTargetType), customReadTargetTypes,
328-
new Producer() {
329-
330-
@Override
331-
public Class<?> get() {
332-
return getCustomTarget(sourceType, requestedTargetType, readingPairs);
333-
}
334-
});
316+
return customReadTargetTypes.computeIfAbsent(new ConvertiblePair(sourceType, requestedTargetType),
317+
it -> getCustomTarget(sourceType, requestedTargetType, readingPairs)).orElse(null);
335318
}
336319

337320
/**
@@ -343,54 +326,26 @@ public Class<?> get() {
343326
* @param pairs must not be {@literal null}.
344327
* @return
345328
*/
346-
private static Class<?> getCustomTarget(Class<?> sourceType, Class<?> requestedTargetType,
329+
private static Optional<Class<?>> getCustomTarget(Class<?> sourceType, Class<?> requestedTargetType,
347330
Collection<ConvertiblePair> pairs) {
348331

349332
Assert.notNull(sourceType, "Source Class must not be null!");
350333
Assert.notNull(pairs, "Collection of ConvertiblePair must not be null!");
351334

352335
if (requestedTargetType != null && pairs.contains(new ConvertiblePair(sourceType, requestedTargetType))) {
353-
return requestedTargetType;
336+
return Optional.of(requestedTargetType);
354337
}
355338

356339
for (ConvertiblePair typePair : pairs) {
357340
if (typePair.getSourceType().isAssignableFrom(sourceType)) {
358341
Class<?> targetType = typePair.getTargetType();
359342
if (requestedTargetType == null || targetType.isAssignableFrom(requestedTargetType)) {
360-
return targetType;
343+
return Optional.of(targetType);
361344
}
362345
}
363346
}
364347

365-
return null;
366-
}
367-
368-
/**
369-
* Will try to find a value for the given key in the given cache or produce one using the given {@link Producer} and
370-
* store it in the cache.
371-
*
372-
* @param key the key to lookup a potentially existing value, must not be {@literal null}.
373-
* @param cache the cache to find the value in, must not be {@literal null}.
374-
* @param producer the {@link Producer} to create values to cache, must not be {@literal null}.
375-
* @return
376-
*/
377-
private static <T> Class<?> getOrCreateAndCache(T key, Map<T, CacheValue<Class<?>>> cache, Producer producer) {
378-
379-
CacheValue<Class<?>> cacheValue = cache.get(key);
380-
381-
if (cacheValue != null) {
382-
return cacheValue.getValue();
383-
}
384-
385-
Class<?> type = producer.get();
386-
cache.put(key, CacheValue.<Class<?>> ofNullable(type));
387-
388-
return type;
389-
}
390-
391-
private interface Producer {
392-
393-
Class<?> get();
348+
return Optional.empty();
394349
}
395350

396351
@WritingConverter

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import org.bson.Document;
1919
import java.util.List;
20+
import java.util.Optional;
2021

2122
import org.springframework.dao.InvalidDataAccessApiUsageException;
2223
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
@@ -45,7 +46,7 @@ public interface DbRefResolver {
4546
* @param callback will never be {@literal null}.
4647
* @return
4748
*/
48-
Object resolveDbRef(MongoPersistentProperty property, DBRef dbref, DbRefResolverCallback callback,
49+
Optional<Object> resolveDbRef(MongoPersistentProperty property, DBRef dbref, DbRefResolverCallback callback,
4950
DbRefProxyHandler proxyHandler);
5051

5152
/**

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,9 @@ public Object populateId(MongoPersistentProperty property, DBRef source, Object
6161
return proxy;
6262
}
6363

64-
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(property);
65-
MongoPersistentProperty idProperty = entity.getIdProperty();
64+
MongoPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(property);
65+
MongoPersistentProperty idProperty = entity.getIdProperty()
66+
.orElseThrow(() -> new IllegalStateException("Couldn't find identifier property!"));
6667

6768
if (idProperty.usePropertyAccess()) {
6869
return proxy;

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

+4-3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.util.Collections;
2727
import java.util.Comparator;
2828
import java.util.List;
29+
import java.util.Optional;
2930

3031
import org.aopalliance.intercept.MethodInterceptor;
3132
import org.aopalliance.intercept.MethodInvocation;
@@ -84,17 +85,17 @@ public DefaultDbRefResolver(MongoDbFactory mongoDbFactory) {
8485
* @see org.springframework.data.mongodb.core.convert.DbRefResolver#resolveDbRef(org.springframework.data.mongodb.core.mapping.MongoPersistentProperty, org.springframework.data.mongodb.core.convert.DbRefResolverCallback)
8586
*/
8687
@Override
87-
public Object resolveDbRef(MongoPersistentProperty property, DBRef dbref, DbRefResolverCallback callback,
88+
public Optional<Object> resolveDbRef(MongoPersistentProperty property, DBRef dbref, DbRefResolverCallback callback,
8889
DbRefProxyHandler handler) {
8990

9091
Assert.notNull(property, "Property must not be null!");
9192
Assert.notNull(callback, "Callback must not be null!");
9293

9394
if (isLazyDbRef(property)) {
94-
return createLazyLoadingProxy(property, dbref, callback, handler);
95+
return Optional.of(createLazyLoadingProxy(property, dbref, callback, handler));
9596
}
9697

97-
return callback.resolve(property);
98+
return Optional.ofNullable(callback.resolve(property));
9899
}
99100

100101
/*

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

+10-8
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import java.util.Arrays;
1919
import java.util.List;
2020
import java.util.Map;
21+
import java.util.Optional;
2122
import java.util.Set;
2223

2324
import org.bson.Document;
@@ -26,6 +27,7 @@
2627
import org.springframework.data.convert.SimpleTypeInformationMapper;
2728
import org.springframework.data.convert.TypeAliasAccessor;
2829
import org.springframework.data.convert.TypeInformationMapper;
30+
import org.springframework.data.mapping.Alias;
2931
import org.springframework.data.mapping.PersistentEntity;
3032
import org.springframework.data.mapping.context.MappingContext;
3133
import org.springframework.data.util.ClassTypeInformation;
@@ -116,13 +118,13 @@ public void writeTypeRestrictions(Document result, Set<Class<?>> restrictedTypes
116118
accessor.writeTypeTo(result, new Document("$in", restrictedMappedTypes));
117119
}
118120

119-
/* (non-Javadoc)
121+
/*
122+
* (non-Javadoc)
120123
* @see org.springframework.data.convert.DefaultTypeMapper#getFallbackTypeFor(java.lang.Object)
121124
*/
122125
@Override
123-
protected TypeInformation<?> getFallbackTypeFor(Bson source) {
124-
125-
return source instanceof BasicDBList ? LIST_TYPE_INFO : MAP_TYPE_INFO;
126+
protected Optional<TypeInformation<?>> getFallbackTypeFor(Bson source) {
127+
return Optional.of(source instanceof BasicDBList ? LIST_TYPE_INFO : MAP_TYPE_INFO);
126128
}
127129

128130
/**
@@ -142,16 +144,16 @@ public DocumentTypeAliasAccessor(String typeKey) {
142144
* (non-Javadoc)
143145
* @see org.springframework.data.convert.TypeAliasAccessor#readAliasFrom(java.lang.Object)
144146
*/
145-
public Object readAliasFrom(Bson source) {
147+
public Alias readAliasFrom(Bson source) {
146148

147149
if (source instanceof List) {
148-
return null;
150+
return Alias.NONE;
149151
}
150152

151153
if (source instanceof Document) {
152-
return ((Document) source).get(typeKey);
154+
return Alias.ofOptional(Optional.ofNullable(((Document) source).get(typeKey)));
153155
} else if (source instanceof DBObject) {
154-
return ((DBObject) source).get(typeKey);
156+
return Alias.ofOptional(Optional.ofNullable(((DBObject) source).get(typeKey)));
155157
}
156158

157159
throw new IllegalArgumentException("Cannot read alias from " + source.getClass());

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

+11
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import java.util.Arrays;
1919
import java.util.Iterator;
2020
import java.util.Map;
21+
import java.util.Optional;
22+
import java.util.function.Supplier;
2123

2224
import org.bson.Document;
2325
import org.bson.conversions.Bson;
@@ -89,6 +91,15 @@ public void put(MongoPersistentProperty prop, Object value) {
8991
}
9092
}
9193

94+
public void computeIfAbsent(MongoPersistentProperty prop, Supplier<Optional<Object>> supplier) {
95+
96+
if (hasValue(prop)) {
97+
return;
98+
}
99+
100+
supplier.get().ifPresent(it -> put(prop, it));
101+
}
102+
92103
/**
93104
* Returns the value the given {@link MongoPersistentProperty} refers to. By default this will be a direct field but
94105
* the method will also transparently resolve nested values the {@link MongoPersistentProperty} might refer to through

0 commit comments

Comments
 (0)