|
|
|
|
@ -18,6 +18,7 @@ package org.springframework.data.mongodb.core.convert;
@@ -18,6 +18,7 @@ package org.springframework.data.mongodb.core.convert;
|
|
|
|
|
import java.util.ArrayList; |
|
|
|
|
import java.util.Arrays; |
|
|
|
|
import java.util.List; |
|
|
|
|
import java.util.Set; |
|
|
|
|
|
|
|
|
|
import org.bson.types.ObjectId; |
|
|
|
|
import org.springframework.core.convert.ConversionException; |
|
|
|
|
@ -84,8 +85,22 @@ public class QueryMapper {
@@ -84,8 +85,22 @@ public class QueryMapper {
|
|
|
|
|
|
|
|
|
|
for (String key : query.keySet()) { |
|
|
|
|
|
|
|
|
|
if (Keyword.isKeyword(key)) { |
|
|
|
|
result.putAll(getMappedKeyword(new Keyword(query, key), entity)); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Field field = entity == null ? new Field(key) : new MetadataBackedField(key, entity, mappingContext); |
|
|
|
|
result.put(field.getMappedKey(), getMappedValue(query.get(key), field)); |
|
|
|
|
|
|
|
|
|
Object rawValue = query.get(key); |
|
|
|
|
String newKey = field.getMappedKey(); |
|
|
|
|
|
|
|
|
|
if (Keyword.isKeyword(rawValue) && !field.isIdField()) { |
|
|
|
|
Keyword keyword = new Keyword((DBObject) rawValue); |
|
|
|
|
result.put(newKey, getMappedKeyword(field, keyword)); |
|
|
|
|
} else { |
|
|
|
|
result.put(newKey, getMappedValue(field, query.get(key))); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
|
@ -101,13 +116,14 @@ public class QueryMapper {
@@ -101,13 +116,14 @@ public class QueryMapper {
|
|
|
|
|
private DBObject getMappedKeyword(Keyword query, MongoPersistentEntity<?> entity) { |
|
|
|
|
|
|
|
|
|
// $or/$nor
|
|
|
|
|
if (query.key.matches(N_OR_PATTERN)) { |
|
|
|
|
if (query.key.matches(N_OR_PATTERN) || query.value instanceof Iterable) { |
|
|
|
|
|
|
|
|
|
Iterable<?> conditions = (Iterable<?>) query.value; |
|
|
|
|
BasicDBList newConditions = new BasicDBList(); |
|
|
|
|
|
|
|
|
|
for (Object condition : conditions) { |
|
|
|
|
newConditions.add(getMappedObject((DBObject) condition, entity)); |
|
|
|
|
newConditions.add(condition instanceof DBObject ? getMappedObject((DBObject) condition, entity) |
|
|
|
|
: convertSimpleOrDBObject(condition, entity)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return new BasicDBObject(query.key, newConditions); |
|
|
|
|
@ -119,15 +135,15 @@ public class QueryMapper {
@@ -119,15 +135,15 @@ public class QueryMapper {
|
|
|
|
|
/** |
|
|
|
|
* Returns the mapped keyword considered defining a criteria for the given property. |
|
|
|
|
* |
|
|
|
|
* @param keyword |
|
|
|
|
* @param property |
|
|
|
|
* @param keyword |
|
|
|
|
* @return |
|
|
|
|
*/ |
|
|
|
|
private DBObject getMappedKeyword(Keyword keyword, Field property) { |
|
|
|
|
private DBObject getMappedKeyword(Field property, Keyword keyword) { |
|
|
|
|
|
|
|
|
|
boolean needsAssociationConversion = property.isAssociation() && !keyword.isExists(); |
|
|
|
|
Object value = needsAssociationConversion ? convertAssociation(keyword.value, property.getProperty()) |
|
|
|
|
: getMappedValue(keyword.value, property.with(keyword.key)); |
|
|
|
|
: getMappedValue(property.with(keyword.key), keyword.value); |
|
|
|
|
|
|
|
|
|
return new BasicDBObject(keyword.key, value); |
|
|
|
|
} |
|
|
|
|
@ -136,17 +152,17 @@ public class QueryMapper {
@@ -136,17 +152,17 @@ public class QueryMapper {
|
|
|
|
|
* Returns the mapped value for the given source object assuming it's a value for the given |
|
|
|
|
* {@link MongoPersistentProperty}. |
|
|
|
|
* |
|
|
|
|
* @param source the source object to be mapped |
|
|
|
|
* @param value the source object to be mapped |
|
|
|
|
* @param property the property the value is a value for |
|
|
|
|
* @param newKey the key the value will be bound to eventually |
|
|
|
|
* @return |
|
|
|
|
*/ |
|
|
|
|
private Object getMappedValue(Object source, Field key) { |
|
|
|
|
private Object getMappedValue(Field documentField, Object value) { |
|
|
|
|
|
|
|
|
|
if (key.isIdField()) { |
|
|
|
|
if (documentField.isIdField()) { |
|
|
|
|
|
|
|
|
|
if (source instanceof DBObject) { |
|
|
|
|
DBObject valueDbo = (DBObject) source; |
|
|
|
|
if (value instanceof DBObject) { |
|
|
|
|
DBObject valueDbo = (DBObject) value; |
|
|
|
|
if (valueDbo.containsField("$in") || valueDbo.containsField("$nin")) { |
|
|
|
|
String inKey = valueDbo.containsField("$in") ? "$in" : "$nin"; |
|
|
|
|
List<Object> ids = new ArrayList<Object>(); |
|
|
|
|
@ -157,22 +173,25 @@ public class QueryMapper {
@@ -157,22 +173,25 @@ public class QueryMapper {
|
|
|
|
|
} else if (valueDbo.containsField("$ne")) { |
|
|
|
|
valueDbo.put("$ne", convertId(valueDbo.get("$ne"))); |
|
|
|
|
} else { |
|
|
|
|
return getMappedObject((DBObject) source, null); |
|
|
|
|
return getMappedObject((DBObject) value, null); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return valueDbo; |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
return convertId(source); |
|
|
|
|
return convertId(value); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (key.isAssociation()) { |
|
|
|
|
return Keyword.isKeyword(source) ? getMappedKeyword(new Keyword(source), key) : convertAssociation(source, |
|
|
|
|
key.getProperty()); |
|
|
|
|
if (Keyword.isKeyword(value)) { |
|
|
|
|
return getMappedKeyword(new Keyword((DBObject) value), null); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (documentField.isAssociation()) { |
|
|
|
|
return convertAssociation(value, documentField.getProperty()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return convertSimpleOrDBObject(source, key.getPropertyEntity()); |
|
|
|
|
return convertSimpleOrDBObject(value, documentField.getPropertyEntity()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
@ -256,16 +275,18 @@ public class QueryMapper {
@@ -256,16 +275,18 @@ public class QueryMapper {
|
|
|
|
|
String key; |
|
|
|
|
Object value; |
|
|
|
|
|
|
|
|
|
public Keyword(Object source) { |
|
|
|
|
|
|
|
|
|
Assert.isInstanceOf(DBObject.class, source); |
|
|
|
|
public Keyword(DBObject source, String key) { |
|
|
|
|
this.key = key; |
|
|
|
|
this.value = source.get(key); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
DBObject value = (DBObject) source; |
|
|
|
|
public Keyword(DBObject dbObject) { |
|
|
|
|
|
|
|
|
|
Assert.isTrue(value.keySet().size() == 1, "Keyword must have a single key only!"); |
|
|
|
|
Set<String> keys = dbObject.keySet(); |
|
|
|
|
Assert.isTrue(keys.size() == 1, "Can only use a single value DBObject!"); |
|
|
|
|
|
|
|
|
|
this.key = value.keySet().iterator().next(); |
|
|
|
|
this.value = value.get(key); |
|
|
|
|
this.key = keys.iterator().next(); |
|
|
|
|
this.value = dbObject.get(key); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
@ -286,6 +307,10 @@ public class QueryMapper {
@@ -286,6 +307,10 @@ public class QueryMapper {
|
|
|
|
|
*/ |
|
|
|
|
public static boolean isKeyword(Object value) { |
|
|
|
|
|
|
|
|
|
if (value instanceof String) { |
|
|
|
|
return ((String) value).startsWith("$"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!(value instanceof DBObject)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|