26
26
import org .springframework .data .mongodb .core .spel .ExpressionTransformationContextSupport ;
27
27
import org .springframework .data .mongodb .core .spel .LiteralNode ;
28
28
import org .springframework .data .mongodb .core .spel .MethodReferenceNode ;
29
+ import org .springframework .data .mongodb .core .spel .MethodReferenceNode .AggregationMethodReference ;
30
+ import org .springframework .data .mongodb .core .spel .MethodReferenceNode .AggregationMethodReference .ArgumentType ;
31
+ import org .springframework .data .mongodb .core .spel .NotOperatorNode ;
29
32
import org .springframework .data .mongodb .core .spel .OperatorNode ;
30
33
import org .springframework .expression .spel .ExpressionState ;
31
34
import org .springframework .expression .spel .SpelNode ;
32
35
import org .springframework .expression .spel .SpelParserConfiguration ;
33
36
import org .springframework .expression .spel .ast .CompoundExpression ;
37
+ import org .springframework .expression .spel .ast .ConstructorReference ;
34
38
import org .springframework .expression .spel .ast .Indexer ;
35
39
import org .springframework .expression .spel .ast .InlineList ;
40
+ import org .springframework .expression .spel .ast .InlineMap ;
41
+ import org .springframework .expression .spel .ast .OperatorNot ;
36
42
import org .springframework .expression .spel .ast .PropertyOrFieldReference ;
37
43
import org .springframework .expression .spel .standard .SpelExpression ;
38
44
import org .springframework .expression .spel .standard .SpelExpressionParser ;
39
45
import org .springframework .expression .spel .support .StandardEvaluationContext ;
40
46
import org .springframework .util .Assert ;
41
47
import org .springframework .util .NumberUtils ;
48
+ import org .springframework .util .ObjectUtils ;
42
49
43
50
/**
44
51
* Renders the AST of a SpEL expression as a MongoDB Aggregation Framework projection expression.
45
52
*
46
53
* @author Thomas Darimont
54
+ * @author Christoph Strobl
47
55
*/
48
56
class SpelExpressionTransformer implements AggregationExpressionTransformer {
49
57
@@ -65,6 +73,8 @@ public SpelExpressionTransformer() {
65
73
conversions .add (new PropertyOrFieldReferenceNodeConversion (this ));
66
74
conversions .add (new CompoundExpressionNodeConversion (this ));
67
75
conversions .add (new MethodReferenceNodeConversion (this ));
76
+ conversions .add (new NotOperatorNodeConversion (this ));
77
+ conversions .add (new ValueRetrievingNodeConversion (this ));
68
78
69
79
this .conversions = Collections .unmodifiableList (conversions );
70
80
}
@@ -231,8 +241,17 @@ public OperatorNodeConversion(AggregationExpressionTransformer transformer) {
231
241
protected Object convert (AggregationExpressionTransformationContext <OperatorNode > context ) {
232
242
233
243
OperatorNode currentNode = context .getCurrentNode ();
234
-
235
244
Document operationObject = createOperationObjectAndAddToPreviousArgumentsIfNecessary (context , currentNode );
245
+
246
+ if (currentNode .isLogicalOperator ()) {
247
+
248
+ for (ExpressionNode expressionNode : currentNode ) {
249
+ transform (expressionNode , currentNode , operationObject , context );
250
+ }
251
+
252
+ return operationObject ;
253
+ }
254
+
236
255
Object leftResult = transform (currentNode .getLeft (), currentNode , operationObject , context );
237
256
238
257
if (currentNode .isUnaryMinus ()) {
@@ -286,7 +305,7 @@ private Object convertUnaryMinusOp(ExpressionTransformationContextSupport<Operat
286
305
*/
287
306
@ Override
288
307
protected boolean supports (ExpressionNode node ) {
289
- return node .isMathematicalOperation ();
308
+ return node .isMathematicalOperation () || node . isLogicalOperator () ;
290
309
}
291
310
}
292
311
@@ -459,13 +478,31 @@ public MethodReferenceNodeConversion(AggregationExpressionTransformer transforme
459
478
protected Object convert (AggregationExpressionTransformationContext <MethodReferenceNode > context ) {
460
479
461
480
MethodReferenceNode node = context .getCurrentNode ();
462
- List < Object > args = new ArrayList < Object > ();
481
+ AggregationMethodReference methodReference = node . getMethodReference ();
463
482
464
- for (ExpressionNode childNode : node ) {
465
- args .add (transform (childNode , context ));
483
+ Object args = null ;
484
+
485
+ if (ObjectUtils .nullSafeEquals (methodReference .getArgumentType (), ArgumentType .SINGLE )) {
486
+ args = transform (node .getChild (0 ), context );
487
+ } else if (ObjectUtils .nullSafeEquals (methodReference .getArgumentType (), ArgumentType .MAP )) {
488
+
489
+ Document dbo = new Document ();
490
+ for (int i = 0 ; i < methodReference .getArgumentMap ().length ; i ++) {
491
+ dbo .put (methodReference .getArgumentMap ()[i ], transform (node .getChild (i ), context ));
492
+ }
493
+ args = dbo ;
494
+ } else {
495
+
496
+ List <Object > argList = new ArrayList <Object >();
497
+
498
+ for (ExpressionNode childNode : node ) {
499
+ argList .add (transform (childNode , context ));
500
+ }
501
+
502
+ args = argList ;
466
503
}
467
504
468
- return context .addToPreviousOrReturn (new Document (node . getMethodName (), args ));
505
+ return context .addToPreviousOrReturn (new Document (methodReference . getMongoOperator (), args ));
469
506
}
470
507
}
471
508
@@ -507,4 +544,83 @@ protected boolean supports(ExpressionNode node) {
507
544
return node .isOfType (CompoundExpression .class );
508
545
}
509
546
}
547
+
548
+ /**
549
+ * @author Christoph Strobl
550
+ * @since 1.10
551
+ */
552
+ static class NotOperatorNodeConversion extends ExpressionNodeConversion <NotOperatorNode > {
553
+
554
+ /**
555
+ * Creates a new {@link ExpressionNodeConversion}.
556
+ *
557
+ * @param transformer must not be {@literal null}.
558
+ */
559
+ public NotOperatorNodeConversion (AggregationExpressionTransformer transformer ) {
560
+ super (transformer );
561
+ }
562
+
563
+ /*
564
+ * (non-Javadoc)
565
+ * @see org.springframework.data.mongodb.core.aggregation.SpelExpressionTransformer.SpelNodeWrapper#convertSpelNodeToMongoObjectExpression(org.springframework.data.mongodb.core.aggregation.SpelExpressionTransformer.ExpressionConversionContext)
566
+ */
567
+ @ Override
568
+ protected Object convert (AggregationExpressionTransformationContext <NotOperatorNode > context ) {
569
+
570
+ NotOperatorNode node = context .getCurrentNode ();
571
+ List <Object > args = new ArrayList <Object >();
572
+
573
+ for (ExpressionNode childNode : node ) {
574
+ args .add (transform (childNode , context ));
575
+ }
576
+
577
+ return context .addToPreviousOrReturn (new Document (node .getMongoOperator (), args ));
578
+ }
579
+
580
+ /*
581
+ * (non-Javadoc)
582
+ * @see org.springframework.data.mongodb.core.aggregation.SpelExpressionTransformer.NodeConversion#supports(org.springframework.data.mongodb.core.spel.ExpressionNode)
583
+ */
584
+ @ Override
585
+ protected boolean supports (ExpressionNode node ) {
586
+ return node .isOfType (OperatorNot .class );
587
+ }
588
+ }
589
+
590
+ /**
591
+ * @author Christoph Strobl
592
+ * @since 1.10
593
+ */
594
+ static class ValueRetrievingNodeConversion extends ExpressionNodeConversion <ExpressionNode > {
595
+
596
+ /**
597
+ * Creates a new {@link ExpressionNodeConversion}.
598
+ *
599
+ * @param transformer must not be {@literal null}.
600
+ */
601
+ public ValueRetrievingNodeConversion (AggregationExpressionTransformer transformer ) {
602
+ super (transformer );
603
+ }
604
+
605
+ /*
606
+ * (non-Javadoc)
607
+ * @see org.springframework.data.mongodb.core.aggregation.SpelExpressionTransformer.SpelNodeWrapper#convertSpelNodeToMongoObjectExpression(org.springframework.data.mongodb.core.aggregation.SpelExpressionTransformer.ExpressionConversionContext)
608
+ */
609
+ @ Override
610
+ protected Object convert (AggregationExpressionTransformationContext <ExpressionNode > context ) {
611
+
612
+ Object value = context .getCurrentNode ().getValue ();
613
+ return ObjectUtils .isArray (value ) ? Arrays .asList (ObjectUtils .toObjectArray (value )) : value ;
614
+ }
615
+
616
+ /*
617
+ * (non-Javadoc)
618
+ * @see org.springframework.data.mongodb.core.aggregation.SpelExpressionTransformer.NodeConversion#supports(org.springframework.data.mongodb.core.spel.ExpressionNode)
619
+ */
620
+ @ Override
621
+ protected boolean supports (ExpressionNode node ) {
622
+ return node .isOfType (InlineMap .class ) || node .isOfType (InlineList .class )
623
+ || node .isOfType (ConstructorReference .class );
624
+ }
625
+ }
510
626
}
0 commit comments