25
25
import org .springframework .core .convert .ConversionException ;
26
26
import org .springframework .core .convert .ConversionService ;
27
27
import org .springframework .data .mapping .PersistentEntity ;
28
+ import org .springframework .data .mapping .context .MappingContext ;
28
29
import org .springframework .data .mongodb .core .mapping .MongoPersistentEntity ;
29
30
import org .springframework .data .mongodb .core .mapping .MongoPersistentProperty ;
30
31
import org .springframework .util .Assert ;
31
32
33
+ import com .mongodb .BasicDBList ;
32
34
import com .mongodb .BasicDBObject ;
33
35
import com .mongodb .DBObject ;
34
36
40
42
*/
41
43
public class QueryMapper {
42
44
45
+ private static final List <String > DEFAULT_ID_NAMES = Arrays .asList ("id" , "_id" );
46
+ private static final String N_OR_PATTERN = "\\ $.*or" ;
47
+
43
48
private final ConversionService conversionService ;
44
49
private final MongoConverter converter ;
45
50
@@ -58,17 +63,20 @@ public QueryMapper(MongoConverter converter) {
58
63
* Replaces the property keys used in the given {@link DBObject} with the appropriate keys by using the
59
64
* {@link PersistentEntity} metadata.
60
65
*
61
- * @param query
62
- * @param entity
66
+ * @param query must not be {@literal null}.
67
+ * @param entity can be {@literal null}.
63
68
* @return
64
69
*/
65
70
public DBObject getMappedObject (DBObject query , MongoPersistentEntity <?> entity ) {
66
71
67
72
DBObject newDbo = new BasicDBObject ();
68
73
69
74
for (String key : query .keySet ()) {
75
+
76
+ MongoPersistentEntity <?> nestedEntity = getNestedEntity (entity , key );
70
77
String newKey = key ;
71
78
Object value = query .get (key );
79
+
72
80
if (isIdKey (key , entity )) {
73
81
if (value instanceof DBObject ) {
74
82
DBObject valueDbo = (DBObject ) value ;
@@ -80,34 +88,51 @@ public DBObject getMappedObject(DBObject query, MongoPersistentEntity<?> entity)
80
88
}
81
89
valueDbo .put (inKey , ids .toArray (new Object [ids .size ()]));
82
90
} else {
83
- value = getMappedObject ((DBObject ) value , entity );
91
+ value = getMappedObject ((DBObject ) value , nestedEntity );
84
92
}
85
93
} else {
86
94
value = convertId (value );
87
95
}
88
96
newKey = "_id" ;
89
- } else if (key .startsWith ( "$" ) && key . endsWith ( "or" )) {
97
+ } else if (key .matches ( N_OR_PATTERN )) {
90
98
// $or/$nor
91
99
Iterable <?> conditions = (Iterable <?>) value ;
92
100
BasicBSONList newConditions = new BasicBSONList ();
93
101
Iterator <?> iter = conditions .iterator ();
94
102
while (iter .hasNext ()) {
95
- newConditions .add (getMappedObject ((DBObject ) iter .next (), entity ));
103
+ newConditions .add (getMappedObject ((DBObject ) iter .next (), nestedEntity ));
96
104
}
97
105
value = newConditions ;
98
106
} else if (key .equals ("$ne" )) {
99
107
value = convertId (value );
100
- } else if (value instanceof DBObject ) {
101
- newDbo .put (newKey , getMappedObject ((DBObject ) value , entity ));
102
- continue ;
103
108
}
104
109
105
- newDbo .put (newKey , converter . convertToMongoType (value ));
110
+ newDbo .put (newKey , convertSimpleOrDBObject (value , nestedEntity ));
106
111
}
107
112
108
113
return newDbo ;
109
114
}
110
115
116
+ /**
117
+ * Retriggers mapping if the given source is a {@link DBObject} or simply invokes the
118
+ *
119
+ * @param source
120
+ * @param entity
121
+ * @return
122
+ */
123
+ private Object convertSimpleOrDBObject (Object source , MongoPersistentEntity <?> entity ) {
124
+
125
+ if (source instanceof BasicDBList ) {
126
+ return converter .convertToMongoType (source );
127
+ }
128
+
129
+ if (source instanceof DBObject ) {
130
+ return getMappedObject ((DBObject ) source , entity );
131
+ }
132
+
133
+ return converter .convertToMongoType (source );
134
+ }
135
+
111
136
/**
112
137
* Returns whether the given key will be considered an id key.
113
138
*
@@ -122,7 +147,19 @@ private boolean isIdKey(String key, MongoPersistentEntity<?> entity) {
122
147
return idProperty .getName ().equals (key ) || idProperty .getFieldName ().equals (key );
123
148
}
124
149
125
- return Arrays .asList ("id" , "_id" ).contains (key );
150
+ return DEFAULT_ID_NAMES .contains (key );
151
+ }
152
+
153
+ private MongoPersistentEntity <?> getNestedEntity (MongoPersistentEntity <?> entity , String key ) {
154
+
155
+ MongoPersistentProperty property = entity == null ? null : entity .getPersistentProperty (key );
156
+
157
+ if (property == null || !property .isEntity ()) {
158
+ return null ;
159
+ }
160
+
161
+ MappingContext <? extends MongoPersistentEntity <?>, MongoPersistentProperty > context = converter .getMappingContext ();
162
+ return context .getPersistentEntity (property );
126
163
}
127
164
128
165
/**
0 commit comments