diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentAccessor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentAccessor.java index 13234cc3a..dfb51d94b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentAccessor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentAccessor.java @@ -17,17 +17,16 @@ package org.springframework.data.mongodb.core.convert; import java.util.Arrays; import java.util.Iterator; -import java.util.Map; import org.bson.Document; import org.bson.conversions.Bson; + import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.data.mongodb.util.BsonUtils; import org.springframework.lang.Nullable; import org.springframework.util.Assert; -import com.mongodb.BasicDBObject; import com.mongodb.DBObject; /** @@ -110,28 +109,7 @@ class DocumentAccessor { */ @Nullable public Object get(MongoPersistentProperty property) { - - String fieldName = property.getFieldName(); - Map map = BsonUtils.asMap(document); - - if (!fieldName.contains(".")) { - return map.get(fieldName); - } - - Iterator parts = Arrays.asList(fieldName.split("\\.")).iterator(); - Map source = map; - Object result = null; - - while (source != null && parts.hasNext()) { - - result = source.get(parts.next()); - - if (parts.hasNext()) { - source = getAsMap(result); - } - } - - return result; + return BsonUtils.resolveValue(document, property.getFieldName()); } /** @@ -157,71 +135,7 @@ class DocumentAccessor { Assert.notNull(property, "Property must not be null!"); - String fieldName = property.getFieldName(); - - - if (this.document instanceof Document) { - - if (((Document) this.document).containsKey(fieldName)) { - return true; - } - } else if (this.document instanceof DBObject) { - if (((DBObject) this.document).containsField(fieldName)) { - return true; - } - } - - if (!fieldName.contains(".")) { - return false; - } - - String[] parts = fieldName.split("\\."); - Map source; - - if (this.document instanceof Document) { - source = ((Document) this.document); - } else { - source = ((DBObject) this.document).toMap(); - } - - Object result = null; - - for (int i = 1; i < parts.length; i++) { - - result = source.get(parts[i - 1]); - source = getAsMap(result); - - if (source == null) { - return false; - } - } - - return source.containsKey(parts[parts.length - 1]); - } - - /** - * Returns the given source object as map, i.e. {@link Document}s and maps as is or {@literal null} otherwise. - * - * @param source can be {@literal null}. - * @return can be {@literal null}. - */ - @Nullable - @SuppressWarnings("unchecked") - private static Map getAsMap(Object source) { - - if (source instanceof Document) { - return (Document) source; - } - - if (source instanceof BasicDBObject) { - return (BasicDBObject) source; - } - - if (source instanceof Map) { - return (Map) source; - } - - return null; + return BsonUtils.hasValue(document, property.getFieldName()); } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java index 2ac6744db..7c327b22d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java @@ -291,6 +291,7 @@ public class BsonUtils { * @param bson the source to inspect. Must not be {@literal null}. * @param key the key to lookup. Must not be {@literal null}. * @return can be {@literal null}. + * @since 3.0.8 */ @Nullable public static Object resolveValue(Bson bson, String key) { @@ -307,7 +308,7 @@ public class BsonUtils { Object result = source.get(parts[i - 1]); - if (result == null || !(result instanceof Bson)) { + if (!(result instanceof Bson)) { return null; } @@ -317,6 +318,73 @@ public class BsonUtils { return source.get(parts[parts.length - 1]); } + /** + * Returns whether the underlying {@link Bson bson} has a value ({@literal null} or non-{@literal null}) for the given + * {@code key}. + * + * @param bson the source to inspect. Must not be {@literal null}. + * @param key the key to lookup. Must not be {@literal null}. + * @return {@literal true} if no non {@literal null} value present. + * @since 3.0.8 + */ + public static boolean hasValue(Bson bson, String key) { + + Map source = asMap(bson); + + if (source.get(key) != null) { + return true; + } + + if (!key.contains(".")) { + return false; + } + + String[] parts = key.split("\\."); + + Object result; + + for (int i = 1; i < parts.length; i++) { + + result = source.get(parts[i - 1]); + source = getAsMap(result); + + if (source == null) { + return false; + } + } + + return source.containsKey(parts[parts.length - 1]); + } + + /** + * Returns the given source object as map, i.e. {@link Document}s and maps as is or {@literal null} otherwise. + * + * @param source can be {@literal null}. + * @return can be {@literal null}. + */ + @Nullable + @SuppressWarnings("unchecked") + private static Map getAsMap(Object source) { + + if (source instanceof Document) { + return (Document) source; + } + + if (source instanceof BasicDBObject) { + return (BasicDBObject) source; + } + + if (source instanceof DBObject) { + return ((DBObject) source).toMap(); + } + + if (source instanceof Map) { + return (Map) source; + } + + return null; + } + @Nullable private static String toJson(@Nullable Object value) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java index f1ce4005a..9c5b5500e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java @@ -1914,7 +1914,7 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests { @Test // GH-3590 void shouldIncludeValueFromNestedShardKeyPath() { - WithShardKeyPoitingToNested source = new WithShardKeyPoitingToNested(); + WithShardKeyPointingToNested source = new WithShardKeyPointingToNested(); source.id = "id-1"; source.value = "v1"; source.nested = new WithNamedFields(); @@ -2266,7 +2266,7 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests { } @Sharded(shardKey = {"value", "nested.customName"}) - static class WithShardKeyPoitingToNested { + static class WithShardKeyPointingToNested { String id; String value; WithNamedFields nested;