1
1
/*
2
- * Copyright (c) 2011 by the original author(s) .
2
+ * Copyright 2011-2012 the original author or authors .
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
6
6
* You may obtain a copy of the License at
7
7
*
8
- * http://www.apache.org/licenses/LICENSE-2.0
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
9
*
10
10
* Unless required by applicable law or agreed to in writing, software
11
11
* distributed under the License is distributed on an "AS IS" BASIS,
19
19
import java .util .Arrays ;
20
20
import java .util .List ;
21
21
22
- import org .bson .types .BasicBSONList ;
23
22
import org .bson .types .ObjectId ;
24
23
import org .springframework .core .convert .ConversionException ;
25
24
import org .springframework .core .convert .ConversionService ;
35
34
import com .mongodb .BasicDBList ;
36
35
import com .mongodb .BasicDBObject ;
37
36
import com .mongodb .DBObject ;
37
+ import com .mongodb .DBRef ;
38
38
39
39
/**
40
40
* A helper class to encapsulate any modifications of a Query object before it gets submitted to the database.
41
41
*
42
- * @author Jon Brisbin <[email protected] >
42
+ * @author Jon Brisbin
43
43
* @author Oliver Gierke
44
44
*/
45
45
public class QueryMapper {
@@ -75,8 +75,8 @@ public QueryMapper(MongoConverter converter) {
75
75
*/
76
76
public DBObject getMappedObject (DBObject query , MongoPersistentEntity <?> entity ) {
77
77
78
- if (isKeyWord (query )) {
79
- return getMappedKeyword (query , entity );
78
+ if (Keyword . isKeyword (query )) {
79
+ return getMappedKeyword (new Keyword ( query ) , entity );
80
80
}
81
81
82
82
DBObject result = new BasicDBObject ();
@@ -100,25 +100,38 @@ public DBObject getMappedObject(DBObject query, MongoPersistentEntity<?> entity)
100
100
* @param entity
101
101
* @return
102
102
*/
103
- private DBObject getMappedKeyword (DBObject query , MongoPersistentEntity <?> entity ) {
104
-
105
- String newKey = query .keySet ().iterator ().next ();
106
- Object value = query .get (newKey );
103
+ private DBObject getMappedKeyword (Keyword query , MongoPersistentEntity <?> entity ) {
107
104
108
105
// $or/$nor
109
- if (newKey .matches (N_OR_PATTERN )) {
106
+ if (query . key .matches (N_OR_PATTERN )) {
110
107
111
- Iterable <?> conditions = (Iterable <?>) value ;
108
+ Iterable <?> conditions = (Iterable <?>) query . value ;
112
109
BasicDBList newConditions = new BasicDBList ();
113
110
114
111
for (Object condition : conditions ) {
115
112
newConditions .add (getMappedObject ((DBObject ) condition , entity ));
116
113
}
117
114
118
- return new BasicDBObject (newKey , newConditions );
115
+ return new BasicDBObject (query . key , newConditions );
119
116
}
120
117
121
- return new BasicDBObject (newKey , convertSimpleOrDBObject (value , entity ));
118
+ return new BasicDBObject (query .key , convertSimpleOrDBObject (query .value , entity ));
119
+ }
120
+
121
+ /**
122
+ * Returns the mapped keyword considered defining a criteria for the given property.
123
+ *
124
+ * @param keyword
125
+ * @param property
126
+ * @return
127
+ */
128
+ public DBObject getMappedKeyword (Keyword keyword , MongoPersistentProperty property ) {
129
+
130
+ if (property .isAssociation ()) {
131
+ convertAssociation (keyword .value , property );
132
+ }
133
+
134
+ return new BasicDBObject (keyword .key , getMappedValue (keyword .value , property , keyword .key ));
122
135
}
123
136
124
137
/**
@@ -161,7 +174,7 @@ private Object getMappedValue(Object source, MongoPersistentProperty property, S
161
174
}
162
175
163
176
if (property .isAssociation ()) {
164
- return isKeyWord (source ) ? getMappedValue ( getKeywordValue (source ), property , newKey ) : convertAssociation (source ,
177
+ return Keyword . isKeyword (source ) ? getMappedKeyword ( new Keyword (source ), property ) : convertAssociation (source ,
165
178
property );
166
179
}
167
180
@@ -243,14 +256,14 @@ private Object convertAssociation(Object source, MongoPersistentProperty propert
243
256
}
244
257
245
258
if (source instanceof Iterable ) {
246
- BasicBSONList result = new BasicBSONList ();
259
+ BasicDBList result = new BasicDBList ();
247
260
for (Object element : (Iterable <?>) source ) {
248
- result .add (converter .toDBRef (element , property ));
261
+ result .add (element instanceof DBRef ? element : converter .toDBRef (element , property ));
249
262
}
250
263
return result ;
251
264
}
252
265
253
- return converter .toDBRef (source , property );
266
+ return source instanceof DBRef ? source : converter .toDBRef (source , property );
254
267
}
255
268
256
269
/**
@@ -276,47 +289,59 @@ private boolean isIdKey(String key, MongoPersistentEntity<?> entity) {
276
289
}
277
290
278
291
/**
279
- * Returns whether the given value is representing a query keyword .
292
+ * Converts the given raw id value into either {@link ObjectId} or {@link String} .
280
293
*
281
- * @param value
294
+ * @param id
282
295
* @return
283
296
*/
284
- private static boolean isKeyWord (Object value ) {
297
+ public Object convertId (Object id ) {
285
298
286
- if (!(value instanceof DBObject ) || value instanceof BasicDBList ) {
287
- return false ;
299
+ try {
300
+ return conversionService .convert (id , ObjectId .class );
301
+ } catch (ConversionException e ) {
302
+ // Ignore
288
303
}
289
304
290
- DBObject dbObject = (DBObject ) value ;
291
- return dbObject .keySet ().size () == 1 && dbObject .keySet ().iterator ().next ().startsWith ("$" );
305
+ return converter .convertToMongoType (id );
292
306
}
293
307
294
308
/**
295
- * Returns the value of the given source assuming it's a query keyword.
309
+ * Value object to capture a query keyword representation .
296
310
*
297
- * @param source
298
- * @return
311
+ * @author Oliver Gierke
299
312
*/
300
- private static Object getKeywordValue ( Object source ) {
313
+ private static class Keyword {
301
314
302
- DBObject dbObject = (DBObject ) source ;
303
- return dbObject .get (dbObject .keySet ().iterator ().next ());
304
- }
315
+ String key ;
316
+ Object value ;
305
317
306
- /**
307
- * Converts the given raw id value into either {@link ObjectId} or {@link String}.
308
- *
309
- * @param id
310
- * @return
311
- */
312
- public Object convertId (Object id ) {
318
+ Keyword (Object source ) {
313
319
314
- try {
315
- return conversionService .convert (id , ObjectId .class );
316
- } catch (ConversionException e ) {
317
- // Ignore
320
+ Assert .isInstanceOf (DBObject .class , source );
321
+
322
+ DBObject value = (DBObject ) source ;
323
+
324
+ Assert .isTrue (value .keySet ().size () == 1 , "Keyword must have a single key only!" );
325
+
326
+ this .key = value .keySet ().iterator ().next ();
327
+ this .value = value .get (key );
318
328
}
319
329
320
- return converter .convertToMongoType (id );
330
+ /**
331
+ * Returns whether the given value actually represents a keyword. If this returns {@literal true} it's safe to call
332
+ * the constructor.
333
+ *
334
+ * @param value
335
+ * @return
336
+ */
337
+ static boolean isKeyword (Object value ) {
338
+
339
+ if (!(value instanceof DBObject )) {
340
+ return false ;
341
+ }
342
+
343
+ DBObject dbObject = (DBObject ) value ;
344
+ return dbObject .keySet ().size () == 1 && dbObject .keySet ().iterator ().next ().startsWith ("$" );
345
+ }
321
346
}
322
347
}
0 commit comments