From a5c000d171392c99ac313278088b64001f6dbb4b Mon Sep 17 00:00:00 2001 From: Maxim Katcharov Date: Mon, 5 Dec 2022 14:19:51 -0700 Subject: [PATCH 01/11] Fixes --- .../client/model/expressions/Expression.java | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java b/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java index fb94262796f..49146555ac1 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java @@ -26,15 +26,26 @@ * * TODO-END: 'cause an error', 'execution context', wrong types/unsafe operations * TODO-END: types and how missing/null are not part of any type. + * TODO-END: behaviour of equals * * @see Expressions */ @Evolving public interface Expression { + /** + * The method {@link Expression#eq} should be used to compare values for + * equality. + */ + @Deprecated // TODO-END (?)

Marked deprecated to prevent erroneous use. + @Override + boolean equals(Object other); + /** * Whether {@code this} value is equal to the {@code other} value. * + *

The result does not correlate with {@link Expression#equals(Object)}. + * * @param other the other value. * @return the resulting value. */ @@ -97,9 +108,6 @@ public interface Expression { * {@code this} is a number, or the {@code other} number value if * {@code this} is null, or is missing, or is of any other non-number type. * - *

Since integers are a subset of numbers, if a value is an integer, - * this does not imply that it is not a number, and vice-versa. - * * @param other the other value. * @return the resulting value. */ @@ -110,18 +118,15 @@ public interface Expression { * {@code this} is an integer, or the {@code other} integer value if * {@code this} is null, or is missing, or is of any other non-integer type. * - *

Since integers are a subset of numbers, if a value is an integer, - * this does not imply that it is not a number, and vice-versa. - * * @param other the other value. * @return the resulting value. */ IntegerExpression isIntegerOr(IntegerExpression other); /** - * {@code this} value as a {@link BooleanExpression boolean} if - * {@code this} is a boolean, or the {@code other} boolean value if - * {@code this} is null, or is missing, or is of any other non-boolean type. + * {@code this} value as a {@link StringExpression string} if + * {@code this} is a string, or the {@code other} string value if + * {@code this} is null, or is missing, or is of any other non-string type. * * @param other the other value. * @return the resulting value. @@ -129,9 +134,9 @@ public interface Expression { StringExpression isStringOr(StringExpression other); /** - * {@code this} value as a {@link StringExpression string} if - * {@code this} is a string, or the {@code other} string value if - * {@code this} is null, or is missing, or is of any other non-string type. + * {@code this} value as a {@link DateExpression boolean} if + * {@code this} is a date, or the {@code other} date value if + * {@code this} is null, or is missing, or is of any other non-date type. * * @param other the other value. * @return the resulting value. @@ -150,7 +155,7 @@ public interface Expression { * the user is an unchecked assertion that all elements are of that type, * and that no element is null, is missing, or is of some other type. If the * user cannot make such an assertion, some appropriate super-type should be - * chosen, and elements should be individually type-checked. + * chosen, and if necessary elements should be individually type-checked. * * @param other the other value. * @return the resulting value. @@ -164,7 +169,7 @@ public interface Expression { MapExpression isMapOr(MapExpression other); /** - * The {@link StringExpression string} value corresponding to this value. + * The {@link StringExpression string} representation of {@code this} value. * *

This may "cause an error" if the type cannot be converted to string, * as is the case with {@link ArrayExpression arrays}, @@ -182,13 +187,10 @@ public interface Expression { StringExpression asString(); /** - * Applies the provided function to {@code this}. + * Applies the provided function to {@code this} value. * *

Equivalent to {@code f.apply(this)}, and allows lambdas and static, - * user-defined functions to use the chaining syntax. For example: - * {@code myInteger.apply(isEven)} (here, {@code isEven} is a function - * taking an {@link IntegerExpression integer} and yielding a - * {@link BooleanExpression boolean}). + * user-defined functions to use the chaining syntax. * * @param f the function to apply. * @return the resulting value. From dccdf34b1faba17cc46c1024be96bf1bede81d2a Mon Sep 17 00:00:00 2001 From: Maxim Katcharov Date: Wed, 11 Jan 2023 16:43:28 -0700 Subject: [PATCH 02/11] Update docs --- .../model/expressions/ArrayExpression.java | 34 ++--- .../model/expressions/BooleanExpression.java | 7 +- .../model/expressions/DateExpression.java | 3 +- .../client/model/expressions/Expression.java | 98 ++++++++++++--- .../client/model/expressions/Expressions.java | 119 ++++++++++++++---- .../model/expressions/IntegerExpression.java | 15 ++- .../model/expressions/NumberExpression.java | 13 +- 7 files changed, 214 insertions(+), 75 deletions(-) diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/ArrayExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/ArrayExpression.java index 7b499f7ada0..90fd498c1eb 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/ArrayExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/ArrayExpression.java @@ -21,35 +21,39 @@ import static com.mongodb.client.model.expressions.Expressions.of; /** - * Expresses an array value. An array value is a finite, ordered collection of - * elements of a certain type. + * An array {@link Expression value} in the context of the MongoDB Query + * Language (MQL). An array is a finite, ordered collection of elements of a + * certain type. It is also known as a finite mathematical sequence. * - * @param the type of the elements in the array + * @param the type of the elements */ public interface ArrayExpression extends Expression { /** - * Returns an array consisting of those elements in this array that match - * the given predicate condition. Evaluates each expression in this array - * according to the cond function. If cond evaluates to logical true, then - * the element is preserved; if cond evaluates to logical false, the element - * is omitted. + * An array consisting of only those elements in {@code this} array that + * match the provided predicate. * - * @param cond the function to apply to each element - * @return the new array + * @param predicate the predicate to apply to each element to determine if + * it should be included. + * @return the resulting array. */ ArrayExpression filter(Function cond); /** - * Returns an array consisting of the results of applying the given function - * to the elements of this array. + * An array consisting of the results of applying the provided function to + * the elements of {@code this} array. * - * @param in the function to apply to each element - * @return the new array - * @param the type contained in the resulting array + * @param in the function to apply to each element. + * @return the resulting array. + * @param the type of the elements of the resulting array. */ ArrayExpression map(Function in); + /** + * The size of {@code this} array. + * + * @return the size. + */ IntegerExpression size(); BooleanExpression any(Function predicate); diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/BooleanExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/BooleanExpression.java index 00da72a208e..8cb59611e4a 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/BooleanExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/BooleanExpression.java @@ -19,7 +19,8 @@ import java.util.function.Function; /** - * A logical boolean value, either true or false. + * A boolean {@linkplain Expression value} in the context of the + * MongoDB Query Language (MQL). */ public interface BooleanExpression extends Expression { @@ -51,8 +52,8 @@ public interface BooleanExpression extends Expression { * The {@code left} branch when {@code this} is true, * and the {@code right} branch otherwise. * - * @param left the left branch. - * @param right the right branch. + * @param left the left value. + * @param right the right value. * @return the resulting value. * @param The type of the resulting expression. */ diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/DateExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/DateExpression.java index be2b838058b..83bc09de0e2 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/DateExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/DateExpression.java @@ -19,7 +19,8 @@ import java.util.function.Function; /** - * An instantaneous date and time. Tracks a UTC datetime, the number of + * An instantaneous date and time {@linkplain Expression value} in the context + * of the MongoDB Query Language (MQL). Tracks a UTC datetime, the number of * milliseconds since the Unix epoch. Does not track the timezone. */ public interface DateExpression extends Expression { diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java b/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java index 49146555ac1..5b29c5615bb 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java @@ -21,12 +21,68 @@ import java.util.function.Function; /** - *

Users should treat these interfaces as sealed, and must not implement any - * sub-interfaces. + * A value in the context of the MongoDB Query Language (MQL). * - * TODO-END: 'cause an error', 'execution context', wrong types/unsafe operations - * TODO-END: types and how missing/null are not part of any type. - * TODO-END: behaviour of equals + *

The API provided by this base type and its subtypes is the Java-native + * variant of MQL. It is used to query the MongoDB server, to perform remote + * computations, to store and retrieve data, or to otherwise work with data + * on a MongoDB server or compatible execution context. + * + *

The following is an example of usage within an aggregation pipeline. Here, + * the current document value is obtained and its "numberArray" field is + * filtered and summed, in a style similar to that of the Java Stream API: + * + *

{@code
+ * AggregateIterable result = col.aggregate(Arrays.asList(
+ *     addFields(new Field<>("result", current()
+ *         .getArray("numberArray")
+ *         .filter(v -> v.gt(of(0)))
+ *         .sum(v -> v)))));
+ * }
+ * + *

Values are typically obtained via the current document and its fields, or + * specified via statically-imported methods on the {@link Expressions} class. + * + *

The null value is not part of, and cannot be used as if it were part of, + * any other type. It has no explicit type of its own. Instead of checking for + * null, users should check for their expected type, via methods such as + * {@link Expression#isNumberOr(NumberExpression)}. Where the null value must + * be checked explicitly, users may use {@link Branches#isNull} within + * {@link Expression#switchOn}. + * + *

There is no explicit "missing" or "undefined" value. Users may use + * {@link DocumentExpression#has}. + * + *

This type hierarchy differs from BSON in that it provides operations, + * while the BSON API does not, its numeric types are less granular, and it + * offers multiple abstractions of certain types (document, map, entry). It + * differs from Java types in that the operations available differ, and in that + * an implementation of this API may be used to be used to generate MQL in the + * form of BSON. (This API makes no guarantee regarding the BSON output produced + * by its implementation, which in any case may vary due to optimization or + * other factors.) + * + *

This API is a language binding in the sense that it exposes the operations + * available on the MongoDB server or compatible execution context, and the + * implied corresponding data types, through a Java API. The methods exposed + * through this API correspond to MQL operations, though this correspondence + * is not exact. + * + *

Some methods within the API constitute an assertion by the user that the + * data is of a certain type. For example, {@link DocumentExpression#getArray}} + * requires that the underlying field is both an array, and an array of some + * certain type. If the field is not an array in the underlying data, behaviour + * is undefined by this API (though behaviours may be defined by the execution + * context, users are strongly discouraged from relying on behaviour that is not + * part of this API). + * + *

As with the Java Stream API's terminal operations, corresponding Java + * values are not directly available, but must be obtained indirectly via the + * aggregation pipeline, or via find. Certain methods may cause an error, which + * will be produced through these "terminal operations". + * + *

Users should treat these interfaces as sealed, and should not create + * implementations. * * @see Expressions */ @@ -35,9 +91,8 @@ public interface Expression { /** * The method {@link Expression#eq} should be used to compare values for - * equality. + * equality. This method checks reference equality. */ - @Deprecated // TODO-END (?)

Marked deprecated to prevent erroneous use. @Override boolean equals(Object other); @@ -54,6 +109,8 @@ public interface Expression { /** * Whether {@code this} value is not equal to the {@code other} value. * + *

The result does not correlate with {@link Expression#equals(Object)}. + * * @param other the other value. * @return the resulting value. */ @@ -94,7 +151,7 @@ public interface Expression { BooleanExpression lte(Expression other); /** - * {@code this} value as a {@link BooleanExpression boolean} if + * {@code this} value as a {@linkplain BooleanExpression boolean} if * {@code this} is a boolean, or the {@code other} boolean value if * {@code this} is null, or is missing, or is of any other non-boolean type. * @@ -104,7 +161,7 @@ public interface Expression { BooleanExpression isBooleanOr(BooleanExpression other); /** - * {@code this} value as a {@link NumberExpression number} if + * {@code this} value as a {@linkplain NumberExpression number} if * {@code this} is a number, or the {@code other} number value if * {@code this} is null, or is missing, or is of any other non-number type. * @@ -114,7 +171,7 @@ public interface Expression { NumberExpression isNumberOr(NumberExpression other); /** - * {@code this} value as an {@link IntegerExpression integer} if + * {@code this} value as an {@linkplain IntegerExpression integer} if * {@code this} is an integer, or the {@code other} integer value if * {@code this} is null, or is missing, or is of any other non-integer type. * @@ -124,7 +181,7 @@ public interface Expression { IntegerExpression isIntegerOr(IntegerExpression other); /** - * {@code this} value as a {@link StringExpression string} if + * {@code this} value as a {@linkplain StringExpression string} if * {@code this} is a string, or the {@code other} string value if * {@code this} is null, or is missing, or is of any other non-string type. * @@ -134,7 +191,7 @@ public interface Expression { StringExpression isStringOr(StringExpression other); /** - * {@code this} value as a {@link DateExpression boolean} if + * {@code this} value as a {@linkplain DateExpression boolean} if * {@code this} is a date, or the {@code other} date value if * {@code this} is null, or is missing, or is of any other non-date type. * @@ -145,7 +202,7 @@ public interface Expression { /** - * {@code this} value as a {@link ArrayExpression array} if + * {@code this} value as a {@linkplain ArrayExpression array} if * {@code this} is an array, or the {@code other} array value if * {@code this} is null, or is missing, or is of any other non-array type. * @@ -169,15 +226,16 @@ public interface Expression { MapExpression isMapOr(MapExpression other); /** - * The {@link StringExpression string} representation of {@code this} value. + * The {@linkplain StringExpression string} representation of {@code this} value. * - *

This may "cause an error" if the type cannot be converted to string, - * as is the case with {@link ArrayExpression arrays}, - * {@link DocumentExpression documents}, and {@link MapExpression maps}. - * TODO-END what about null/missing? - * TODO-END document vs record - * TODO-END "cause an error" above + *

This may cause an error to be produced if the type cannot be converted + * to a {@linkplain StringExpression string}, as is the case with + * {@linkplain ArrayExpression arrays}, + * {@linkplain DocumentExpression documents}, + * {@linkplain MapExpression maps}, and + * {@linkplain EntryExpression entries}. * + * TODO-END what about null/missing? * * @see StringExpression#parseDate() * @see StringExpression#parseInteger() diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/Expressions.java b/driver-core/src/main/com/mongodb/client/model/expressions/Expressions.java index 132d0fa03c1..4a40ca25eaf 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/Expressions.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/Expressions.java @@ -39,31 +39,25 @@ import static com.mongodb.client.model.expressions.MqlExpression.extractBsonValue; /** - * Convenience methods related to {@link Expression}. + * Convenience methods related to {@link Expression}, used primarily to + * produce values in the context of the MongoDB Query Language (MQL). */ public final class Expressions { private Expressions() {} /** - * Returns an expression having the same boolean value as the provided - * boolean primitive. + * Returns a {@linkplain BooleanExpression boolean} value corresponding to + * the provided boolean primitive. * - * @param of the boolean primitive - * @return the boolean expression + * @param of the boolean primitive. + * @return the resulting value. */ public static BooleanExpression of(final boolean of) { // we intentionally disallow ofBoolean(null) return new MqlExpression<>((codecRegistry) -> new AstPlaceholder(new BsonBoolean(of))); } - /** - * Returns an array expression containing the same boolean values as the - * provided array of booleans. - * - * @param array the array of booleans - * @return the boolean array expression - */ public static ArrayExpression ofBooleanArray(final boolean... array) { Assertions.notNull("array", array); List list = new ArrayList<>(); @@ -74,11 +68,11 @@ public static ArrayExpression ofBooleanArray(final boolean... } /** - * Returns an expression having the same integer value as the provided - * int primitive. + * Returns an {@linkplain IntegerExpression integer} value corresponding to + * the provided int primitive. * - * @param of the int primitive - * @return the integer expression + * @param of the int primitive. + * @return the resulting value. */ public static IntegerExpression of(final int of) { return new MqlExpression<>((codecRegistry) -> new AstPlaceholder(new BsonInt32(of))); @@ -93,6 +87,13 @@ public static ArrayExpression ofIntegerArray(final int... arr return new MqlExpression<>((cr) -> new AstPlaceholder(new BsonArray(list))); } + /** + * Returns an {@linkplain IntegerExpression integer} value corresponding to + * the provided long primitive. + * + * @param of the long primitive. + * @return the resulting value. + */ public static IntegerExpression of(final long of) { return new MqlExpression<>((codecRegistry) -> new AstPlaceholder(new BsonInt64(of))); } @@ -106,6 +107,13 @@ public static ArrayExpression ofIntegerArray(final long... ar return new MqlExpression<>((cr) -> new AstPlaceholder(new BsonArray(list))); } + /** + * Returns a {@linkplain NumberExpression number} value corresponding to + * the provided double primitive. + * + * @param of the double primitive. + * @return the resulting value. + */ public static NumberExpression of(final double of) { return new MqlExpression<>((codecRegistry) -> new AstPlaceholder(new BsonDouble(of))); } @@ -119,6 +127,13 @@ public static ArrayExpression ofNumberArray(final double... ar return new MqlExpression<>((cr) -> new AstPlaceholder(new BsonArray(list))); } + /** + * Returns a {@linkplain NumberExpression number} value corresponding to + * the provided Decimal128. + * + * @param of the Decimal128. + * @return the resulting value. + */ public static NumberExpression of(final Decimal128 of) { Assertions.notNull("Decimal128", of); return new MqlExpression<>((codecRegistry) -> new AstPlaceholder(new BsonDecimal128(of))); @@ -134,6 +149,14 @@ public static ArrayExpression ofNumberArray(final Decimal128.. return new MqlExpression<>((cr) -> new AstPlaceholder(new BsonArray(result))); } + + /** + * Returns a {@linkplain DateExpression date and time} value corresponding to + * the provided Instant. + * + * @param of the instant. + * @return the resulting value. + */ public static DateExpression of(final Instant of) { Assertions.notNull("Instant", of); return new MqlExpression<>((codecRegistry) -> new AstPlaceholder(new BsonDateTime(of.toEpochMilli()))); @@ -150,18 +173,17 @@ public static ArrayExpression ofDateArray(final Instant... array } /** - * Returns an expression having the same string value as the provided - * string. + * Returns an {@linkplain StringExpression string} value corresponding to + * the provided string. * - * @param of the string - * @return the string expression + * @param of the string. + * @return the resulting value. */ public static StringExpression of(final String of) { Assertions.notNull("String", of); return new MqlExpression<>((codecRegistry) -> new AstPlaceholder(new BsonString(of))); } - public static ArrayExpression ofStringArray(final String... array) { Assertions.notNull("array", array); List result = new ArrayList<>(); @@ -172,6 +194,13 @@ public static ArrayExpression ofStringArray(final String... ar return new MqlExpression<>((cr) -> new AstPlaceholder(new BsonArray(result))); } + /** + * Returns the current or root {@linkplain DocumentExpression document} value, + * the top-level document, currently being processed in the aggregation + * pipeline stage. + * + * @return the resulting value + */ public static DocumentExpression current() { return new MqlExpression<>((cr) -> new AstPlaceholder(new BsonString("$$CURRENT"))) .assertImplementsAllExpressions(); @@ -182,6 +211,14 @@ public static MapExpression currentAsMap() { .assertImplementsAllExpressions(); } + /** + * Returns an {@linkplain DocumentExpression array} value, containing the + * values provided. + * + * @param array the values provided. + * @return the resulting value. + * @param the type of the array elements. + */ @SafeVarargs // nothing is stored in the array public static ArrayExpression ofArray(final T... array) { Assertions.notNull("array", array); @@ -195,6 +232,17 @@ public static ArrayExpression ofArray(final T... array }); } + /** + * Returns an {@linkplain EntryExpression entry} value. An entry is a key + * and a value, and is used with {@linkplain MapExpression maps}. An entry + * value may be equal to a document value with a field "k" equal to the + * entry's key and a field "v" equal to the entry's value. + * + * @param k the key. + * @param v the value. + * @return the resulting value. + * @param the type of the key. + */ public static EntryExpression ofEntry(final StringExpression k, final T v) { Assertions.notNull("k", k); Assertions.notNull("v", v); @@ -211,11 +259,13 @@ public static MapExpression ofMap() { } /** - * user asserts type of values is T + * Returns a {@linkplain MapExpression map} value corresponding to the + * provided BSON document. The user asserts that all values in the document + * are of type {@code T}. * - * @param map - * @return - * @param + * @param map the map as BSON. + * @return the resulting value. + * @param the type of the resulting map's values. */ public static MapExpression ofMap(final Bson map) { Assertions.notNull("map", map); @@ -223,6 +273,13 @@ public static MapExpression ofMap(final Bson map) { map.toBsonDocument(BsonDocument.class, cr)))); } + /** + * Returns a {@linkplain DocumentExpression document} value corresponding to the + * provided BSON document. + * + * @param document the document as BSON. + * @return the resulting value. + */ public static DocumentExpression of(final Bson document) { Assertions.notNull("document", document); // All documents are wrapped in a $literal. If we don't wrap, we need to @@ -232,6 +289,18 @@ public static DocumentExpression of(final Bson document) { document.toBsonDocument(BsonDocument.class, cr)))); } + /** + * The null value in the context of the MongoDB Query Language (MQL). + * + *

The null value is not part of, and cannot be used as if it were part of, + * any other type. It has no explicit type of its own. Instead of checking for + * null, users should check for their expected type, via methods such as + * {@link Expression#isNumberOr(NumberExpression)}. Where the null value must + * be checked explicitly, users may use {@link Branches#isNull} within + * {@link Expression#switchOn}. + * + * @return the null value + */ public static Expression ofNull() { // There is no specific expression type corresponding to Null, // and Null is not a value in any other expression type. diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/IntegerExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/IntegerExpression.java index 9e7bac51bae..e0705f4dce8 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/IntegerExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/IntegerExpression.java @@ -19,9 +19,10 @@ import java.util.function.Function; /** - * An integer value. Integers are a subset of {@link NumberExpression numbers}, - * and so, for example, the integer 0 and the number 0 are the same value, - * and are equal. + * An integer {@linkplain Expression value} in the context of the MongoDB Query + * Language (MQL). Integers are a subset of {@linkplain NumberExpression numbers}, + * and so, for example, the integer 0 and the number 0 are + * {@linkplain #eq(Expression) equal}. */ public interface IntegerExpression extends NumberExpression { @@ -80,7 +81,8 @@ default IntegerExpression subtract(final int other) { } /** - * The larger value of {@code this} and the {@code other} value. + * The {@linkplain #gt(Expression) larger} value of {@code this} + * and the {@code other} value. * * @param other the other value. * @return the resulting value. @@ -88,7 +90,8 @@ default IntegerExpression subtract(final int other) { IntegerExpression max(IntegerExpression other); /** - * The smaller value of {@code this} and the {@code other} value. + * The {@linkplain #lt(Expression) smaller} value of {@code this} + * and the {@code other} value. * * @param other the other value. * @return the resulting value. @@ -103,7 +106,7 @@ default IntegerExpression subtract(final int other) { IntegerExpression abs(); /** - * The {@link DateExpression date} corresponding to {@code this} value + * The {@linkplain DateExpression date} corresponding to {@code this} value * when taken to be the number of milliseconds since the Unix epoch. * * @return the resulting value. diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/NumberExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/NumberExpression.java index 52f882ae9f8..2156a0f8068 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/NumberExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/NumberExpression.java @@ -19,9 +19,10 @@ import java.util.function.Function; /** - * A number value. {@link IntegerExpression Integers} are a subset of numbers, - * and so, for example, the integer 0 and the number 0 are the same value, - * and are equal. + * A number {@linkplain Expression value} in the context of the MongoDB Query + * Language (MQL). {@linkplain IntegerExpression Integers} are a subset of + * numbers, and so, for example, the integer 0 and the number 0 are + * {@linkplain #eq(Expression) equal}. */ public interface NumberExpression extends Expression { @@ -102,7 +103,8 @@ default NumberExpression subtract(final Number other) { } /** - * The larger value of {@code this} and the {@code other} value. + * The {@linkplain #gt(Expression) larger} value of {@code this} + * and the {@code other} value. * * @param other the other value. * @return the resulting value. @@ -110,7 +112,8 @@ default NumberExpression subtract(final Number other) { NumberExpression max(NumberExpression other); /** - * The smaller value of {@code this} and the {@code other} value. + * The {@linkplain #lt(Expression) smaller} value of {@code this} + * and the {@code other} value. * * @param other the other value. * @return the resulting value. From e545c90edcdada8198ddfb7bf21af23c4bb0f1a4 Mon Sep 17 00:00:00 2001 From: Maxim Katcharov Date: Fri, 13 Jan 2023 12:25:26 -0700 Subject: [PATCH 03/11] Fixes --- .../model/expressions/BooleanExpression.java | 10 +-- .../client/model/expressions/Expressions.java | 69 +++++++++++-------- .../model/expressions/IntegerExpression.java | 4 +- .../model/expressions/MqlExpression.java | 4 +- .../model/expressions/NumberExpression.java | 16 ++--- 5 files changed, 59 insertions(+), 44 deletions(-) diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/BooleanExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/BooleanExpression.java index 8cb59611e4a..9c08bf1a93c 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/BooleanExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/BooleanExpression.java @@ -49,15 +49,15 @@ public interface BooleanExpression extends Expression { // TODO-END check the evaluation semantics of and/or /** - * The {@code left} branch when {@code this} is true, - * and the {@code right} branch otherwise. + * The {@code ifTrue} value when {@code this} is true, + * and the {@code ifFalse} value otherwise. * - * @param left the left value. - * @param right the right value. + * @param ifTrue the ifTrue value. + * @param ifFalse the ifFalse value. * @return the resulting value. * @param The type of the resulting expression. */ - T cond(T left, T right); + T cond(T ifTrue, T ifFalse); R passBooleanTo(Function f); diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/Expressions.java b/driver-core/src/main/com/mongodb/client/model/expressions/Expressions.java index 4a40ca25eaf..9912e8c2eb1 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/Expressions.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/Expressions.java @@ -48,9 +48,9 @@ private Expressions() {} /** * Returns a {@linkplain BooleanExpression boolean} value corresponding to - * the provided boolean primitive. + * the provided {@code boolean} primitive. * - * @param of the boolean primitive. + * @param of the {@code boolean} primitive. * @return the resulting value. */ public static BooleanExpression of(final boolean of) { @@ -69,9 +69,9 @@ public static ArrayExpression ofBooleanArray(final boolean... /** * Returns an {@linkplain IntegerExpression integer} value corresponding to - * the provided int primitive. + * the provided {@code int} primitive. * - * @param of the int primitive. + * @param of the {@code int} primitive. * @return the resulting value. */ public static IntegerExpression of(final int of) { @@ -89,9 +89,9 @@ public static ArrayExpression ofIntegerArray(final int... arr /** * Returns an {@linkplain IntegerExpression integer} value corresponding to - * the provided long primitive. + * the provided {@code long} primitive. * - * @param of the long primitive. + * @param of the {@code long} primitive. * @return the resulting value. */ public static IntegerExpression of(final long of) { @@ -109,9 +109,9 @@ public static ArrayExpression ofIntegerArray(final long... ar /** * Returns a {@linkplain NumberExpression number} value corresponding to - * the provided double primitive. + * the provided {@code double} primitive. * - * @param of the double primitive. + * @param of the {@code double} primitive. * @return the resulting value. */ public static NumberExpression of(final double of) { @@ -129,9 +129,9 @@ public static ArrayExpression ofNumberArray(final double... ar /** * Returns a {@linkplain NumberExpression number} value corresponding to - * the provided Decimal128. + * the provided {@link Decimal128} * - * @param of the Decimal128. + * @param of the {@link Decimal128}. * @return the resulting value. */ public static NumberExpression of(final Decimal128 of) { @@ -152,9 +152,9 @@ public static ArrayExpression ofNumberArray(final Decimal128.. /** * Returns a {@linkplain DateExpression date and time} value corresponding to - * the provided Instant. + * the provided {@link Instant}. * - * @param of the instant. + * @param of the {@link Instant}. * @return the resulting value. */ public static DateExpression of(final Instant of) { @@ -174,9 +174,9 @@ public static ArrayExpression ofDateArray(final Instant... array /** * Returns an {@linkplain StringExpression string} value corresponding to - * the provided string. + * the provided {@link String}. * - * @param of the string. + * @param of the {@link String}. * @return the resulting value. */ public static StringExpression of(final String of) { @@ -195,9 +195,9 @@ public static ArrayExpression ofStringArray(final String... ar } /** - * Returns the current or root {@linkplain DocumentExpression document} value, - * the top-level document, currently being processed in the aggregation - * pipeline stage. + * Returns the "current" {@linkplain DocumentExpression document} value. + * The "current" value is the top-level document currently being processed + * in the aggregation pipeline stage. * * @return the resulting value */ @@ -211,11 +211,24 @@ public static MapExpression currentAsMap() { .assertImplementsAllExpressions(); } + /** + * Returns the "current" value as a {@linkplain MapExpression map} value. + * The "current" value is the top-level document currently being processed + * in the aggregation pipeline stage. + * + * @return the resulting value + * @param the type of the resulting value + */ + public static MapExpression currentAsMap() { + return new MqlExpression<>((cr) -> new AstPlaceholder(new BsonString("$$CURRENT"))) + .assertImplementsAllExpressions(); + } + /** * Returns an {@linkplain DocumentExpression array} value, containing the - * values provided. + * {@linkplain Expression values} provided. * - * @param array the values provided. + * @param array the {@linkplain Expression values}. * @return the resulting value. * @param the type of the array elements. */ @@ -233,8 +246,10 @@ public static ArrayExpression ofArray(final T... array } /** - * Returns an {@linkplain EntryExpression entry} value. An entry is a key - * and a value, and is used with {@linkplain MapExpression maps}. An entry + * Returns an {@linkplain EntryExpression entry} value. An entry is a + * {@linkplain StringExpression string} key and some + * {@linkplain Expression value}. Entries are used with + * {@linkplain MapExpression maps}. An entry * value may be equal to a document value with a field "k" equal to the * entry's key and a field "v" equal to the entry's value. * @@ -260,11 +275,11 @@ public static MapExpression ofMap() { /** * Returns a {@linkplain MapExpression map} value corresponding to the - * provided BSON document. The user asserts that all values in the document - * are of type {@code T}. + * provided {@link Bson Bson document}. The user asserts that all values + * in the document are of type {@code T}. * - * @param map the map as BSON. - * @return the resulting value. + * @param map the map as a {@link Bson Bson document}. + * @return the resulting map value. * @param the type of the resulting map's values. */ public static MapExpression ofMap(final Bson map) { @@ -275,9 +290,9 @@ public static MapExpression ofMap(final Bson map) { /** * Returns a {@linkplain DocumentExpression document} value corresponding to the - * provided BSON document. + * provided {@link Bson Bson document}. * - * @param document the document as BSON. + * @param document the {@link Bson Bson document}. * @return the resulting value. */ public static DocumentExpression of(final Bson document) { diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/IntegerExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/IntegerExpression.java index e0705f4dce8..555ec3369ae 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/IntegerExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/IntegerExpression.java @@ -63,7 +63,7 @@ default IntegerExpression add(final int other) { } /** - * The result of subtracting the {@code other} value from {@code this}. + * The difference of subtracting the {@code other} value from {@code this}. * * @param other the other value. * @return the resulting value. @@ -71,7 +71,7 @@ default IntegerExpression add(final int other) { IntegerExpression subtract(IntegerExpression other); /** - * The result of subtracting the {@code other} value from {@code this}. + * The difference of subtracting the {@code other} value from {@code this}. * * @param other the other value. * @return the resulting value. diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/MqlExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/MqlExpression.java index a1d923c8be2..69330fc8f54 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/MqlExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/MqlExpression.java @@ -155,8 +155,8 @@ public BooleanExpression and(final BooleanExpression other) { } @Override - public R cond(final R left, final R right) { - return newMqlExpression(ast("$cond", left, right)); + public R cond(final R ifTrue, final R ifFalse) { + return newMqlExpression(ast("$cond", ifTrue, ifFalse)); } /** @see DocumentExpression */ diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/NumberExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/NumberExpression.java index 2156a0f8068..a0ab8959d0f 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/NumberExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/NumberExpression.java @@ -45,9 +45,9 @@ default NumberExpression multiply(final Number other) { } /** - * The result of dividing {@code this} value by the {@code other} value. - * This is not integer division: dividing {@code 1} by {@code 2} will yield - * {@code 0.5}. + * The quotient of dividing {@code this} value by the {@code other} value. + * This is not integer division: dividing {@code 1} by {@code 2} will + * always yield {@code 0.5}. * * @param other the other value. * @return the resulting value. @@ -55,9 +55,9 @@ default NumberExpression multiply(final Number other) { NumberExpression divide(NumberExpression other); /** - * The result of dividing {@code this} value by the {@code other} value. - * This is not integer division: dividing {@code 1} by {@code 2} will yield - * {@code 0.5}. + * The quotient of dividing {@code this} value by the {@code other} value. + * This is not integer division: dividing {@code 1} by {@code 2} will + * always yield {@code 0.5}. * * @param other the other value. * @return the resulting value. @@ -85,7 +85,7 @@ default NumberExpression add(final Number other) { } /** - * The result of subtracting the {@code other} value from {@code this}. + * The difference of subtracting the {@code other} value from {@code this}. * * @param other the other value. * @return the resulting value. @@ -93,7 +93,7 @@ default NumberExpression add(final Number other) { NumberExpression subtract(NumberExpression other); /** - * The result of subtracting the {@code other} value from {@code this}. + * The difference of subtracting the {@code other} value from {@code this}. * * @param other the other value. * @return the resulting value. From 45f75f5f2b58cae0742a9c54a652233d14368f85 Mon Sep 17 00:00:00 2001 From: Maxim Katcharov Date: Mon, 16 Jan 2023 09:55:14 -0700 Subject: [PATCH 04/11] Doc fixes --- .../model/expressions/ArrayExpression.java | 2 +- .../model/expressions/DateExpression.java | 6 +-- .../model/expressions/EntryExpression.java | 10 ++++ .../client/model/expressions/Expression.java | 53 +++++++++---------- .../client/model/expressions/Expressions.java | 40 ++++++-------- .../model/expressions/package-info.java | 1 + 6 files changed, 57 insertions(+), 55 deletions(-) diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/ArrayExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/ArrayExpression.java index 90fd498c1eb..300965a4d7b 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/ArrayExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/ArrayExpression.java @@ -37,7 +37,7 @@ public interface ArrayExpression extends Expression { * it should be included. * @return the resulting array. */ - ArrayExpression filter(Function cond); + ArrayExpression filter(Function predicate); /** * An array consisting of the results of applying the provided function to diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/DateExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/DateExpression.java index 83bc09de0e2..60c77f4c81f 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/DateExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/DateExpression.java @@ -19,9 +19,9 @@ import java.util.function.Function; /** - * An instantaneous date and time {@linkplain Expression value} in the context - * of the MongoDB Query Language (MQL). Tracks a UTC datetime, the number of - * milliseconds since the Unix epoch. Does not track the timezone. + * A UTC date-time {@linkplain Expression value} in the context + * of the MongoDB Query Language (MQL). Tracks the number of + * milliseconds since the Unix epoch, and does not track the timezone. */ public interface DateExpression extends Expression { diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/EntryExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/EntryExpression.java index 6fda24588c6..26441c36f41 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/EntryExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/EntryExpression.java @@ -18,6 +18,16 @@ import static com.mongodb.client.model.expressions.Expressions.of; +/** + * A map entry {@linkplain Expression value} in the context + * of the MongoDB Query Language (MQL). An entry has a + * {@linkplain StringExpression string} key and some + * {@linkplain Expression value}. Entries are used with + * {@linkplain MapExpression maps}. An entry + * value may be equal to a document value with a field "k" equal to the + * entry's key and a field "v" equal to the entry's value. + * @param + */ public interface EntryExpression extends Expression { StringExpression getKey(); diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java b/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java index 5b29c5615bb..ff015ce8d9b 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java @@ -25,14 +25,18 @@ * *

The API provided by this base type and its subtypes is the Java-native * variant of MQL. It is used to query the MongoDB server, to perform remote - * computations, to store and retrieve data, or to otherwise work with data - * on a MongoDB server or compatible execution context. + * computations, to store and retrieve data, or to otherwise work with data on + * a MongoDB server or compatible execution context. Though the methods exposed + * through this API generally correspond to MQL operations, this correspondence + * is not exact. * *

The following is an example of usage within an aggregation pipeline. Here, * the current document value is obtained and its "numberArray" field is * filtered and summed, in a style similar to that of the Java Stream API: * *

{@code
+ * import static com.mongodb.client.model.expressions.Expressions.current;
+ * MongoCollection col = ...;
  * AggregateIterable result = col.aggregate(Arrays.asList(
  *     addFields(new Field<>("result", current()
  *         .getArray("numberArray")
@@ -40,33 +44,30 @@
  *         .sum(v -> v)))));
  * }
* - *

Values are typically obtained via the current document and its fields, or - * specified via statically-imported methods on the {@link Expressions} class. + *

Values are typically initially obtained via the current document and its + * fields, or specified via statically-imported methods on the + * {@link Expressions} class. + * + *

As with the Java Stream API's terminal operations, corresponding Java + * values are not directly available, but must be obtained indirectly via the + * aggregation pipeline, or via find. Certain methods may cause an error, which + * will be produced through these "terminal operations". * *

The null value is not part of, and cannot be used as if it were part of, - * any other type. It has no explicit type of its own. Instead of checking for - * null, users should check for their expected type, via methods such as - * {@link Expression#isNumberOr(NumberExpression)}. Where the null value must - * be checked explicitly, users may use {@link Branches#isNull} within - * {@link Expression#switchOn}. + * any other type. See {@link Expressions#ofNull} for more details. * *

There is no explicit "missing" or "undefined" value. Users may use - * {@link DocumentExpression#has}. + * {@link MapExpression#has} or {@link DocumentExpression#has}. * - *

This type hierarchy differs from BSON in that it provides operations, - * while the BSON API does not, its numeric types are less granular, and it - * offers multiple abstractions of certain types (document, map, entry). It - * differs from Java types in that the operations available differ, and in that - * an implementation of this API may be used to be used to generate MQL in the - * form of BSON. (This API makes no guarantee regarding the BSON output produced - * by its implementation, which in any case may vary due to optimization or - * other factors.) - * - *

This API is a language binding in the sense that it exposes the operations - * available on the MongoDB server or compatible execution context, and the - * implied corresponding data types, through a Java API. The methods exposed - * through this API correspond to MQL operations, though this correspondence - * is not exact. + *

This type hierarchy differs from the {@linkplain org.bson} types in that + * they provide computational operations, the numeric types are less granular, + * and it offers multiple abstractions of certain types (document, map, entry). + * It differs from the corresponding Java types (such as {@code int}, + * {@link String}, {@link java.util.Map) in that the operations + * available differ, and in that an implementation of this API may be used to + * produce MQL in the form of BSON. (This API makes no guarantee regarding the + * BSON output produced by its implementation, which in any case may vary due + * to optimization or other factors.) * *

Some methods within the API constitute an assertion by the user that the * data is of a certain type. For example, {@link DocumentExpression#getArray}} @@ -76,10 +77,6 @@ * context, users are strongly discouraged from relying on behaviour that is not * part of this API). * - *

As with the Java Stream API's terminal operations, corresponding Java - * values are not directly available, but must be obtained indirectly via the - * aggregation pipeline, or via find. Certain methods may cause an error, which - * will be produced through these "terminal operations". * *

Users should treat these interfaces as sealed, and should not create * implementations. diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/Expressions.java b/driver-core/src/main/com/mongodb/client/model/expressions/Expressions.java index 9912e8c2eb1..ad43dead676 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/Expressions.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/Expressions.java @@ -195,31 +195,28 @@ public static ArrayExpression ofStringArray(final String... ar } /** - * Returns the "current" {@linkplain DocumentExpression document} value. + * Returns a reference to the "current" + * {@linkplain DocumentExpression document} value. * The "current" value is the top-level document currently being processed * in the aggregation pipeline stage. * - * @return the resulting value + * @return a reference to the current value */ public static DocumentExpression current() { return new MqlExpression<>((cr) -> new AstPlaceholder(new BsonString("$$CURRENT"))) .assertImplementsAllExpressions(); } - public static MapExpression currentAsMap() { - return new MqlExpression<>((cr) -> new AstPlaceholder(new BsonString("$$CURRENT"))) - .assertImplementsAllExpressions(); - } - /** - * Returns the "current" value as a {@linkplain MapExpression map} value. + * Returns a reference to the "current" + * value as a {@linkplain MapExpression map} value. * The "current" value is the top-level document currently being processed * in the aggregation pipeline stage. * - * @return the resulting value - * @param the type of the resulting value + * @return a reference to the current value as a map. + * @param the type of the map's values. */ - public static MapExpression currentAsMap() { + public static MapExpression currentAsMap() { return new MqlExpression<>((cr) -> new AstPlaceholder(new BsonString("$$CURRENT"))) .assertImplementsAllExpressions(); } @@ -246,12 +243,7 @@ public static ArrayExpression ofArray(final T... array } /** - * Returns an {@linkplain EntryExpression entry} value. An entry is a - * {@linkplain StringExpression string} key and some - * {@linkplain Expression value}. Entries are used with - * {@linkplain MapExpression maps}. An entry - * value may be equal to a document value with a field "k" equal to the - * entry's key and a field "v" equal to the entry's value. + * Returns an {@linkplain EntryExpression entry} value. * * @param k the key. * @param v the value. @@ -292,7 +284,7 @@ public static MapExpression ofMap(final Bson map) { * Returns a {@linkplain DocumentExpression document} value corresponding to the * provided {@link Bson Bson document}. * - * @param document the {@link Bson Bson document}. + * @param document the {@linkplain Bson BSON document}. * @return the resulting value. */ public static DocumentExpression of(final Bson document) { @@ -307,11 +299,13 @@ public static DocumentExpression of(final Bson document) { /** * The null value in the context of the MongoDB Query Language (MQL). * - *

The null value is not part of, and cannot be used as if it were part of, - * any other type. It has no explicit type of its own. Instead of checking for - * null, users should check for their expected type, via methods such as - * {@link Expression#isNumberOr(NumberExpression)}. Where the null value must - * be checked explicitly, users may use {@link Branches#isNull} within + *

The null value is not part of, and cannot be used as if it were part + * of, any other type. It has no explicit type of its own. + * + *

Instead of checking that a value is null, users should generally + * check that a value is of their expected type, via methods such as + * {@link Expression#isNumberOr(NumberExpression)}. Where the null value + * must be checked explicitly, users may use {@link Branches#isNull} within * {@link Expression#switchOn}. * * @return the null value diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/package-info.java b/driver-core/src/main/com/mongodb/client/model/expressions/package-info.java index 596d642e654..f9b52b24897 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/package-info.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/package-info.java @@ -18,6 +18,7 @@ * API for MQL expressions. * * @see com.mongodb.client.model.expressions.Expression + * @see com.mongodb.client.model.expressions.Expressions */ @NonNullApi package com.mongodb.client.model.expressions; From 8419928351b718515bc7337dcfc015f3aedb4834 Mon Sep 17 00:00:00 2001 From: Maxim Katcharov Date: Mon, 16 Jan 2023 17:10:44 -0700 Subject: [PATCH 05/11] Fixes --- .../mongodb/client/model/expressions/Expression.java | 12 +++++++----- .../client/model/expressions/Expressions.java | 3 ++- .../client/model/expressions/NumberExpression.java | 3 ++- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java b/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java index ff015ce8d9b..b70b7b27162 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java @@ -49,12 +49,14 @@ * {@link Expressions} class. * *

As with the Java Stream API's terminal operations, corresponding Java - * values are not directly available, but must be obtained indirectly via the - * aggregation pipeline, or via find. Certain methods may cause an error, which - * will be produced through these "terminal operations". + * values are not directly available, but must be obtained indirectly via + * {@code MongoCollection.aggregate} or {@code MongoCollection.find}. + * Certain methods may cause an error, which will be produced + * through these "terminal operations". * - *

The null value is not part of, and cannot be used as if it were part of, - * any other type. See {@link Expressions#ofNull} for more details. + *

The null value is not part of, and cannot be used as if it were part + * of, any explicit type (except the root type {@link Expression} itself). + * See {@link Expressions#ofNull} for more details. * *

There is no explicit "missing" or "undefined" value. Users may use * {@link MapExpression#has} or {@link DocumentExpression#has}. diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/Expressions.java b/driver-core/src/main/com/mongodb/client/model/expressions/Expressions.java index ad43dead676..e1cabfa10d6 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/Expressions.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/Expressions.java @@ -300,7 +300,8 @@ public static DocumentExpression of(final Bson document) { * The null value in the context of the MongoDB Query Language (MQL). * *

The null value is not part of, and cannot be used as if it were part - * of, any other type. It has no explicit type of its own. + * of, any explicit type (except the root type {@link Expression} itself). + * It has no explicit type of its own. * *

Instead of checking that a value is null, users should generally * check that a value is of their expected type, via methods such as diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/NumberExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/NumberExpression.java index a0ab8959d0f..e177475b2d9 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/NumberExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/NumberExpression.java @@ -128,7 +128,8 @@ default NumberExpression subtract(final Number other) { IntegerExpression round(); /** - * The result of rounding {@code this} to the nearest even {@code place}. + * The result of rounding {@code this} to {@code place} decimal places + * using the "half to even" approach. * * @param place the decimal place to round to, from -20 to 100, exclusive. * Positive values specify the place to the right of the From a015f4a10d0269a29efe60f421bea9d262357759 Mon Sep 17 00:00:00 2001 From: Maxim Katcharov Date: Tue, 17 Jan 2023 14:59:15 -0700 Subject: [PATCH 06/11] Update docs. --- .../mongodb/client/model/expressions/EntryExpression.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/EntryExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/EntryExpression.java index 26441c36f41..f3f212aa981 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/EntryExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/EntryExpression.java @@ -23,9 +23,8 @@ * of the MongoDB Query Language (MQL). An entry has a * {@linkplain StringExpression string} key and some * {@linkplain Expression value}. Entries are used with - * {@linkplain MapExpression maps}. An entry - * value may be equal to a document value with a field "k" equal to the - * entry's key and a field "v" equal to the entry's value. + * {@linkplain MapExpression maps}. + * * @param */ public interface EntryExpression extends Expression { From 3bed841b283f79fb1a718eb07f9019f6d9fb328d Mon Sep 17 00:00:00 2001 From: Maxim Katcharov Date: Tue, 17 Jan 2023 16:36:21 -0700 Subject: [PATCH 07/11] Update expression variations, fix/remove TODOs --- .../model/expressions/ArrayExpression.java | 20 ++++- .../model/expressions/BooleanExpression.java | 21 ++++- .../model/expressions/DateExpression.java | 23 ++++- .../model/expressions/DocumentExpression.java | 21 ++++- .../model/expressions/EntryExpression.java | 4 +- .../client/model/expressions/Expression.java | 85 +++++++++++++++---- .../model/expressions/IntegerExpression.java | 22 ++++- .../model/expressions/MapExpression.java | 21 ++++- .../model/expressions/NumberExpression.java | 21 ++++- .../model/expressions/StringExpression.java | 21 ++++- 10 files changed, 231 insertions(+), 28 deletions(-) diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/ArrayExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/ArrayExpression.java index 300965a4d7b..674efb3d5a7 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/ArrayExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/ArrayExpression.java @@ -117,7 +117,25 @@ default ArrayExpression slice(final int start, final int length) { ArrayExpression distinct(); + /** + * The result of passing {@code this} value to the provided function. + * Equivalent to {@code f.apply(this)}, and allows lambdas and static, + * user-defined functions to use the chaining syntax. + * + * @see Expression#passTo + * @param f the function to apply. + * @return the resulting value. + * @param the type of the resulting value. + */ R passArrayTo(Function, ? extends R> f); - R switchArrayOn(Function>, ? extends BranchesTerminal, ? extends R>> on); + /** + * The result of applying the provided switch mapping to {@code this} value. + * + * @see Expression#switchOn + * @param mapping the switch mapping. + * @return the resulting value. + * @param the type of the resulting value. + */ + R switchArrayOn(Function>, ? extends BranchesTerminal, ? extends R>> mapping); } diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/BooleanExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/BooleanExpression.java index 9c08bf1a93c..489fecc9a8d 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/BooleanExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/BooleanExpression.java @@ -46,7 +46,6 @@ public interface BooleanExpression extends Expression { * @return the resulting value. */ BooleanExpression and(BooleanExpression other); - // TODO-END check the evaluation semantics of and/or /** * The {@code ifTrue} value when {@code this} is true, @@ -59,7 +58,25 @@ public interface BooleanExpression extends Expression { */ T cond(T ifTrue, T ifFalse); + /** + * The result of passing {@code this} value to the provided function. + * Equivalent to {@code f.apply(this)}, and allows lambdas and static, + * user-defined functions to use the chaining syntax. + * + * @see Expression#passTo + * @param f the function to apply. + * @return the resulting value. + * @param the type of the resulting value. + */ R passBooleanTo(Function f); - R switchBooleanOn(Function, ? extends BranchesTerminal> on); + /** + * The result of applying the provided switch mapping to {@code this} value. + * + * @see Expression#switchOn + * @param mapping the switch mapping. + * @return the resulting value. + * @param the type of the resulting value. + */ + R switchBooleanOn(Function, ? extends BranchesTerminal> mapping); } diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/DateExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/DateExpression.java index 60c77f4c81f..0ddc695bec0 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/DateExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/DateExpression.java @@ -124,11 +124,30 @@ public interface DateExpression extends Expression { * provided {@code timezone}, and formatted according to the {@code format}. * * @param timezone the UTC Offset or Olson Timezone Identifier. - * @param format the format specifier. TODO-END what standard is this? + * @param format the format specifier. * @return the resulting value. */ StringExpression asString(StringExpression timezone, StringExpression format); + /** + * The result of passing {@code this} value to the provided function. + * Equivalent to {@code f.apply(this)}, and allows lambdas and static, + * user-defined functions to use the chaining syntax. + * + * @see Expression#passTo + * @param f the function to apply. + * @return the resulting value. + * @param the type of the resulting value. + */ R passDateTo(Function f); - R switchDateOn(Function, ? extends BranchesTerminal> on); + + /** + * The result of applying the provided switch mapping to {@code this} value. + * + * @see Expression#switchOn + * @param mapping the switch mapping. + * @return the resulting value. + * @param the type of the resulting value. + */ + R switchDateOn(Function, ? extends BranchesTerminal> mapping); } diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/DocumentExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/DocumentExpression.java index 4d7d2ef678f..343a8e7f68d 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/DocumentExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/DocumentExpression.java @@ -102,6 +102,25 @@ default MapExpression getMap(final String fieldName, f MapExpression asMap(); + /** + * The result of passing {@code this} value to the provided function. + * Equivalent to {@code f.apply(this)}, and allows lambdas and static, + * user-defined functions to use the chaining syntax. + * + * @see Expression#passTo + * @param f the function to apply. + * @return the resulting value. + * @param the type of the resulting value. + */ R passDocumentTo(Function f); - R switchDocumentOn(Function, ? extends BranchesTerminal> on); + + /** + * The result of applying the provided switch mapping to {@code this} value. + * + * @see Expression#switchOn + * @param mapping the switch mapping. + * @return the resulting value. + * @param the type of the resulting value. + */ + R switchDocumentOn(Function, ? extends BranchesTerminal> mapping); } diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/EntryExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/EntryExpression.java index f3f212aa981..4bafd935ab9 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/EntryExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/EntryExpression.java @@ -24,8 +24,8 @@ * {@linkplain StringExpression string} key and some * {@linkplain Expression value}. Entries are used with * {@linkplain MapExpression maps}. - * - * @param + * + * @param The type of the value */ public interface EntryExpression extends Expression { StringExpression getKey(); diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java b/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java index b70b7b27162..5d315d77400 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java @@ -199,7 +199,6 @@ public interface Expression { */ DateExpression isDateOr(DateExpression other); - /** * {@code this} value as a {@linkplain ArrayExpression array} if * {@code this} is an array, or the {@code other} array value if @@ -211,7 +210,7 @@ public interface Expression { * the user is an unchecked assertion that all elements are of that type, * and that no element is null, is missing, or is of some other type. If the * user cannot make such an assertion, some appropriate super-type should be - * chosen, and if necessary elements should be individually type-checked. + * chosen, and if necessary the elements should be individually type-checked. * * @param other the other value. * @return the resulting value. @@ -219,9 +218,39 @@ public interface Expression { */ ArrayExpression isArrayOr(ArrayExpression other); - // TODO-END doc after Map merged, "record" and "schema objects" are decided + /** + * {@code this} value as a {@linkplain DocumentExpression document} if + * {@code this} is a document or document-like value (such as a + * {@linkplain MapExpression map} or + * {@linkplain EntryExpression entry}) + * or the {@code other} document value if + * {@code this} is null, or is missing, or is of any other non-document type. + * + * @param other the other value. + * @return the resulting value. + */ T isDocumentOr(T other); + /** + * {@code this} value as a {@linkplain MapExpression map} if + * {@code this} is a map or map-like value (such as a + * {@linkplain DocumentExpression document} or + * {@linkplain EntryExpression entry}) + * or the {@code other} map value if + * {@code this} is null, or is missing, or is of any other non-map type. + * + *

Warning: this operation does not guarantee type safety. While this + * operation is guaranteed to produce a map, the type of the values of + * that array are not guaranteed by the API. The specification of a type by + * the user is an unchecked assertion that all values are of that type, + * and that no value is null of some other type. If the + * user cannot make such an assertion, some appropriate super-type should be + * chosen, and if necessary the values should be individually type-checked. + * + * @param other the other value. + * @return the resulting value. + * @param the type of the values of the resulting map. + */ MapExpression isMapOr(MapExpression other); /** @@ -231,32 +260,41 @@ public interface Expression { * to a {@linkplain StringExpression string}, as is the case with * {@linkplain ArrayExpression arrays}, * {@linkplain DocumentExpression documents}, - * {@linkplain MapExpression maps}, and - * {@linkplain EntryExpression entries}. - * - * TODO-END what about null/missing? + * {@linkplain MapExpression maps}, + * {@linkplain EntryExpression entries}, and the + * {@linkplain Expressions#ofNull() null value}. * * @see StringExpression#parseDate() * @see StringExpression#parseInteger() - * TODO-END all the others? implement? * @return the resulting value. */ StringExpression asString(); /** - * Applies the provided function to {@code this} value. - * - *

Equivalent to {@code f.apply(this)}, and allows lambdas and static, + * The result of passing {@code this} value to the provided function. + * Equivalent to {@code f.apply(this)}, and allows lambdas and static, * user-defined functions to use the chaining syntax. * + *

The appropriate type-based variant should be used when the type + * of {@code this} is known. + * + * @see BooleanExpression#passBooleanTo + * @see IntegerExpression#passIntegerTo + * @see NumberExpression#passNumberTo + * @see StringExpression#passStringTo + * @see DateExpression#passDateTo + * @see ArrayExpression#passArrayTo + * @see MapExpression#passMapTo + * @see DocumentExpression#passDocumentTo + * * @param f the function to apply. * @return the resulting value. * @param the type of the resulting value. */ R passTo(Function f); + /** - * The value resulting from applying the provided switch mapping to - * {@code this} value. + * The result of applying the provided switch mapping to {@code this} value. * *

Can be used to perform pattern matching on the type of {@code this} * value, or to perform comparisons, or to perform any arbitrary check on @@ -264,12 +302,29 @@ public interface Expression { * *

The suggested convention is to use "{@code on}" as the name of the * {@code mapping} parameter, for example: - * {@code myValue.switchOn(on -> on.isInteger(...)...)}. + * + *

{@code
+     * myValue.switchOn(on -> on
+     *     .isInteger(...)
+     *     ...
+     *     .defaults(...))
+     * }
+ * + *

The appropriate type-based variant should be used when the type + * of {@code this} is known. + * + * @see BooleanExpression#switchBooleanOn + * @see IntegerExpression#switchIntegerOn + * @see NumberExpression#switchNumberOn + * @see StringExpression#switchStringOn + * @see DateExpression#switchDateOn + * @see ArrayExpression#switchArrayOn + * @see MapExpression#switchMapOn + * @see DocumentExpression#switchDocumentOn * * @param mapping the switch mapping. * @return the resulting value. * @param the type of the resulting value. */ R switchOn(Function, ? extends BranchesTerminal> mapping); - } diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/IntegerExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/IntegerExpression.java index 555ec3369ae..4757e64eab1 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/IntegerExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/IntegerExpression.java @@ -112,8 +112,26 @@ default IntegerExpression subtract(final int other) { * @return the resulting value. */ DateExpression millisecondsToDate(); - // TODO-END rename integer.utcMillisecondsToDate -- date.asUtcMilliseconds + /** + * The result of passing {@code this} value to the provided function. + * Equivalent to {@code f.apply(this)}, and allows lambdas and static, + * user-defined functions to use the chaining syntax. + * + * @see Expression#passTo + * @param f the function to apply. + * @return the resulting value. + * @param the type of the resulting value. + */ R passIntegerTo(Function f); - R switchIntegerOn(Function, ? extends BranchesTerminal> on); + + /** + * The result of applying the provided switch mapping to {@code this} value. + * + * @see Expression#switchOn + * @param mapping the switch mapping. + * @return the resulting value. + * @param the type of the resulting value. + */ + R switchIntegerOn(Function, ? extends BranchesTerminal> mapping); } diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/MapExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/MapExpression.java index d5d782c7728..d33c1bcf80d 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/MapExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/MapExpression.java @@ -60,6 +60,25 @@ default MapExpression unset(final String key) { R asDocument(); + /** + * The result of passing {@code this} value to the provided function. + * Equivalent to {@code f.apply(this)}, and allows lambdas and static, + * user-defined functions to use the chaining syntax. + * + * @see Expression#passTo + * @param f the function to apply. + * @return the resulting value. + * @param the type of the resulting value. + */ R passMapTo(Function, ? extends R> f); - R switchMapOn(Function>, ? extends BranchesTerminal, ? extends R>> on); + + /** + * The result of applying the provided switch mapping to {@code this} value. + * + * @see Expression#switchOn + * @param mapping the switch mapping. + * @return the resulting value. + * @param the type of the resulting value. + */ + R switchMapOn(Function>, ? extends BranchesTerminal, ? extends R>> mapping); } diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/NumberExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/NumberExpression.java index e177475b2d9..1756ed02318 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/NumberExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/NumberExpression.java @@ -145,6 +145,25 @@ default NumberExpression subtract(final Number other) { */ NumberExpression abs(); + /** + * The result of passing {@code this} value to the provided function. + * Equivalent to {@code f.apply(this)}, and allows lambdas and static, + * user-defined functions to use the chaining syntax. + * + * @see Expression#passTo + * @param f the function to apply. + * @return the resulting value. + * @param the type of the resulting value. + */ R passNumberTo(Function f); - R switchNumberOn(Function, ? extends BranchesTerminal> on); + + /** + * The result of applying the provided switch mapping to {@code this} value. + * + * @see Expression#switchOn + * @param mapping the switch mapping. + * @return the resulting value. + * @param the type of the resulting value. + */ + R switchNumberOn(Function, ? extends BranchesTerminal> mapping); } diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/StringExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/StringExpression.java index f4990b54949..633a99baba0 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/StringExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/StringExpression.java @@ -55,6 +55,25 @@ default StringExpression substrBytes(final int start, final int length) { DateExpression parseDate(StringExpression timezone, StringExpression format); + /** + * The result of passing {@code this} value to the provided function. + * Equivalent to {@code f.apply(this)}, and allows lambdas and static, + * user-defined functions to use the chaining syntax. + * + * @see Expression#passTo + * @param f the function to apply. + * @return the resulting value. + * @param the type of the resulting value. + */ R passStringTo(Function f); - R switchStringOn(Function, ? extends BranchesTerminal> on); + + /** + * The result of applying the provided switch mapping to {@code this} value. + * + * @see Expression#switchOn + * @param mapping the switch mapping. + * @return the resulting value. + * @param the type of the resulting value. + */ + R switchStringOn(Function, ? extends BranchesTerminal> mapping); } From 37e66f3a10cba157080418691f44f8c3ead698e2 Mon Sep 17 00:00:00 2001 From: Maxim Katcharov Date: Tue, 17 Jan 2023 16:45:10 -0700 Subject: [PATCH 08/11] Fix --- .../main/com/mongodb/client/model/expressions/Expression.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java b/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java index 5d315d77400..4fded304eda 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java @@ -59,7 +59,7 @@ * See {@link Expressions#ofNull} for more details. * *

There is no explicit "missing" or "undefined" value. Users may use - * {@link MapExpression#has} or {@link DocumentExpression#has}. + * {@link MapExpression#has}. * *

This type hierarchy differs from the {@linkplain org.bson} types in that * they provide computational operations, the numeric types are less granular, From a85d3568475d3eb1ec86fed7fc42a4b1af792afa Mon Sep 17 00:00:00 2001 From: Maxim Katcharov Date: Wed, 18 Jan 2023 11:26:36 -0700 Subject: [PATCH 09/11] Checkstyle --- .../main/com/mongodb/client/model/expressions/Expression.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java b/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java index 4fded304eda..25cb28ccd97 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java @@ -65,7 +65,7 @@ * they provide computational operations, the numeric types are less granular, * and it offers multiple abstractions of certain types (document, map, entry). * It differs from the corresponding Java types (such as {@code int}, - * {@link String}, {@link java.util.Map) in that the operations + * {@link String}, {@link java.util.Map}) in that the operations * available differ, and in that an implementation of this API may be used to * produce MQL in the form of BSON. (This API makes no guarantee regarding the * BSON output produced by its implementation, which in any case may vary due From 7f00decc0bfba9b2879442a85fa4a30598362feb Mon Sep 17 00:00:00 2001 From: Maxim Katcharov Date: Thu, 19 Jan 2023 08:36:38 -0700 Subject: [PATCH 10/11] Fixes --- .../client/model/expressions/Expression.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java b/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java index 25cb28ccd97..f05c294bb2d 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java @@ -58,8 +58,8 @@ * of, any explicit type (except the root type {@link Expression} itself). * See {@link Expressions#ofNull} for more details. * - *

There is no explicit "missing" or "undefined" value. Users may use - * {@link MapExpression#has}. + *

This API specifies no "missing" or "undefined" value. Users may use + * {@link MapExpression#has} to check whether a value is present. * *

This type hierarchy differs from the {@linkplain org.bson} types in that * they provide computational operations, the numeric types are less granular, @@ -220,9 +220,9 @@ public interface Expression { /** * {@code this} value as a {@linkplain DocumentExpression document} if - * {@code this} is a document or document-like value (such as a - * {@linkplain MapExpression map} or - * {@linkplain EntryExpression entry}) + * {@code this} is a document or document-like value (such as all + * {@linkplain MapExpression maps} and all + * {@linkplain EntryExpression entries} created using the present API) * or the {@code other} document value if * {@code this} is null, or is missing, or is of any other non-document type. * @@ -233,9 +233,9 @@ public interface Expression { /** * {@code this} value as a {@linkplain MapExpression map} if - * {@code this} is a map or map-like value (such as a - * {@linkplain DocumentExpression document} or - * {@linkplain EntryExpression entry}) + * {@code this} is a map or map-like value (such as all + * {@linkplain DocumentExpression documents} and all + * {@linkplain EntryExpression entries} created using the present API) * or the {@code other} map value if * {@code this} is null, or is missing, or is of any other non-map type. * From cce2afc99eb58d348809df79db4bc03007c02fc1 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Tue, 17 Jan 2023 19:03:36 -0700 Subject: [PATCH 11/11] Add `@MqlUnchecked` and a few usage examples --- .../model/expressions/ArrayExpression.java | 3 + .../client/model/expressions/Branches.java | 4 +- .../model/expressions/DocumentExpression.java | 4 ++ .../client/model/expressions/Expression.java | 4 +- .../model/expressions/MapExpression.java | 2 + .../model/expressions/MqlUnchecked.java | 72 +++++++++++++++++++ 6 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 driver-core/src/main/com/mongodb/client/model/expressions/MqlUnchecked.java diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/ArrayExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/ArrayExpression.java index 674efb3d5a7..26186b2b581 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/ArrayExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/ArrayExpression.java @@ -19,6 +19,7 @@ import java.util.function.Function; import static com.mongodb.client.model.expressions.Expressions.of; +import static com.mongodb.client.model.expressions.MqlUnchecked.Unchecked.PRESENT; /** * An array {@link Expression value} in the context of the MongoDB Query @@ -85,6 +86,7 @@ public interface ArrayExpression extends Expression { * @param i * @return */ + @MqlUnchecked(PRESENT) T elementAt(IntegerExpression i); default T elementAt(final int i) { @@ -95,6 +97,7 @@ default T elementAt(final int i) { * user asserts that array is not empty * @return */ + @MqlUnchecked(PRESENT) T first(); /** diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/Branches.java b/driver-core/src/main/com/mongodb/client/model/expressions/Branches.java index 40a726b4c9c..fbda31c2e9e 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/Branches.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/Branches.java @@ -20,6 +20,8 @@ import java.util.List; import java.util.function.Function; +import static com.mongodb.client.model.expressions.MqlUnchecked.Unchecked.TYPE_ARGUMENT; + public final class Branches { Branches() { @@ -78,7 +80,7 @@ public BranchesIntermediary isDate(final Function BranchesIntermediary isArray(final Function, ? extends R> r) { + public BranchesIntermediary isArray(final Function, ? extends R> r) { return is(v -> mqlEx(v).isArray(), v -> r.apply((ArrayExpression) v)); } diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/DocumentExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/DocumentExpression.java index 343a8e7f68d..42105b2f213 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/DocumentExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/DocumentExpression.java @@ -23,6 +23,8 @@ import static com.mongodb.client.model.expressions.Expressions.of; import static com.mongodb.client.model.expressions.Expressions.ofMap; +import static com.mongodb.client.model.expressions.MqlUnchecked.Unchecked.PRESENT; +import static com.mongodb.client.model.expressions.MqlUnchecked.Unchecked.TYPE; /** * Expresses a document value. A document is an ordered set of fields, where the @@ -34,8 +36,10 @@ public interface DocumentExpression extends Expression { DocumentExpression unsetField(String fieldName); + @MqlUnchecked(PRESENT) Expression getField(String fieldName); + @MqlUnchecked({PRESENT, TYPE}) BooleanExpression getBoolean(String fieldName); BooleanExpression getBoolean(String fieldName, BooleanExpression other); diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java b/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java index f05c294bb2d..5009cd50e04 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/Expression.java @@ -20,6 +20,8 @@ import java.util.function.Function; +import static com.mongodb.client.model.expressions.MqlUnchecked.Unchecked.TYPE_ARGUMENT; + /** * A value in the context of the MongoDB Query Language (MQL). * @@ -216,7 +218,7 @@ public interface Expression { * @return the resulting value. * @param the type of the elements of the resulting array. */ - ArrayExpression isArrayOr(ArrayExpression other); + ArrayExpression<@MqlUnchecked(TYPE_ARGUMENT) T> isArrayOr(ArrayExpression other); /** * {@code this} value as a {@linkplain DocumentExpression document} if diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/MapExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/MapExpression.java index d33c1bcf80d..db0d387bb02 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/MapExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/MapExpression.java @@ -19,6 +19,7 @@ import java.util.function.Function; import static com.mongodb.client.model.expressions.Expressions.of; +import static com.mongodb.client.model.expressions.MqlUnchecked.Unchecked.PRESENT; public interface MapExpression extends Expression { @@ -29,6 +30,7 @@ default BooleanExpression has(String key) { } // TODO-END doc "user asserts" + @MqlUnchecked(PRESENT) T get(StringExpression key); // TODO-END doc "user asserts" diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/MqlUnchecked.java b/driver-core/src/main/com/mongodb/client/model/expressions/MqlUnchecked.java new file mode 100644 index 00000000000..4dcdb76308d --- /dev/null +++ b/driver-core/src/main/com/mongodb/client/model/expressions/MqlUnchecked.java @@ -0,0 +1,72 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.client.model.expressions; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Documents places where the API relies on a user asserting + * something that is not checked at run-time. + * If the assertion turns out to be false, the API behavior is unspecified. + * + *

This class is not part of the public API and may be removed or changed at any time

+ */ +@Documented +@Retention(RetentionPolicy.SOURCE) +@Target({ElementType.METHOD, ElementType.TYPE_USE}) +public @interface MqlUnchecked { + /** + * @return A hint on the user assertion the API relies on. + */ + Unchecked[] value(); + + /** + * @see MqlUnchecked#value() + */ + enum Unchecked { + /** + * The API relies on the values it encounters being of the type + * implied/specified by or inferred from the user code. + * For example, {@link com.mongodb.client.model.expressions.DocumentExpression#getBoolean(String)} + * relies on the values of the document field being of the + * {@linkplain com.mongodb.client.model.expressions.BooleanExpression boolean} type. + */ + TYPE, + /** + * The API checks the raw type, but relies on the type argument + * implied/specified by or inferred from the user code being correct. + * For example, {@link com.mongodb.client.model.expressions.Expression#isArrayOr(ArrayExpression)} + * checks that the value is of the + * {@linkplain com.mongodb.client.model.expressions.ArrayExpression array} raw type, + * but relies on the elements of the array being of the type derived from the user code. + * + *

One may think of it as a more specific version of {@link #TYPE}.

+ */ + TYPE_ARGUMENT, + /** + * The API relies on the element identified by index, name, position, etc., being present in the + * {@linkplain com.mongodb.client.model.expressions.DocumentExpression document}, + * {@linkplain com.mongodb.client.model.expressions.MapExpression map}, + * {@linkplain com.mongodb.client.model.expressions.ArrayExpression array} involved. + * For example, {@link com.mongodb.client.model.expressions.DocumentExpression#getField(String)}. + */ + PRESENT, + } +}