18
18
19
19
import com .mongodb .MongoNamespace ;
20
20
import com .mongodb .WriteConcern ;
21
- import com .mongodb .internal . async . SingleResultCallback ;
21
+ import com .mongodb .client . model . Collation ;
22
22
import com .mongodb .connection .ConnectionDescription ;
23
- import com .mongodb .connection . ServerDescription ;
23
+ import com .mongodb .internal . async . SingleResultCallback ;
24
24
import com .mongodb .internal .binding .AsyncWriteBinding ;
25
25
import com .mongodb .internal .binding .WriteBinding ;
26
26
import com .mongodb .internal .session .SessionContext ;
27
+ import com .mongodb .lang .Nullable ;
27
28
import org .bson .BsonDocument ;
28
29
import org .bson .BsonInt64 ;
30
+ import org .bson .BsonString ;
31
+ import org .bson .BsonValue ;
29
32
import org .bson .FieldNameValidator ;
30
33
import org .bson .codecs .Decoder ;
34
+ import org .bson .conversions .Bson ;
35
+
36
+ import java .util .concurrent .TimeUnit ;
31
37
32
38
import static com .mongodb .assertions .Assertions .notNull ;
33
39
import static com .mongodb .internal .operation .CommandOperationHelper .CommandCreator ;
34
40
import static com .mongodb .internal .operation .CommandOperationHelper .executeRetryableWrite ;
35
41
import static com .mongodb .internal .operation .CommandOperationHelper .executeRetryableWriteAsync ;
42
+ import static com .mongodb .internal .operation .DocumentHelper .putIfNotNull ;
43
+ import static com .mongodb .internal .operation .DocumentHelper .putIfNotZero ;
36
44
import static com .mongodb .internal .operation .OperationHelper .isRetryableWrite ;
45
+ import static com .mongodb .internal .operation .OperationHelper .validateCollation ;
46
+ import static com .mongodb .internal .operation .OperationHelper .validateHintForFindAndModify ;
37
47
import static com .mongodb .internal .operation .ServerVersionHelper .serverIsAtLeastVersionThreeDotTwo ;
48
+ import static java .util .concurrent .TimeUnit .MILLISECONDS ;
38
49
39
50
/**
40
51
* Abstract base class for findAndModify-based operations
@@ -49,6 +60,15 @@ public abstract class BaseFindAndModifyOperation<T> implements AsyncWriteOperati
49
60
private final boolean retryWrites ;
50
61
private final Decoder <T > decoder ;
51
62
63
+ private BsonDocument filter ;
64
+ private BsonDocument projection ;
65
+ private BsonDocument sort ;
66
+ private long maxTimeMS ;
67
+ private Collation collation ;
68
+ private Bson hint ;
69
+ private String hintString ;
70
+ private BsonValue comment ;
71
+
52
72
/**
53
73
* Construct a new instance.
54
74
*
@@ -81,8 +101,6 @@ public void executeAsync(final AsyncWriteBinding binding, final SingleResultCall
81
101
getCommandCreator (binding .getSessionContext ()), FindAndModifyHelper .asyncTransformer (), cmd -> cmd , callback );
82
102
}
83
103
84
- protected abstract String getDatabaseName ();
85
-
86
104
/**
87
105
* Gets the namespace.
88
106
*
@@ -122,22 +140,231 @@ public boolean isRetryWrites() {
122
140
return retryWrites ;
123
141
}
124
142
125
- protected abstract CommandCreator getCommandCreator (SessionContext sessionContext );
126
143
127
- protected void addTxnNumberToCommand (final ServerDescription serverDescription , final ConnectionDescription connectionDescription ,
128
- final BsonDocument commandDocument , final SessionContext sessionContext ) {
129
- if (isRetryableWrite (isRetryWrites (), getWriteConcern (), serverDescription , connectionDescription , sessionContext )) {
130
- commandDocument .put ("txnNumber" , new BsonInt64 (sessionContext .advanceTransactionNumber ()));
131
- }
144
+ /**
145
+ * Gets the query filter.
146
+ *
147
+ * @return the query filter
148
+ * @mongodb.driver.manual reference/method/db.collection.find/ Filter
149
+ */
150
+ public BsonDocument getFilter () {
151
+ return filter ;
152
+ }
153
+
154
+ /**
155
+ * Sets the query filter to apply to the query.
156
+ *
157
+ * @param filter the query filter, which may be null.
158
+ * @return this
159
+ * @mongodb.driver.manual reference/method/db.collection.find/ Filter
160
+ */
161
+ public BaseFindAndModifyOperation <T > filter (final BsonDocument filter ) {
162
+ this .filter = filter ;
163
+ return this ;
164
+ }
165
+
166
+ /**
167
+ * Gets a document describing the fields to return for all matching documents.
168
+ *
169
+ * @return the project document, which may be null
170
+ * @mongodb.driver.manual reference/method/db.collection.find/ Projection
171
+ */
172
+ public BsonDocument getProjection () {
173
+ return projection ;
174
+ }
175
+
176
+ /**
177
+ * Sets a document describing the fields to return for all matching documents.
178
+ *
179
+ * @param projection the project document, which may be null.
180
+ * @return this
181
+ * @mongodb.driver.manual reference/method/db.collection.find/ Projection
182
+ */
183
+ public BaseFindAndModifyOperation <T > projection (final BsonDocument projection ) {
184
+ this .projection = projection ;
185
+ return this ;
186
+ }
187
+
188
+ /**
189
+ * Gets the maximum execution time on the server for this operation. The default is 0, which places no limit on the execution time.
190
+ *
191
+ * @param timeUnit the time unit to return the result in
192
+ * @return the maximum execution time in the given time unit
193
+ */
194
+ public long getMaxTime (final TimeUnit timeUnit ) {
195
+ notNull ("timeUnit" , timeUnit );
196
+ return timeUnit .convert (maxTimeMS , TimeUnit .MILLISECONDS );
197
+ }
198
+
199
+ /**
200
+ * Sets the maximum execution time on the server for this operation.
201
+ *
202
+ * @param maxTime the max time
203
+ * @param timeUnit the time unit, which may not be null
204
+ * @return this
205
+ */
206
+ public BaseFindAndModifyOperation <T > maxTime (final long maxTime , final TimeUnit timeUnit ) {
207
+ notNull ("timeUnit" , timeUnit );
208
+ this .maxTimeMS = TimeUnit .MILLISECONDS .convert (maxTime , timeUnit );
209
+ return this ;
210
+ }
211
+
212
+ /**
213
+ * Gets the sort criteria to apply to the query. The default is null, which means that the documents will be returned in an undefined
214
+ * order.
215
+ *
216
+ * @return a document describing the sort criteria
217
+ * @mongodb.driver.manual reference/method/cursor.sort/ Sort
218
+ */
219
+ public BsonDocument getSort () {
220
+ return sort ;
221
+ }
222
+
223
+ /**
224
+ * Sets the sort criteria to apply to the query.
225
+ *
226
+ * @param sort the sort criteria, which may be null.
227
+ * @return this
228
+ * @mongodb.driver.manual reference/method/cursor.sort/ Sort
229
+ */
230
+ public BaseFindAndModifyOperation <T > sort (final BsonDocument sort ) {
231
+ this .sort = sort ;
232
+ return this ;
233
+ }
234
+
235
+ /**
236
+ * Returns the collation options
237
+ *
238
+ * @return the collation options
239
+ * @since 3.4
240
+ * @mongodb.server.release 3.4
241
+ */
242
+ public Collation getCollation () {
243
+ return collation ;
244
+ }
245
+
246
+ /**
247
+ * Returns the hint for which index to use. The default is not to set a hint.
248
+ *
249
+ * @return the hint
250
+ * @since 4.1
251
+ */
252
+ @ Nullable
253
+ public Bson getHint () {
254
+ return hint ;
255
+ }
256
+
257
+ /**
258
+ * Sets the hint for which index to use. A null value means no hint is set.
259
+ *
260
+ * @param hint the hint
261
+ * @return this
262
+ * @since 4.1
263
+ */
264
+ public BaseFindAndModifyOperation <T > hint (@ Nullable final Bson hint ) {
265
+ this .hint = hint ;
266
+ return this ;
267
+ }
268
+
269
+ /**
270
+ * Gets the hint string to apply.
271
+ *
272
+ * @return the hint string, which should be the name of an existing index
273
+ * @since 4.1
274
+ */
275
+ @ Nullable
276
+ public String getHintString () {
277
+ return hintString ;
278
+ }
279
+
280
+ /**
281
+ * Sets the hint to apply.
282
+ *
283
+ * @param hint the name of the index which should be used for the operation
284
+ * @return this
285
+ * @since 4.1
286
+ */
287
+ public BaseFindAndModifyOperation <T > hintString (@ Nullable final String hint ) {
288
+ this .hintString = hint ;
289
+ return this ;
290
+ }
291
+
292
+ /**
293
+ * Sets the collation options
294
+ *
295
+ * <p>A null value represents the server default.</p>
296
+ * @param collation the collation options to use
297
+ * @return this
298
+ * @since 3.4
299
+ * @mongodb.server.release 3.4
300
+ */
301
+ public BaseFindAndModifyOperation <T > collation (final Collation collation ) {
302
+ this .collation = collation ;
303
+ return this ;
304
+ }
305
+
306
+ /**
307
+ * @return comment for this operation. A null value means no comment is set.
308
+ * @since 4.6
309
+ * @mongodb.server.release 4.4
310
+ */
311
+ public BsonValue getComment () {
312
+ return comment ;
132
313
}
133
314
134
- protected void addWriteConcernToCommand (final ConnectionDescription connectionDescription , final BsonDocument commandDocument ,
135
- final SessionContext sessionContext ) {
136
- if (getWriteConcern ().isAcknowledged () && !getWriteConcern ().isServerDefault ()
137
- && serverIsAtLeastVersionThreeDotTwo (connectionDescription ) && !sessionContext .hasActiveTransaction ()) {
138
- commandDocument .put ("writeConcern" , getWriteConcern ().asDocument ());
139
- }
315
+ /**
316
+ * Sets the comment for this operation. A null value means no comment is set.
317
+ *
318
+ * @param comment the comment
319
+ * @return this
320
+ * @since 4.6
321
+ * @mongodb.server.release 4.4
322
+ */
323
+ public BaseFindAndModifyOperation <T > comment (final BsonValue comment ) {
324
+ this .comment = comment ;
325
+ return this ;
140
326
}
141
327
142
328
protected abstract FieldNameValidator getFieldNameValidator ();
329
+
330
+ protected abstract void specializeCommand (BsonDocument initialCommand , ConnectionDescription connectionDescription );
331
+
332
+ private CommandCreator getCommandCreator (final SessionContext sessionContext ) {
333
+ return (serverDescription , connectionDescription ) -> {
334
+ validateCollation (connectionDescription , getCollation ());
335
+ BsonDocument commandDocument = new BsonDocument ("findAndModify" , new BsonString (getNamespace ().getCollectionName ()));
336
+ putIfNotNull (commandDocument , "query" , getFilter ());
337
+ putIfNotNull (commandDocument , "fields" , getProjection ());
338
+ putIfNotNull (commandDocument , "sort" , getSort ());
339
+
340
+ specializeCommand (commandDocument , connectionDescription );
341
+
342
+ putIfNotZero (commandDocument , "maxTimeMS" , getMaxTime (MILLISECONDS ));
343
+ if (getWriteConcern ().isAcknowledged () && !getWriteConcern ().isServerDefault ()
344
+ && serverIsAtLeastVersionThreeDotTwo (connectionDescription ) && !sessionContext .hasActiveTransaction ()) {
345
+ commandDocument .put ("writeConcern" , getWriteConcern ().asDocument ());
346
+ }
347
+ if (getCollation () != null ) {
348
+ commandDocument .put ("collation" , getCollation ().asDocument ());
349
+ }
350
+ if (getHint () != null || getHintString () != null ) {
351
+ validateHintForFindAndModify (connectionDescription , getWriteConcern ());
352
+ if (getHint () != null ) {
353
+ commandDocument .put ("hint" , getHint ().toBsonDocument (BsonDocument .class , null ));
354
+ } else {
355
+ commandDocument .put ("hint" , new BsonString (getHintString ()));
356
+ }
357
+ }
358
+ putIfNotNull (commandDocument , "comment" , getComment ());
359
+
360
+ if (isRetryableWrite (isRetryWrites (), getWriteConcern (), serverDescription , connectionDescription , sessionContext )) {
361
+ commandDocument .put ("txnNumber" , new BsonInt64 (sessionContext .advanceTransactionNumber ()));
362
+ }
363
+ return commandDocument ;
364
+ };
365
+ }
366
+
367
+ private String getDatabaseName () {
368
+ return getNamespace ().getDatabaseName ();
369
+ }
143
370
}
0 commit comments