26
26
import java .util .function .BinaryOperator ;
27
27
import java .util .function .Function ;
28
28
29
+ import static com .mongodb .client .model .expressions .Expressions .of ;
30
+ import static com .mongodb .client .model .expressions .Expressions .ofStringArray ;
31
+
29
32
final class MqlExpression <T extends Expression >
30
33
implements Expression , BooleanExpression , IntegerExpression , NumberExpression ,
31
34
StringExpression , DateExpression , DocumentExpression , ArrayExpression <T > {
@@ -61,6 +64,12 @@ private Function<CodecRegistry, AstPlaceholder> ast(final String name) {
61
64
return (cr ) -> new AstPlaceholder (new BsonDocument (name , this .toBsonValue (cr )));
62
65
}
63
66
67
+ // in cases where we must wrap the first argument in an array
68
+ private Function <CodecRegistry , AstPlaceholder > astWrapped (final String name ) {
69
+ return (cr ) -> new AstPlaceholder (new BsonDocument (name ,
70
+ new BsonArray (Collections .singletonList (this .toBsonValue (cr )))));
71
+ }
72
+
64
73
private Function <CodecRegistry , AstPlaceholder > ast (final String name , final Expression param1 ) {
65
74
return (cr ) -> {
66
75
BsonArray value = new BsonArray ();
@@ -161,6 +170,80 @@ public BooleanExpression lte(final Expression lte) {
161
170
return new MqlExpression <>(ast ("$lte" , lte ));
162
171
}
163
172
173
+ public BooleanExpression isBoolean () {
174
+ return new MqlExpression <>(ast ("$type" )).eq (of ("bool" ));
175
+ }
176
+
177
+ @ Override
178
+ public BooleanExpression isBooleanOr (final BooleanExpression or ) {
179
+ return this .isBoolean ().cond (this , or );
180
+ }
181
+
182
+ public BooleanExpression isNumber () {
183
+ return new MqlExpression <>(astWrapped ("$isNumber" ));
184
+ }
185
+
186
+ @ Override
187
+ public NumberExpression isNumberOr (final NumberExpression or ) {
188
+ return this .isNumber ().cond (this , or );
189
+ }
190
+
191
+ public BooleanExpression isString () {
192
+ return new MqlExpression <>(ast ("$type" )).eq (of ("string" ));
193
+ }
194
+
195
+ @ Override
196
+ public StringExpression isStringOr (final StringExpression or ) {
197
+ return this .isString ().cond (this , or );
198
+ }
199
+
200
+ public BooleanExpression isDate () {
201
+ return ofStringArray ("date" ).contains (new MqlExpression <>(ast ("$type" )));
202
+ }
203
+
204
+ @ Override
205
+ public DateExpression isDateOr (final DateExpression or ) {
206
+ return this .isDate ().cond (this , or );
207
+ }
208
+
209
+ public BooleanExpression isArray () {
210
+ return new MqlExpression <>(astWrapped ("$isArray" ));
211
+ }
212
+
213
+ @ SuppressWarnings ("unchecked" ) // TODO
214
+ @ Override
215
+ public ArrayExpression <Expression > isArrayOr (final ArrayExpression <? extends Expression > or ) {
216
+ // TODO it seems that ArrEx<T> does not make sense here
217
+ return (ArrayExpression <Expression >) this .isArray ().cond (this .assertImplementsAllExpressions (), or );
218
+ }
219
+
220
+ public BooleanExpression isDocument () {
221
+ return new MqlExpression <>(ast ("$type" )).eq (of ("object" ));
222
+ }
223
+
224
+ @ Override
225
+ public <R extends DocumentExpression > R isDocumentOr (final R or ) {
226
+ return this .isDocument ().cond (this .assertImplementsAllExpressions (), or );
227
+ }
228
+
229
+ @ Override
230
+ public StringExpression asString () {
231
+ return new MqlExpression <>(astWrapped ("$toString" ));
232
+ }
233
+
234
+ private Function <CodecRegistry , AstPlaceholder > convertInternal (final String to , final Expression orElse ) {
235
+ return (cr ) -> astDoc ("$convert" , new BsonDocument ()
236
+ .append ("input" , this .fn .apply (cr ).bsonValue )
237
+ .append ("onError" , extractBsonValue (cr , orElse ))
238
+ .append ("to" , new BsonString (to )));
239
+ }
240
+
241
+ @ Override
242
+ public IntegerExpression parseInteger () {
243
+ Expression asLong = new MqlExpression <>(ast ("$toLong" ));
244
+ return new MqlExpression <>(convertInternal ("int" , asLong ));
245
+ }
246
+
164
247
/** @see ArrayExpression */
165
248
166
249
@ Override
@@ -191,10 +274,7 @@ public T reduce(final T initialValue, final BinaryOperator<T> in) {
191
274
192
275
@ Override
193
276
public IntegerExpression size () {
194
- return new MqlExpression <>(
195
- (cr ) -> new AstPlaceholder (new BsonDocument ("$size" ,
196
- // must wrap the first argument in a list
197
- new BsonArray (Collections .singletonList (this .toBsonValue (cr ))))));
277
+ return new MqlExpression <>(astWrapped ("$size" ));
198
278
}
199
279
200
280
@ Override
@@ -205,19 +285,13 @@ public T elementAt(final IntegerExpression at) {
205
285
206
286
@ Override
207
287
public T first () {
208
- return new MqlExpression <>(
209
- (cr ) -> new AstPlaceholder (new BsonDocument ("$first" ,
210
- // must wrap the first argument in a list
211
- new BsonArray (Collections .singletonList (this .toBsonValue (cr ))))))
288
+ return new MqlExpression <>(astWrapped ("$first" ))
212
289
.assertImplementsAllExpressions ();
213
290
}
214
291
215
292
@ Override
216
293
public T last () {
217
- return new MqlExpression <>(
218
- (cr ) -> new AstPlaceholder (new BsonDocument ("$last" ,
219
- // must wrap the first argument in a list
220
- new BsonArray (Collections .singletonList (this .toBsonValue (cr ))))))
294
+ return new MqlExpression <>(astWrapped ("$last" ))
221
295
.assertImplementsAllExpressions ();
222
296
}
223
297
@@ -233,7 +307,7 @@ public BooleanExpression contains(final T item) {
233
307
}
234
308
235
309
@ Override
236
- public ArrayExpression <T > concat (final ArrayExpression <T > array ) {
310
+ public ArrayExpression <T > concat (final ArrayExpression <? extends T > array ) {
237
311
return new MqlExpression <>(ast ("$concatArrays" , array ))
238
312
.assertImplementsAllExpressions ();
239
313
}
@@ -245,17 +319,14 @@ public ArrayExpression<T> slice(final IntegerExpression start, final IntegerExpr
245
319
}
246
320
247
321
@ Override
248
- public ArrayExpression <T > union (final ArrayExpression <T > set ) {
322
+ public ArrayExpression <T > union (final ArrayExpression <? extends T > set ) {
249
323
return new MqlExpression <>(ast ("$setUnion" , set ))
250
324
.assertImplementsAllExpressions ();
251
325
}
252
326
253
327
@ Override
254
328
public ArrayExpression <T > distinct () {
255
- return new MqlExpression <>(
256
- (cr ) -> new AstPlaceholder (new BsonDocument ("$setUnion" ,
257
- // must wrap the first argument in a list
258
- new BsonArray (Collections .singletonList (this .toBsonValue (cr ))))));
329
+ return new MqlExpression <>(astWrapped ("$setUnion" ));
259
330
}
260
331
261
332
@@ -307,6 +378,11 @@ public IntegerExpression abs() {
307
378
return newMqlExpression (ast ("$abs" ));
308
379
}
309
380
381
+ @ Override
382
+ public DateExpression millisecondsToDate () {
383
+ return newMqlExpression (ast ("$toDate" ));
384
+ }
385
+
310
386
@ Override
311
387
public NumberExpression subtract (final NumberExpression n ) {
312
388
return new MqlExpression <>(ast ("$subtract" , n ));
@@ -391,19 +467,34 @@ public IntegerExpression millisecond(final StringExpression timezone) {
391
467
}
392
468
393
469
@ Override
394
- public StringExpression dateToString ( ) {
470
+ public StringExpression asString ( final StringExpression timezone , final StringExpression format ) {
395
471
return newMqlExpression ((cr ) -> astDoc ("$dateToString" , new BsonDocument ()
396
- .append ("date" , this .toBsonValue (cr ))));
472
+ .append ("date" , this .toBsonValue (cr ))
473
+ .append ("format" , extractBsonValue (cr , format ))
474
+ .append ("timezone" , extractBsonValue (cr , timezone ))));
397
475
}
398
476
399
477
@ Override
400
- public StringExpression dateToString (final StringExpression timezone , final StringExpression format ) {
401
- return newMqlExpression ((cr ) -> astDoc ("$dateToString " , new BsonDocument ()
402
- .append ("date " , this .toBsonValue (cr ))
478
+ public DateExpression parseDate (final StringExpression timezone , final StringExpression format ) {
479
+ return newMqlExpression ((cr ) -> astDoc ("$dateFromString " , new BsonDocument ()
480
+ .append ("dateString " , this .toBsonValue (cr ))
403
481
.append ("format" , extractBsonValue (cr , format ))
404
482
.append ("timezone" , extractBsonValue (cr , timezone ))));
405
483
}
406
484
485
+ @ Override
486
+ public DateExpression parseDate (final StringExpression format ) {
487
+ return newMqlExpression ((cr ) -> astDoc ("$dateFromString" , new BsonDocument ()
488
+ .append ("dateString" , this .toBsonValue (cr ))
489
+ .append ("format" , extractBsonValue (cr , format ))));
490
+ }
491
+
492
+ @ Override
493
+ public DateExpression parseDate () {
494
+ return newMqlExpression ((cr ) -> astDoc ("$dateFromString" , new BsonDocument ()
495
+ .append ("dateString" , this .toBsonValue (cr ))));
496
+ }
497
+
407
498
/** @see StringExpression */
408
499
409
500
@ Override
0 commit comments