View Javadoc
1   /*
2    * #%L
3    * Expressions.java - mongodb-async-driver - Allanbank Consulting, Inc.
4    * %%
5    * Copyright (C) 2011 - 2014 Allanbank Consulting, Inc.
6    * %%
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   * 
11   *      http://www.apache.org/licenses/LICENSE-2.0
12   * 
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   * #L%
19   */
20  
21  package com.allanbank.mongodb.builder.expression;
22  
23  import static com.allanbank.mongodb.bson.builder.BuilderFactory.d;
24  
25  import java.util.Arrays;
26  import java.util.Date;
27  import java.util.List;
28  import java.util.regex.Pattern;
29  
30  import com.allanbank.mongodb.bson.DocumentAssignable;
31  import com.allanbank.mongodb.bson.Element;
32  import com.allanbank.mongodb.bson.builder.BuilderFactory;
33  import com.allanbank.mongodb.bson.element.BooleanElement;
34  import com.allanbank.mongodb.bson.element.DocumentElement;
35  import com.allanbank.mongodb.bson.element.DoubleElement;
36  import com.allanbank.mongodb.bson.element.IntegerElement;
37  import com.allanbank.mongodb.bson.element.LongElement;
38  import com.allanbank.mongodb.bson.element.MongoTimestampElement;
39  import com.allanbank.mongodb.bson.element.NullElement;
40  import com.allanbank.mongodb.bson.element.ObjectId;
41  import com.allanbank.mongodb.bson.element.ObjectIdElement;
42  import com.allanbank.mongodb.bson.element.RegularExpressionElement;
43  import com.allanbank.mongodb.bson.element.StringElement;
44  import com.allanbank.mongodb.bson.element.TimestampElement;
45  
46  /**
47   * Expressions provides a collection of static helper method for constructing
48   * complex expression.
49   * 
50   * @api.yes This class is part of the driver's API. Public and protected members
51   *          will be deprecated for at least 1 non-bugfix release (version
52   *          numbers are <major>.<minor>.<bugfix>) before being
53   *          removed or modified.
54   * @copyright 2012-2013, Allanbank Consulting, Inc., All Rights Reserved
55   */
56  public final class Expressions {
57  
58      /** The {@value} operator token */
59      public static final String ADD = "$add";
60  
61      /** The {@value} operator token */
62      public static final String ALL_ELEMENTS_TRUE = "$allElementsTrue";
63  
64      /** The {@value} operator token */
65      public static final String AND = "$and";
66  
67      /** The {@value} operator token */
68      public static final String ANY_ELEMENT_TRUE = "$anyElementTrue";
69  
70      /** The {@value} operator token */
71      public static final String COMPARE = "$cmp";
72  
73      /** The {@value} operator token */
74      public static final String CONCATENATE = "$concat";
75  
76      /** The {@value} operator token */
77      public static final String CONDITION = "$cond";
78  
79      /** The {@value} operator token */
80      public static final String DAY_OF_MONTH = "$dayOfMonth";
81  
82      /** The {@value} operator token */
83      public static final String DAY_OF_WEEK = "$dayOfWeek";
84  
85      /** The {@value} operator token */
86      public static final String DAY_OF_YEAR = "$dayOfYear";
87  
88      /** The {@value} operator token */
89      public static final String DIVIDE = "$divide";
90  
91      /** The {@value} operator token */
92      public static final String EQUAL = "$eq";
93  
94      /** The {@value} operator token */
95      public static final String GREATER_THAN = "$gt";
96  
97      /** The {@value} operator token */
98      public static final String GREATER_THAN_OR_EQUAL = "$gte";
99  
100     /** The {@value} operator token */
101     public static final String HOUR = "$hour";
102 
103     /** The {@value} operator token */
104     public static final String IF_NULL = "$ifNull";
105 
106     /** The {@value} operator token */
107     public static final String LESS_THAN = "$lt";
108 
109     /** The {@value} operator token */
110     public static final String LESS_THAN_OR_EQUAL = "$lte";
111 
112     /** The {@value} operator token */
113     public static final String LITERAL = "$literal";
114 
115     /** The {@value} operator token */
116     public static final String MILLISECOND = "$millisecond";
117 
118     /** The {@value} operator token */
119     public static final String MINUTE = "$minute";
120 
121     /** The {@value} operator token */
122     public static final String MODULO = "$mod";
123 
124     /** The {@value} operator token */
125     public static final String MONTH = "$month";
126 
127     /** The {@value} operator token */
128     public static final String MULTIPLY = "$multiply";
129 
130     /** The {@value} operator token */
131     public static final String NOT = "$not";
132 
133     /** The {@value} operator token */
134     public static final String NOT_EQUAL = "$ne";
135 
136     /** The {@value} operator token */
137     public static final String OR = "$or";
138 
139     /** The {@value} operator token */
140     public static final String SECOND = "$second";
141 
142     /** The {@value} operator token */
143     public static final String SET_DIFFERENCE = "$setDifference";
144 
145     /** The {@value} operator token */
146     public static final String SET_EQUALS = "$setEquals";
147 
148     /** The {@value} operator token */
149     public static final String SET_INTERSECTION = "$setIntersection";
150 
151     /** The {@value} operator token */
152     public static final String SET_IS_SUBSET = "$setIsSubset";
153 
154     /** The {@value} operator token */
155     public static final String SET_UNION = "$setUnion";
156 
157     /** The {@value} operator token */
158     public static final String SIZE = "$size";
159 
160     /** The {@value} operator token */
161     public static final String STRING_CASE_INSENSITIVE_COMPARE = "$strcasecmp";
162 
163     /** The {@value} operator token */
164     public static final String SUB_STRING = "$substr";
165 
166     /** The {@value} operator token */
167     public static final String SUBTRACT = "$subtract";
168 
169     /** The {@value} operator token */
170     public static final String TO_LOWER = "$toLower";
171 
172     /** The {@value} operator token */
173     public static final String TO_UPPER = "$toUpper";
174 
175     /** The {@value} operator token */
176     public static final String WEEK = "$week";
177 
178     /** The {@value} operator token */
179     public static final String YEAR = "$year";
180 
181     /**
182      * Returns an {@link NaryExpression} {@value #ADD} expression.
183      * 
184      * @param expressions
185      *            The sub-expressions.
186      * @return The {@link NaryExpression} {@value #ADD} expression.
187      */
188     public static NaryExpression add(final Expression... expressions) {
189         return new NaryExpression(ADD, expressions);
190     }
191 
192     /**
193      * Returns a {@link UnaryExpression} {@value #ALL_ELEMENTS_TRUE} expression.
194      * 
195      * @param expression
196      *            The expression that will be evaluated to create the set to
197      *            inspect for a true element.
198      * @return The {@link UnaryExpression} {@value #ALL_ELEMENTS_TRUE}
199      *         expression.
200      */
201     public static UnaryExpression allElementsTrue(final Expression expression) {
202         return new UnaryExpression(ALL_ELEMENTS_TRUE, expression);
203     }
204 
205     /**
206      * Returns an {@link NaryExpression} {@value #AND} expression.
207      * 
208      * @param expressions
209      *            The sub-expressions.
210      * @return The {@link NaryExpression} {@value #AND} expression.
211      */
212     public static NaryExpression and(final Expression... expressions) {
213         return new NaryExpression(AND, expressions);
214     }
215 
216     /**
217      * Returns a {@link UnaryExpression} {@value #ANY_ELEMENT_TRUE} expression.
218      * 
219      * @param expression
220      *            The expression that will be evaluated to create the set to
221      *            inspect for a true element.
222      * @return The {@link UnaryExpression} {@value #ANY_ELEMENT_TRUE}
223      *         expression.
224      */
225     public static UnaryExpression anyElementTrue(final Expression expression) {
226         return new UnaryExpression(ANY_ELEMENT_TRUE, expression);
227     }
228 
229     /**
230      * Returns a {@link NaryExpression} {@value #COMPARE} expression.
231      * 
232      * @param lhs
233      *            The left hand side of the operation.
234      * @param rhs
235      *            The left hand side of the operation.
236      * @return The {@link NaryExpression} {@value #COMPARE} expression.
237      */
238     public static NaryExpression cmp(final Expression lhs, final Expression rhs) {
239         return new NaryExpression(COMPARE, lhs, rhs);
240     }
241 
242     /**
243      * Returns a {@link NaryExpression} {@value #CONCATENATE} expression.
244      * 
245      * @param expression
246      *            The string expressions for the operator.
247      * @return The {@link NaryExpression} {@value #CONCATENATE} expression.
248      * 
249      * @since MongoDB 2.4
250      */
251     public static NaryExpression concatenate(final Expression... expression) {
252         return new NaryExpression(CONCATENATE, expression);
253     }
254 
255     /**
256      * Returns a {@link NaryExpression} {@value #CONDITION} expression.
257      * 
258      * @param test
259      *            The conditions test.
260      * @param trueResult
261      *            The result if the test is true.
262      * @param falseResult
263      *            The result if the test is false.
264      * @return The {@link NaryExpression} {@value #CONDITION} expression.
265      */
266     public static NaryExpression cond(final Expression test,
267             final Expression trueResult, final Expression falseResult) {
268         return new NaryExpression(CONDITION, test, trueResult, falseResult);
269     }
270 
271     /**
272      * Returns a {@link Constant} expression with the provided <tt>value</tt>.
273      * 
274      * @param value
275      *            The constants value.
276      * @return The {@link Constant} expression.
277      */
278     public static Constant constant(final boolean value) {
279         return new Constant(new BooleanElement("", value));
280     }
281 
282     /**
283      * Returns a {@link Constant} expression with the provided <tt>value</tt>.
284      * 
285      * @param value
286      *            The constants value.
287      * @return The {@link Constant} expression.
288      */
289     public static Constant constant(final Date value) {
290         return constantTimestamp(value.getTime());
291     }
292 
293     /**
294      * Returns a {@link Constant} expression with the provided <tt>value</tt>.
295      * 
296      * @param value
297      *            The constants value.
298      * @return The {@link Constant} expression.
299      */
300     public static Constant constant(final double value) {
301         return new Constant(new DoubleElement("", value));
302     }
303 
304     /**
305      * Returns a {@link Constant} expression wrapping the provided
306      * <tt>element</tt>. This method is intended mainly for wrapping arrays
307      * using the {@link BuilderFactory#a} method.<blockquote>
308      * 
309      * <pre>
310      * <code>
311      * import static {@link BuilderFactory#a com.allanbank.mongodb.bson.builder.BuilderFactory.a}
312      * import static {@link Expressions#constant com.allanbank.mongodb.builder.expression.Expressions.constant}
313      * 
314      * constant( a( "This", "is", "an", "array" ) );
315      * </code>
316      * </pre>
317      * 
318      * </blockquote>
319      * 
320      * @param element
321      *            The element value.
322      * @return The {@link Constant} expression.
323      */
324     public static Expression constant(final Element element) {
325         return new Constant(element);
326     }
327 
328     /**
329      * Returns a {@link Constant} expression with the provided <tt>value</tt>.
330      * 
331      * @param value
332      *            The constants value.
333      * @return The {@link Constant} expression.
334      */
335     public static Constant constant(final int value) {
336         return new Constant(new IntegerElement("", value));
337     }
338 
339     /**
340      * Returns a {@link Constant} expression with the provided <tt>value</tt>.
341      * 
342      * @param value
343      *            The constants value.
344      * @return The {@link Constant} expression.
345      */
346     public static Constant constant(final long value) {
347         return new Constant(new LongElement("", value));
348     }
349 
350     /**
351      * Returns a {@link Constant} expression with the provided <tt>value</tt>.
352      * 
353      * @param value
354      *            The constants value.
355      * @return The {@link Constant} expression.
356      */
357     public static Constant constant(final ObjectId value) {
358         return new Constant(new ObjectIdElement("", value));
359     }
360 
361     /**
362      * Returns a {@link Constant} expression with the provided <tt>value</tt>.
363      * 
364      * @param value
365      *            The constants value.
366      * @return The {@link Constant} expression.
367      */
368     public static Constant constant(final Pattern value) {
369         return new Constant(new RegularExpressionElement("", value));
370     }
371 
372     /**
373      * Returns a {@link Constant} expression with the provided <tt>value</tt>.
374      * 
375      * @param value
376      *            The constants value.
377      * @return The {@link Constant} expression.
378      */
379     public static Constant constant(final String value) {
380         return new Constant(new StringElement("", value));
381     }
382 
383     /**
384      * Returns a {@link Constant} expression with the provided <tt>value</tt>.
385      * 
386      * @param value
387      *            The constants value.
388      * @return The {@link Constant} expression.
389      */
390     public static Constant constantMongoTimestamp(final long value) {
391         return new Constant(new MongoTimestampElement("", value));
392     }
393 
394     /**
395      * Returns a {@link Constant} expression with the provided <tt>value</tt>.
396      * 
397      * @param value
398      *            The constants value.
399      * @return The {@link Constant} expression.
400      */
401     public static Constant constantTimestamp(final long value) {
402         return new Constant(new TimestampElement("", value));
403     }
404 
405     /**
406      * Returns a {@link UnaryExpression} {@value #DAY_OF_MONTH} expression.
407      * 
408      * @param expression
409      *            The date for the operator.
410      * @return The {@link UnaryExpression} {@value #DAY_OF_MONTH} expression.
411      */
412     public static UnaryExpression dayOfMonth(final Expression expression) {
413         return new UnaryExpression(DAY_OF_MONTH, expression);
414     }
415 
416     /**
417      * Returns a {@link UnaryExpression} {@value #DAY_OF_WEEK} expression.
418      * 
419      * @param expression
420      *            The date for the operator.
421      * @return The {@link UnaryExpression} {@value #DAY_OF_WEEK} expression.
422      */
423     public static UnaryExpression dayOfWeek(final Expression expression) {
424         return new UnaryExpression(DAY_OF_WEEK, expression);
425     }
426 
427     /**
428      * Returns a {@link UnaryExpression} {@value #DAY_OF_YEAR} expression.
429      * 
430      * @param expression
431      *            The date for the operator.
432      * @return The {@link UnaryExpression} {@value #DAY_OF_YEAR} expression.
433      */
434     public static UnaryExpression dayOfYear(final Expression expression) {
435         return new UnaryExpression(DAY_OF_YEAR, expression);
436     }
437 
438     /**
439      * Returns a {@link NaryExpression} {@value #DIVIDE} expression.
440      * 
441      * @param numerator
442      *            The numerator of the division.
443      * @param denominator
444      *            The denominator of the division.
445      * @return The {@link NaryExpression} {@value #DIVIDE} expression.
446      */
447     public static NaryExpression divide(final Expression numerator,
448             final Expression denominator) {
449         return new NaryExpression(DIVIDE, numerator, denominator);
450     }
451 
452     /**
453      * Returns a {@link NaryExpression} {@value #EQUAL} expression.
454      * 
455      * @param lhs
456      *            The left hand side of the equals.
457      * @param rhs
458      *            The right hand side of the equals.
459      * @return The {@link NaryExpression} {@value #EQUAL} expression.
460      */
461     public static NaryExpression eq(final Expression lhs, final Expression rhs) {
462         return new NaryExpression(EQUAL, lhs, rhs);
463     }
464 
465     /**
466      * Returns a {@link Constant} expression with the provided
467      * <tt>fieldName</tt>.
468      * <p>
469      * Prepends a {@code $} to the field name if not already present.
470      * </p>
471      * <blockquote>
472      * 
473      * <pre>
474      * <code>
475      * Constant field = Expressions.field("field");
476      * 
477      * // Produces output: 
478      * //      $field
479      * System.out.println(field);
480      * </code>
481      * </pre>
482      * 
483      * </blockquote>
484      * 
485      * @param fieldName
486      *            The name of the field.
487      * @return The {@link Constant} expression.
488      */
489     public static Constant field(final String fieldName) {
490         if (fieldName.startsWith("$")) {
491             return new Constant(new StringElement("", fieldName));
492         }
493         return new Constant(new StringElement("", "$" + fieldName));
494     }
495 
496     /**
497      * Returns a {@link NaryExpression} {@value #GREATER_THAN} expression.
498      * 
499      * @param lhs
500      *            The left hand side of the comparison.
501      * @param rhs
502      *            The right hand side of the comparison.
503      * @return The {@link NaryExpression} {@value #GREATER_THAN} expression.
504      */
505     public static NaryExpression gt(final Expression lhs, final Expression rhs) {
506         return new NaryExpression(GREATER_THAN, lhs, rhs);
507     }
508 
509     /**
510      * Returns a {@link NaryExpression} {@value #GREATER_THAN_OR_EQUAL}
511      * expression.
512      * 
513      * @param lhs
514      *            The left hand side of the comparison.
515      * @param rhs
516      *            The right hand side of the comparison.
517      * @return The {@link NaryExpression} {@value #GREATER_THAN_OR_EQUAL}
518      *         expression.
519      */
520     public static NaryExpression gte(final Expression lhs, final Expression rhs) {
521         return new NaryExpression(GREATER_THAN_OR_EQUAL, lhs, rhs);
522     }
523 
524     /**
525      * Returns a {@link UnaryExpression} {@value #HOUR} expression.
526      * 
527      * @param expression
528      *            The date for the operator.
529      * @return The {@link UnaryExpression} {@value #HOUR} expression.
530      */
531     public static UnaryExpression hour(final Expression expression) {
532         return new UnaryExpression(HOUR, expression);
533     }
534 
535     /**
536      * Returns a {@link NaryExpression} {@value #IF_NULL} expression.
537      * 
538      * @param first
539      *            The first expression.
540      * @param second
541      *            The second expression.
542      * @return The {@link NaryExpression} {@value #IF_NULL} expression.
543      */
544     public static NaryExpression ifNull(final Expression first,
545             final Expression second) {
546         return new NaryExpression(IF_NULL, first, second);
547     }
548 
549     /**
550      * Creates a {@code $let} expression with the provided variables and
551      * {@code in} expression.
552      * <p>
553      * Here is the <a href=
554      * "http://docs.mongodb.org/master/reference/operator/aggregation/let/">
555      * <code>let</code> expression's documentation</a> aggregation pipe line
556      * using this helper class. <blockquote>
557      * 
558      * <pre>
559      * <code>
560      * import static com.allanbank.mongodb.builder.AggregationProjectFields.include;
561      * import static {@link Expressions#add com.allanbank.mongodb.builder.expression.Expressions.add};
562      * import static {@link Expressions#cond com.allanbank.mongodb.builder.expression.Expressions.cond};
563      * import static {@link Expressions#constant com.allanbank.mongodb.builder.expression.Expressions.constant};
564      * import static {@link Expressions#field com.allanbank.mongodb.builder.expression.Expressions.field};
565      * import static {@link Expressions#let com.allanbank.mongodb.builder.expression.Expressions.let};
566      * import static {@link Expressions#multiply com.allanbank.mongodb.builder.expression.Expressions.multiply};
567      * import static {@link Expressions#set com.allanbank.mongodb.builder.expression.Expressions.set};
568      * import static {@link Expressions#var com.allanbank.mongodb.builder.expression.Expressions.var};
569      * 
570      * Aggregate.Builder aggregate = Aggregate.builder();
571      * 
572      * //   $project: {
573      * //      finalTotal: {
574      * //         $let: {
575      * //            vars: {
576      * //               total: { $add: [ '$price', '$tax' ] },
577      * //               discounted: { $cond: { if: '$applyDiscount', then: 0.9, else: 1 } }
578      * //            },
579      * //            in: { $multiply: [ "$$total", "$$discounted" ] }
580      * //         }
581      * //      }
582      * //   }
583      * final Aggregate.Builder aggregation = Aggregate.builder();
584      * aggregation.project(
585      *         include(),
586      *         set("finalTotal",
587      *                 let(
588      *                    multiply(var("total"), var("discounted"))
589      *                    set("total", add(field("price"), field("tax"))),
590      *                    set("discounted",
591      *                         cond(field("applyDiscount"), constant(0.9),
592      *                                 constant(1))))));
593      * 
594      * // Aggregation Pipeline : '$pipeline' : [
595      * //   {
596      * //     '$project' : {
597      * //       finalTotal : {
598      * //         '$let' : {
599      * //           vars : {
600      * //             total : {
601      * //               '$add' : [
602      * //                 '$price', 
603      * //                 '$tax'
604      * //               ]
605      * //             },
606      * //             discounted : {
607      * //               '$cond' : [
608      * //                 '$applyDiscount', 
609      * //                 0.9, 
610      * //                 1
611      * //               ]
612      * //             }
613      * //           },
614      * //           in : {
615      * //             '$multiply' : [
616      * //               '$$total', 
617      * //               '$$discounted'
618      * //             ]
619      * //           }
620      * //         }
621      * //       }
622      * //     }
623      * //   }
624      * // ]
625      * System.out.println("Aggregation Pipeline : " + aggregation);
626      * </code>
627      * </pre>
628      * 
629      * </blockquote>
630      * 
631      * @param inExpression
632      *            The expression to be evaluated with the variables within the
633      *            {@code $let} expression.
634      * @param variables
635      *            The variables for the {@code $let} expression.
636      * @return The Element to set the value to the document.
637      */
638     public static UnaryExpression let(final Expression inExpression,
639             final Element... variables) {
640         return let(Arrays.asList(variables), inExpression);
641     }
642 
643     /**
644      * Creates a {@code $let} expression with the provided variables and
645      * {@code in} expression.
646      * <p>
647      * Here is the <a href=
648      * "http://docs.mongodb.org/master/reference/operator/aggregation/let/">
649      * <code>let</code> expression's documentation</a> aggregation pipe line
650      * using this helper class. <blockquote>
651      * 
652      * <pre>
653      * <code>
654      * import static com.allanbank.mongodb.builder.AggregationProjectFields.include;
655      * import static {@link Expressions#add com.allanbank.mongodb.builder.expression.Expressions.add};
656      * import static {@link Expressions#cond com.allanbank.mongodb.builder.expression.Expressions.cond};
657      * import static {@link Expressions#constant com.allanbank.mongodb.builder.expression.Expressions.constant};
658      * import static {@link Expressions#field com.allanbank.mongodb.builder.expression.Expressions.field};
659      * import static {@link Expressions#let com.allanbank.mongodb.builder.expression.Expressions.let};
660      * import static {@link Expressions#multiply com.allanbank.mongodb.builder.expression.Expressions.multiply};
661      * import static {@link Expressions#set com.allanbank.mongodb.builder.expression.Expressions.set};
662      * import static {@link Expressions#var com.allanbank.mongodb.builder.expression.Expressions.var};
663      * 
664      * Aggregate.Builder aggregate = Aggregate.builder();
665      * 
666      * //   $project: {
667      * //      finalTotal: {
668      * //         $let: {
669      * //            vars: {
670      * //               total: { $add: [ '$price', '$tax' ] },
671      * //               discounted: { $cond: { if: '$applyDiscount', then: 0.9, else: 1 } }
672      * //            },
673      * //            in: { $multiply: [ "$$total", "$$discounted" ] }
674      * //         }
675      * //      }
676      * //   }
677      * final Aggregate.Builder aggregation = Aggregate.builder();
678      * aggregation.project(
679      *         include(),
680      *         set("finalTotal",
681      *                 let(
682      *                    Arrays.asList(
683      *                       set("total", add(field("price"), field("tax"))),
684      *                       set("discounted",
685      *                          cond(field("applyDiscount"), constant(0.9),
686      *                                 constant(1))))
687      *                    multiply(var("total"), var("discounted")))));
688      * 
689      * // Aggregation Pipeline : '$pipeline' : [
690      * //   {
691      * //     '$project' : {
692      * //       finalTotal : {
693      * //         '$let' : {
694      * //           vars : {
695      * //             total : {
696      * //               '$add' : [
697      * //                 '$price', 
698      * //                 '$tax'
699      * //               ]
700      * //             },
701      * //             discounted : {
702      * //               '$cond' : [
703      * //                 '$applyDiscount', 
704      * //                 0.9, 
705      * //                 1
706      * //               ]
707      * //             }
708      * //           },
709      * //           in : {
710      * //             '$multiply' : [
711      * //               '$$total', 
712      * //               '$$discounted'
713      * //             ]
714      * //           }
715      * //         }
716      * //       }
717      * //     }
718      * //   }
719      * // ]
720      * System.out.println("Aggregation Pipeline : " + aggregation);
721      * </code>
722      * </pre>
723      * 
724      * </blockquote>
725      * 
726      * @param variables
727      *            The variables for the {@code $let} expression.
728      * @param inExpression
729      *            The expression to be evaluated with the variables within the
730      *            {@code $let} expression.
731      * @return The Element to set the value to the document.
732      */
733     public static UnaryExpression let(final List<Element> variables,
734             final Expression inExpression) {
735         final DocumentAssignable letDocument = d(new DocumentElement("vars",
736                 variables), inExpression.toElement("in"));
737 
738         return new UnaryExpression("$let", new Constant(new DocumentElement(
739                 "$let", letDocument.asDocument())));
740     }
741 
742     /**
743      * Starts the creation of a {@code $let} expression. The returned
744      * {@link LetBuilder} can be used to add additional variables before setting
745      * the {@link LetBuilder#in final expression} to evaluate.
746      * <p>
747      * Here is the <a href=
748      * "http://docs.mongodb.org/master/reference/operator/aggregation/let/">
749      * <code>let</code> expression's documentation</a> aggregation pipe line
750      * using this helper class. <blockquote>
751      * 
752      * <pre>
753      * <code>
754      * import static com.allanbank.mongodb.builder.AggregationProjectFields.include;
755      * import static {@link Expressions#add com.allanbank.mongodb.builder.expression.Expressions.add};
756      * import static {@link Expressions#cond com.allanbank.mongodb.builder.expression.Expressions.cond};
757      * import static {@link Expressions#constant com.allanbank.mongodb.builder.expression.Expressions.constant};
758      * import static {@link Expressions#field com.allanbank.mongodb.builder.expression.Expressions.field};
759      * import static {@link Expressions#let com.allanbank.mongodb.builder.expression.Expressions.let};
760      * import static {@link Expressions#multiply com.allanbank.mongodb.builder.expression.Expressions.multiply};
761      * import static {@link Expressions#set com.allanbank.mongodb.builder.expression.Expressions.set};
762      * import static {@link Expressions#var com.allanbank.mongodb.builder.expression.Expressions.var};
763      * 
764      * Aggregate.Builder aggregate = Aggregate.builder();
765      * 
766      * //   $project: {
767      * //      finalTotal: {
768      * //         $let: {
769      * //            vars: {
770      * //               total: { $add: [ '$price', '$tax' ] },
771      * //               discounted: { $cond: { if: '$applyDiscount', then: 0.9, else: 1 } }
772      * //            },
773      * //            in: { $multiply: [ "$$total", "$$discounted" ] }
774      * //         }
775      * //      }
776      * //   }
777      * final Aggregate.Builder aggregation = Aggregate.builder();
778      * aggregation.project(
779      *         include(),
780      *         set("finalTotal",
781      *                         let("total", add(field("price"), field("tax")))
782      *                            .let("discounted", cond(field("applyDiscount"), 
783      *                                                    constant(0.9),
784      *                                                    constant(1)))
785      *                            .in(multiply(var("total"), var("discounted")))));
786      * 
787      * // Aggregation Pipeline : '$pipeline' : [
788      * //   {
789      * //     '$project' : {
790      * //       finalTotal : {
791      * //         '$let' : {
792      * //           vars : {
793      * //             total : {
794      * //               '$add' : [
795      * //                 '$price', 
796      * //                 '$tax'
797      * //               ]
798      * //             },
799      * //             discounted : {
800      * //               '$cond' : [
801      * //                 '$applyDiscount', 
802      * //                 0.9, 
803      * //                 1
804      * //               ]
805      * //             }
806      * //           },
807      * //           in : {
808      * //             '$multiply' : [
809      * //               '$$total', 
810      * //               '$$discounted'
811      * //             ]
812      * //           }
813      * //         }
814      * //       }
815      * //     }
816      * //   }
817      * // ]
818      * System.out.println("Aggregation Pipeline : " + aggregation);
819      * </code>
820      * </pre>
821      * 
822      * </blockquote>
823      * 
824      * @param name
825      *            The name of the first field to set.
826      * @param document
827      *            The document to set the first field value to.
828      * @return The Element to set the value to the document.
829      */
830     public static LetBuilder let(final String name,
831             final DocumentAssignable document) {
832         return new LetBuilder(new DocumentElement(name, document.asDocument()));
833     }
834 
835     /**
836      * Starts the creation of a {@code $let} expression. The returned
837      * {@link LetBuilder} can be used to add additional variables before setting
838      * the {@link LetBuilder#in final expression} to evaluate.
839      * <p>
840      * Here is the <a href=
841      * "http://docs.mongodb.org/master/reference/operator/aggregation/let/">
842      * <code>let</code> expression's documentation</a> aggregation pipe line
843      * using this helper class. <blockquote>
844      * 
845      * <pre>
846      * <code>
847      * import static com.allanbank.mongodb.builder.AggregationProjectFields.include;
848      * import static {@link Expressions#add com.allanbank.mongodb.builder.expression.Expressions.add};
849      * import static {@link Expressions#cond com.allanbank.mongodb.builder.expression.Expressions.cond};
850      * import static {@link Expressions#constant com.allanbank.mongodb.builder.expression.Expressions.constant};
851      * import static {@link Expressions#field com.allanbank.mongodb.builder.expression.Expressions.field};
852      * import static {@link Expressions#let com.allanbank.mongodb.builder.expression.Expressions.let};
853      * import static {@link Expressions#multiply com.allanbank.mongodb.builder.expression.Expressions.multiply};
854      * import static {@link Expressions#set com.allanbank.mongodb.builder.expression.Expressions.set};
855      * import static {@link Expressions#var com.allanbank.mongodb.builder.expression.Expressions.var};
856      * 
857      * Aggregate.Builder aggregate = Aggregate.builder();
858      * 
859      * //   $project: {
860      * //      finalTotal: {
861      * //         $let: {
862      * //            vars: {
863      * //               total: { $add: [ '$price', '$tax' ] },
864      * //               discounted: { $cond: { if: '$applyDiscount', then: 0.9, else: 1 } }
865      * //            },
866      * //            in: { $multiply: [ "$$total", "$$discounted" ] }
867      * //         }
868      * //      }
869      * //   }
870      * final Aggregate.Builder aggregation = Aggregate.builder();
871      * aggregation.project(
872      *         include(),
873      *         set("finalTotal",
874      *                         let("total", add(field("price"), field("tax")))
875      *                            .let("discounted", cond(field("applyDiscount"), 
876      *                                                    constant(0.9),
877      *                                                    constant(1)))
878      *                            .in(multiply(var("total"), var("discounted")))));
879      * 
880      * // Aggregation Pipeline : '$pipeline' : [
881      * //   {
882      * //     '$project' : {
883      * //       finalTotal : {
884      * //         '$let' : {
885      * //           vars : {
886      * //             total : {
887      * //               '$add' : [
888      * //                 '$price', 
889      * //                 '$tax'
890      * //               ]
891      * //             },
892      * //             discounted : {
893      * //               '$cond' : [
894      * //                 '$applyDiscount', 
895      * //                 0.9, 
896      * //                 1
897      * //               ]
898      * //             }
899      * //           },
900      * //           in : {
901      * //             '$multiply' : [
902      * //               '$$total', 
903      * //               '$$discounted'
904      * //             ]
905      * //           }
906      * //         }
907      * //       }
908      * //     }
909      * //   }
910      * // ]
911      * System.out.println("Aggregation Pipeline : " + aggregation);
912      * </code>
913      * </pre>
914      * 
915      * </blockquote>
916      * 
917      * @param name
918      *            The name of the field to set.
919      * @param expression
920      *            The expression to compute the value for the first field.
921      * @return The Element to set the value to the expression.
922      */
923     public static LetBuilder let(final String name, final Expression expression) {
924         return new LetBuilder(expression.toElement(name));
925     }
926 
927     /**
928      * Returns a {@link Constant} expression wrapping the <tt>value</tt> in a
929      * {@value #LITERAL} sub-document.
930      * 
931      * @param value
932      *            The constants value.
933      * @return The {@link Constant} expression.
934      */
935     public static Constant literal(final String value) {
936         return new Constant(new DocumentElement("", new StringElement(
937                 "$literal", value)));
938     }
939 
940     /**
941      * Returns a {@link NaryExpression} {@value #LESS_THAN} expression.
942      * 
943      * @param lhs
944      *            The left hand side of the comparison.
945      * @param rhs
946      *            The right hand side of the comparison.
947      * @return The {@link NaryExpression} {@value #LESS_THAN} expression.
948      */
949     public static NaryExpression lt(final Expression lhs, final Expression rhs) {
950         return new NaryExpression(LESS_THAN, lhs, rhs);
951     }
952 
953     /**
954      * Returns a {@link NaryExpression} {@value #LESS_THAN_OR_EQUAL} expression.
955      * 
956      * @param lhs
957      *            The left hand side of the comparison.
958      * @param rhs
959      *            The right hand side of the comparison.
960      * @return The {@link NaryExpression} {@value #LESS_THAN} expression.
961      */
962     public static NaryExpression lte(final Expression lhs, final Expression rhs) {
963         return new NaryExpression(LESS_THAN_OR_EQUAL, lhs, rhs);
964     }
965 
966     /**
967      * Returns a {@link UnaryExpression} expression for the {@code $map}
968      * operation.
969      * <p>
970      * Prepends a {@code $} to the {@code inputField} name if not already
971      * present.
972      * </p>
973      * <p>
974      * Here is the <a href=
975      * "http://docs.mongodb.org/master/reference/operator/aggregation/map/">
976      * <code>map</code> expression's documentation</a> aggregation pipe line
977      * using this helper class. <blockquote>
978      * 
979      * <pre>
980      * <code>
981      * import static com.allanbank.mongodb.builder.AggregationProjectFields.include;
982      * import static {@link Expressions#map(String,String,Expression) com.allanbank.mongodb.builder.expression.Expressions.map};
983      * import static {@link Expressions#set(String,Expression) com.allanbank.mongodb.builder.expression.Expressions.set};
984      * import static {@link Expressions#add(Expression...) com.allanbank.mongodb.builder.expression.Expressions.add};
985      * import static {@link Expressions#var(String) com.allanbank.mongodb.builder.expression.Expressions.var};
986      * import static {@link Expressions#constant(int) com.allanbank.mongodb.builder.expression.Expressions.constant};
987      * 
988      * Aggregate.Builder aggregate = Aggregate.builder();
989      * 
990      * // { $project: { adjustments: { $map: { input: "$skews",
991      * //                            as: "adj",
992      * //                            in: { $add: [ "$$adj", 12 ] } } } } }
993      * aggregate.project(
994      *     include(),
995      *     set( "adjustments", 
996      *         map("skews").as("adj").in( add( var("adj"), constant(12) ) ) ) );
997      * 
998      * // Produces output: 
999      * //    {
1000      * //       '$project' : {
1001      * //          adjustments : {
1002      * //             '$map' {
1003      * //                input : '$skews',
1004      * //                as : 'adj',
1005      * //                in : {
1006      * //                   '$add' : [
1007      * //                      '$$adj',
1008      * //                      12
1009      * //                   ]
1010      * //                }
1011      * //             }
1012      * //          }
1013      * //       }
1014      * //    }
1015      * System.out.println(aggregate);
1016      * </code>
1017      * </pre>
1018      * 
1019      * </blockquote>
1020      * 
1021      * @param inputField
1022      *            The name of the {@code input} field. The map operation
1023      *            expression.
1024      * @return The first stage of the {@code $map} expression construction.
1025      * 
1026      * @see <a
1027      *      href="http://docs.mongodb.org/master/reference/operator/aggregation/map/"><code>map</code>
1028      *      expression documentation</a>
1029      */
1030     public static MapStage1 map(final String inputField) {
1031         return new MapStage1(inputField);
1032     }
1033 
1034     /**
1035      * Returns a {@link UnaryExpression} expression for the {@code $map}
1036      * operation.
1037      * <p>
1038      * Prepends a {@code $} to the {@code inputField} name if not already
1039      * present.
1040      * </p>
1041      * <p>
1042      * Here is the <a href=
1043      * "http://docs.mongodb.org/master/reference/operator/aggregation/map/">
1044      * <code>map</code> expression's documentation</a> aggregation pipe line
1045      * using this helper class. <blockquote>
1046      * 
1047      * <pre>
1048      * <code>
1049      * import static com.allanbank.mongodb.builder.AggregationProjectFields.include;
1050      * import static {@link Expressions#map(String,String,Expression) com.allanbank.mongodb.builder.expression.Expressions.map};
1051      * import static {@link Expressions#set(String,Expression) com.allanbank.mongodb.builder.expression.Expressions.set};
1052      * import static {@link Expressions#add(Expression...) com.allanbank.mongodb.builder.expression.Expressions.add};
1053      * import static {@link Expressions#var(String) com.allanbank.mongodb.builder.expression.Expressions.var};
1054      * import static {@link Expressions#constant(int) com.allanbank.mongodb.builder.expression.Expressions.constant};
1055      * 
1056      * Aggregate.Builder aggregate = Aggregate.builder();
1057      * 
1058      * // { $project: { adjustments: { $map: { input: "$skews",
1059      * //                            as: "adj",
1060      * //                            in: { $add: [ "$$adj", 12 ] } } } } }
1061      * aggregate.project(
1062      *     include(),
1063      *     set( "adjustments", 
1064      *         map( "skews", "adj",
1065      *            add( var("adj"), constant(12) ) ) ) );
1066      * 
1067      * // Produces output: 
1068      * //    {
1069      * //       '$project' : {
1070      * //          adjustments : {
1071      * //             '$map' {
1072      * //                input : '$skews',
1073      * //                as : 'adj',
1074      * //                in : {
1075      * //                   '$add' : [
1076      * //                      '$$adj',
1077      * //                      12
1078      * //                   ]
1079      * //                }
1080      * //             }
1081      * //          }
1082      * //       }
1083      * //    }
1084      * System.out.println(aggregate);
1085      * </code>
1086      * </pre>
1087      * 
1088      * </blockquote>
1089      * 
1090      * @param inputField
1091      *            The name of the {@code input} field.
1092      * @param variableName
1093      *            The name of the {@code as} variable.
1094      * @param mapOperation
1095      *            The map operation expression.
1096      * @return The {@link UnaryExpression} expression.
1097      * 
1098      * @see <a
1099      *      href="http://docs.mongodb.org/master/reference/operator/aggregation/map/"><code>map</code>
1100      *      expression documentation</a>
1101      */
1102     public static UnaryExpression map(final String inputField,
1103             final String variableName, final Expression mapOperation) {
1104 
1105         final DocumentAssignable mapDocument = d(
1106                 field(inputField).toElement("input"), constant(variableName)
1107                         .toElement("as"), mapOperation.toElement("in"));
1108 
1109         return new UnaryExpression("$map", new Constant(new DocumentElement(
1110                 "$map", mapDocument.asDocument())));
1111     }
1112 
1113     /**
1114      * Returns a {@link UnaryExpression} {@value #MILLISECOND} expression.
1115      * 
1116      * @param expression
1117      *            The date for the operator.
1118      * @return The {@link UnaryExpression} {@value #MILLISECOND} expression.
1119      */
1120     public static UnaryExpression millisecond(final Expression expression) {
1121         return new UnaryExpression(MILLISECOND, expression);
1122     }
1123 
1124     /**
1125      * Returns a {@link UnaryExpression} {@value #MINUTE} expression.
1126      * 
1127      * @param expression
1128      *            The date for the operator.
1129      * @return The {@link UnaryExpression} {@value #MINUTE} expression.
1130      */
1131     public static UnaryExpression minute(final Expression expression) {
1132         return new UnaryExpression(MINUTE, expression);
1133     }
1134 
1135     /**
1136      * Returns a {@link NaryExpression} {@value #MODULO} expression.
1137      * 
1138      * @param numerator
1139      *            The numerator of the modulo operation.
1140      * @param denominator
1141      *            The denominator of the modulo operation.
1142      * @return The {@link NaryExpression} {@value #MODULO} expression.
1143      */
1144     public static NaryExpression mod(final Expression numerator,
1145             final Expression denominator) {
1146         return new NaryExpression(MODULO, numerator, denominator);
1147     }
1148 
1149     /**
1150      * Returns a {@link UnaryExpression} {@value #MONTH} expression.
1151      * 
1152      * @param expression
1153      *            The date for the operator.
1154      * @return The {@link UnaryExpression} {@value #MONTH} expression.
1155      */
1156     public static UnaryExpression month(final Expression expression) {
1157         return new UnaryExpression(MONTH, expression);
1158     }
1159 
1160     /**
1161      * Returns a {@link NaryExpression} {@value #MULTIPLY} expression.
1162      * 
1163      * @param lhs
1164      *            The left hand side of the operator.
1165      * @param rhs
1166      *            The right hand side of the operator.
1167      * @return The {@link NaryExpression} {@value #MULTIPLY} expression.
1168      */
1169     public static NaryExpression multiply(final Expression lhs,
1170             final Expression rhs) {
1171         return new NaryExpression(MULTIPLY, lhs, rhs);
1172     }
1173 
1174     /**
1175      * Returns a {@link NaryExpression} {@value #NOT_EQUAL} expression.
1176      * 
1177      * @param lhs
1178      *            The left hand side of the comparison.
1179      * @param rhs
1180      *            The right hand side of the comparison.
1181      * @return The {@link NaryExpression} {@value #NOT_EQUAL} expression.
1182      */
1183     public static NaryExpression ne(final Expression lhs, final Expression rhs) {
1184         return new NaryExpression(NOT_EQUAL, lhs, rhs);
1185     }
1186 
1187     /**
1188      * Returns a {@link UnaryExpression} {@value #NOT} expression.
1189      * 
1190      * @param expression
1191      *            The sub expressions for the $not.
1192      * @return The {@link UnaryExpression} {@value #NOT} expression.
1193      */
1194     public static UnaryExpression not(final Expression expression) {
1195         return new UnaryExpression(NOT, expression);
1196     }
1197 
1198     /**
1199      * Returns a <code>null</code> {@link Constant} expression.
1200      * 
1201      * @return The {@link Constant} expression.
1202      */
1203     public static Constant nullConstant() {
1204         return new Constant(new NullElement(""));
1205     }
1206 
1207     /**
1208      * Returns an {@link NaryExpression} {@value #OR} expression.
1209      * 
1210      * @param expressions
1211      *            The sub-expressions.
1212      * @return The {@link NaryExpression} {@value #OR} expression.
1213      */
1214     public static NaryExpression or(final Expression... expressions) {
1215         return new NaryExpression(OR, expressions);
1216     }
1217 
1218     /**
1219      * Returns a {@link UnaryExpression} {@value #SECOND} expression.
1220      * 
1221      * @param expression
1222      *            The date for the operator.
1223      * @return The {@link UnaryExpression} {@value #SECOND} expression.
1224      */
1225     public static UnaryExpression second(final Expression expression) {
1226         return new UnaryExpression(SECOND, expression);
1227     }
1228 
1229     /**
1230      * Returns an element to set the value to.
1231      * 
1232      * @param name
1233      *            The name of the field to set.
1234      * @param document
1235      *            The document to set the document to.
1236      * @return The Element to set the value to the document.
1237      */
1238     public static Element set(final String name,
1239             final DocumentAssignable document) {
1240         return new DocumentElement(name, document.asDocument());
1241     }
1242 
1243     /**
1244      * Returns an element to set the value to.
1245      * 
1246      * @param name
1247      *            The name of the field to set.
1248      * @param expression
1249      *            The expression to compute the value for the field.
1250      * @return The Element to set the value to the expression.
1251      */
1252     public static Element set(final String name, final Expression expression) {
1253         return expression.toElement(name);
1254     }
1255 
1256     /**
1257      * Returns a {@link NaryExpression} {@value #SET_DIFFERENCE} expression.
1258      * 
1259      * @param lhs
1260      *            The expression that will be evaluated to create the first set.
1261      * @param rhs
1262      *            The expression that will be evaluated to create the second
1263      *            set.
1264      * @return The {@link NaryExpression} {@value #SET_DIFFERENCE} expression.
1265      */
1266     public static NaryExpression setDifference(final Expression lhs,
1267             final Expression rhs) {
1268         return new NaryExpression(SET_DIFFERENCE, lhs, rhs);
1269     }
1270 
1271     /**
1272      * Returns a {@link NaryExpression} {@value #SET_EQUALS} expression.
1273      * 
1274      * @param lhs
1275      *            The expression that will be evaluated to create the first set.
1276      * @param rhs
1277      *            The expression that will be evaluated to create the second
1278      *            set.
1279      * @return The {@link NaryExpression} {@value #SET_EQUALS} expression.
1280      */
1281     public static NaryExpression setEquals(final Expression lhs,
1282             final Expression rhs) {
1283         return new NaryExpression(SET_EQUALS, lhs, rhs);
1284     }
1285 
1286     /**
1287      * Returns a {@link NaryExpression} {@value #SET_INTERSECTION} expression.
1288      * 
1289      * @param lhs
1290      *            The expression that will be evaluated to create the first set.
1291      * @param rhs
1292      *            The expression that will be evaluated to create the second
1293      *            set.
1294      * @return The {@link NaryExpression} {@value #SET_INTERSECTION} expression.
1295      */
1296     public static NaryExpression setIntersection(final Expression lhs,
1297             final Expression rhs) {
1298         return new NaryExpression(SET_INTERSECTION, lhs, rhs);
1299     }
1300 
1301     /**
1302      * Returns a {@link NaryExpression} {@value #SET_IS_SUBSET} expression.
1303      * 
1304      * @param subSet
1305      *            The expression that will be tested to see if it is a subset of
1306      *            the {@code completeSet}.
1307      * @param completeSet
1308      *            The expression that will be evaluated to construct the
1309      *            complete set of values.
1310      * @return The {@link NaryExpression} {@value #SET_IS_SUBSET} expression.
1311      */
1312     public static NaryExpression setIsSubset(final Expression subSet,
1313             final Expression completeSet) {
1314         return new NaryExpression(SET_IS_SUBSET, subSet, completeSet);
1315     }
1316 
1317     /**
1318      * Returns a {@link NaryExpression} {@value #SET_UNION} expression.
1319      * 
1320      * @param lhs
1321      *            The expression that will be evaluated to create the first set.
1322      * @param rhs
1323      *            The expression that will be evaluated to create the second
1324      *            set.
1325      * @return The {@link NaryExpression} {@value #SET_UNION} expression.
1326      */
1327     public static NaryExpression setUnion(final Expression lhs,
1328             final Expression rhs) {
1329         return new NaryExpression(SET_UNION, lhs, rhs);
1330     }
1331 
1332     /**
1333      * Returns a {@link UnaryExpression} {@value #SIZE} expression.
1334      * 
1335      * @param expression
1336      *            The expression that will be evaluated to create the set to
1337      *            inspect for a true element.
1338      * @return The {@link UnaryExpression} {@value #SIZE} expression.
1339      */
1340     public static UnaryExpression size(final Expression expression) {
1341         return new UnaryExpression(SIZE, expression);
1342     }
1343 
1344     /**
1345      * Returns a {@link NaryExpression}
1346      * {@value #STRING_CASE_INSENSITIVE_COMPARE} expression.
1347      * 
1348      * @param lhs
1349      *            The left hand side of the comparison.
1350      * @param rhs
1351      *            The right hand side of the comparison.
1352      * @return The {@link NaryExpression}
1353      *         {@value #STRING_CASE_INSENSITIVE_COMPARE} expression.
1354      */
1355     public static NaryExpression strcasecmp(final Expression lhs,
1356             final Expression rhs) {
1357         return new NaryExpression(STRING_CASE_INSENSITIVE_COMPARE, lhs, rhs);
1358     }
1359 
1360     /**
1361      * Returns a {@link NaryExpression} {@value #SUB_STRING} expression.
1362      * 
1363      * @param string
1364      *            The string to pull a sub-string from.
1365      * @param skip
1366      *            The number of characters to skip in the string.
1367      * @param length
1368      *            The length of the string to extract.
1369      * @return The {@link NaryExpression} {@value #SUB_STRING} expression.
1370      */
1371     public static NaryExpression substr(final Expression string,
1372             final Expression skip, final Expression length) {
1373         return new NaryExpression(SUB_STRING, string, skip, length);
1374     }
1375 
1376     /**
1377      * Returns a {@link NaryExpression} {@value #SUBTRACT} expression.
1378      * 
1379      * @param lhs
1380      *            The left hand side of the operator.
1381      * @param rhs
1382      *            The right hand side of the operator.
1383      * @return The {@link NaryExpression} {@value #SUBTRACT} expression.
1384      */
1385     public static NaryExpression subtract(final Expression lhs,
1386             final Expression rhs) {
1387         return new NaryExpression(SUBTRACT, lhs, rhs);
1388     }
1389 
1390     /**
1391      * Returns a {@link UnaryExpression} {@value #TO_LOWER} expression.
1392      * 
1393      * @param string
1394      *            The string to modify.
1395      * @return The {@link UnaryExpression} {@value #TO_LOWER} expression.
1396      */
1397     public static UnaryExpression toLower(final Expression string) {
1398         return new UnaryExpression(TO_LOWER, string);
1399     }
1400 
1401     /**
1402      * Returns a {@link UnaryExpression} {@value #TO_UPPER} expression.
1403      * 
1404      * @param string
1405      *            The string to modify.
1406      * @return The {@link UnaryExpression} {@value #TO_UPPER} expression.
1407      */
1408     public static UnaryExpression toUpper(final Expression string) {
1409         return new UnaryExpression(TO_UPPER, string);
1410     }
1411 
1412     /**
1413      * Returns a {@link Constant} expression with the provided
1414      * <tt>variableName</tt>. See the {@link #let $let} and {@link #map $map}
1415      * expressions for example usage.
1416      * <p>
1417      * Prepends a {@code $$} to the variable name if not already present.
1418      * </p>
1419      * <blockquote>
1420      * 
1421      * <pre>
1422      * <code>
1423      * Constant variable = Expressions.var("variable");
1424      * 
1425      * // Produces output: 
1426      * //      $$variable
1427      * System.out.println(variable);
1428      * </code>
1429      * </pre>
1430      * 
1431      * </blockquote>
1432      * 
1433      * @param variableName
1434      *            The name of the field.
1435      * @return The {@link Constant} expression.
1436      */
1437     public static Constant var(final String variableName) {
1438 
1439         Constant result;
1440         if (variableName.startsWith("$$")) {
1441             result = new Constant(new StringElement("", variableName));
1442         }
1443         else if (variableName.startsWith("$")) {
1444             result = new Constant(new StringElement("", "$" + variableName));
1445         }
1446         else {
1447             result = new Constant(new StringElement("", "$$" + variableName));
1448         }
1449         return result;
1450     }
1451 
1452     /**
1453      * Returns a {@link UnaryExpression} {@value #WEEK} expression.
1454      * 
1455      * @param expression
1456      *            The date for the operator.
1457      * @return The {@link UnaryExpression} {@value #WEEK} expression.
1458      */
1459     public static UnaryExpression week(final Expression expression) {
1460         return new UnaryExpression(WEEK, expression);
1461     }
1462 
1463     /**
1464      * Returns a {@link UnaryExpression} {@value #YEAR} expression.
1465      * 
1466      * @param expression
1467      *            The date for the operator.
1468      * @return The {@link UnaryExpression} {@value #YEAR} expression.
1469      */
1470     public static UnaryExpression year(final Expression expression) {
1471         return new UnaryExpression(YEAR, expression);
1472     }
1473 
1474     /**
1475      * Creates a new Expressions.
1476      */
1477     private Expressions() {
1478     }
1479 }