Skip to content

Commit ff83341

Browse files
katcharovstIncMale
andauthored
Add MQL Expressions (#1032)
* Implement boolean expressions (#1025) JAVA-4779 * Implement filter, map, reduce (#1031) JAVA-4781 * Implement eq, ne, gt, gte, lt, lte (#1033) JAVA-4784 * Implement string expressions (#1036) JAVA-4801 * Implement arithmetic expressions (#1037) Implement arithmetic expressions (from top 50, and others) JAVA-4803 * Implement array expressions (#1043) JAVA-4805 * Implement date expressions (#1045) JAVA-4804 * Implement conversion/type expressions (#1050) JAVA-4802 * Implement document expressions (#1052) JAVA-4782 * Replace reduce with individual reductions (#1053) JAVA-4814 * Implement map expressions (#1054) JAVA-4817 * Implement switch expression (#1055) JAVA-4813 * Test expressions in context (#1057) JAVA-4820 * Add javadoc for boolean, date, number, integer, and expression (#1059) JAVA-4799 * Update and add documentation (#1059) * Fix, tests JAVA-4799 * Add `@MqlUnchecked` and a few usage examples (#1059) JAVA-4799 * Add has to document, add tests (#1070) JAVA-4799 * Add javadocs for remaining classes (#1070) JAVA-4799 * 5.2 annotations (#1070) JAVA-4799 * 5.0 annotations (#1070) JAVA-4799 * 4.4 annotations (#1070) JAVA-4799 * 4.2 annotations (#1070) JAVA-4799 * 4.0 annotations (#1070) JAVA-4799 * Update and add documentation, add tests, fix minor issues (#1070) Rename extractBsonValue Fix access modifiers Remove excess comments Update docs Fix: behaviour of get Add notNull to API, add notNullApi test Fix docs/annotations, tests Fix docs, annotations, since Fix docs Revert external Add missing MqlUnchecked Fix missing null checks Checkstyle JAVA-4799 * Rename to Mql (automated) (#1073) JAVA-3879 * Rename methods (automated) (#1073) JAVA-3879 * Update naming, terms, and missing checks and annotations (#1073) JAVA-3879 --------- Co-authored-by: Valentin Kovalenko <[email protected]>
1 parent 43ee372 commit ff83341

38 files changed

+7680
-23
lines changed

config/checkstyle/suppressions.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,4 +157,6 @@
157157
<suppress checks="ParameterName" files=".*org[\\/]bson[\\/]codecs[\\/]pojo[\\/]bench[\\/].*"/>
158158
<suppress checks="Regexp" files=".*org[\\/]bson[\\/]codecs[\\/]pojo[\\/]bench[\\/].*"/>
159159

160+
<!-- Complicated expressions for demo purposes -->
161+
<suppress checks="SimplifyBooleanExpressionCheck" files="ExpressionsFunctionalTest"/>
160162
</suppressions>

driver-core/src/main/com/mongodb/MongoClientSettings.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import com.mongodb.annotations.Immutable;
2020
import com.mongodb.annotations.NotThreadSafe;
2121
import com.mongodb.client.gridfs.codecs.GridFSFileCodecProvider;
22+
import com.mongodb.client.model.mql.ExpressionCodecProvider;
2223
import com.mongodb.client.model.geojson.codecs.GeoJsonCodecProvider;
2324
import com.mongodb.connection.ClusterSettings;
2425
import com.mongodb.connection.ConnectionPoolSettings;
@@ -76,6 +77,7 @@ public final class MongoClientSettings {
7677
new JsonObjectCodecProvider(),
7778
new BsonCodecProvider(),
7879
new EnumCodecProvider(),
80+
new ExpressionCodecProvider(),
7981
new Jep395RecordCodecProvider()));
8082

8183
private final ReadPreference readPreference;
@@ -123,6 +125,7 @@ public final class MongoClientSettings {
123125
* <li>{@link org.bson.codecs.JsonObjectCodecProvider}</li>
124126
* <li>{@link org.bson.codecs.BsonCodecProvider}</li>
125127
* <li>{@link org.bson.codecs.EnumCodecProvider}</li>
128+
* <li>{@link ExpressionCodecProvider}</li>
126129
* <li>{@link com.mongodb.Jep395RecordCodecProvider}</li>
127130
* </ul>
128131
*
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright 2008-present MongoDB, Inc.
3+
* Copyright 2010 The Guava Authors
4+
* Copyright 2011 The Guava Authors
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package com.mongodb.annotations;
20+
21+
import java.lang.annotation.Documented;
22+
import java.lang.annotation.ElementType;
23+
import java.lang.annotation.Retention;
24+
import java.lang.annotation.RetentionPolicy;
25+
import java.lang.annotation.Target;
26+
27+
/**
28+
* Signifies that the annotated class or interface should be treated as sealed:
29+
* it must not be extended or implemented.
30+
*
31+
* <p>Using such classes and interfaces is no different from using ordinary
32+
* unannotated classes and interfaces.
33+
*
34+
* <p>This annotation does not imply that the API is experimental or
35+
* {@link Beta}, or that the quality or performance of the API is inferior.
36+
*/
37+
@Retention(RetentionPolicy.CLASS)
38+
@Target(ElementType.TYPE)
39+
@Documented
40+
@Sealed
41+
public @interface Sealed {
42+
}
Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
/*
2+
* Copyright 2008-present MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.mongodb.client.model.mql;
18+
19+
import com.mongodb.annotations.Beta;
20+
import com.mongodb.assertions.Assertions;
21+
22+
import java.util.ArrayList;
23+
import java.util.List;
24+
import java.util.function.Function;
25+
26+
import static com.mongodb.client.model.mql.MqlUnchecked.Unchecked.TYPE_ARGUMENT;
27+
28+
/**
29+
* Branches are used in {@linkplain MqlValue#switchOn}, and
30+
* define a sequence of checks that will be performed. The first check
31+
* to succeed will produce the value that it specifies. If no check succeeds,
32+
* then the operation
33+
* {@linkplain BranchesIntermediary#defaults(Function) defaults} to a default
34+
* value, or if none is specified, the operation will cause an error.
35+
*
36+
* @param <T> the type of the values that may be checked.
37+
* @since 4.9.0
38+
*/
39+
@Beta(Beta.Reason.CLIENT)
40+
public final class Branches<T extends MqlValue> {
41+
42+
Branches() {
43+
}
44+
45+
private static <T extends MqlValue, R extends MqlValue> BranchesIntermediary<T, R> with(final Function<T, SwitchCase<R>> switchCase) {
46+
List<Function<T, SwitchCase<R>>> v = new ArrayList<>();
47+
v.add(switchCase);
48+
return new BranchesIntermediary<>(v);
49+
}
50+
51+
private static <T extends MqlValue> MqlExpression<?> mqlEx(final T value) {
52+
return (MqlExpression<?>) value;
53+
}
54+
55+
// is fn
56+
57+
/**
58+
* A successful check for the specified {@code predicate}
59+
* produces a value specified by the {@code mapping}.
60+
*
61+
* @param predicate the predicate.
62+
* @param mapping the mapping.
63+
* @param <R> the type of the produced value.
64+
* @return the appended sequence of checks.
65+
*/
66+
public <R extends MqlValue> BranchesIntermediary<T, R> is(final Function<? super T, MqlBoolean> predicate, final Function<? super T, ? extends R> mapping) {
67+
Assertions.notNull("predicate", predicate);
68+
Assertions.notNull("mapping", mapping);
69+
return with(value -> new SwitchCase<>(predicate.apply(value), mapping.apply(value)));
70+
}
71+
72+
// eq lt lte
73+
74+
/**
75+
* A successful check for {@linkplain MqlValue#eq equality}
76+
* produces a value specified by the {@code mapping}.
77+
*
78+
* @param v the value to check against.
79+
* @param mapping the mapping.
80+
* @param <R> the type of the produced value.
81+
* @return the appended sequence of checks.
82+
*/
83+
public <R extends MqlValue> BranchesIntermediary<T, R> eq(final T v, final Function<? super T, ? extends R> mapping) {
84+
Assertions.notNull("v", v);
85+
Assertions.notNull("mapping", mapping);
86+
return is(value -> value.eq(v), mapping);
87+
}
88+
89+
/**
90+
* A successful check for being
91+
* {@linkplain MqlValue#lt less than}
92+
* the provided value {@code v}
93+
* produces a value specified by the {@code mapping}.
94+
*
95+
* @param v the value to check against.
96+
* @param mapping the mapping.
97+
* @param <R> the type of the produced value.
98+
* @return the appended sequence of checks.
99+
*/
100+
public <R extends MqlValue> BranchesIntermediary<T, R> lt(final T v, final Function<? super T, ? extends R> mapping) {
101+
Assertions.notNull("v", v);
102+
Assertions.notNull("mapping", mapping);
103+
return is(value -> value.lt(v), mapping);
104+
}
105+
106+
/**
107+
* A successful check for being
108+
* {@linkplain MqlValue#lte less than or equal to}
109+
* the provided value {@code v}
110+
* produces a value specified by the {@code mapping}.
111+
*
112+
* @param v the value to check against.
113+
* @param mapping the mapping.
114+
* @param <R> the type of the produced value.
115+
* @return the appended sequence of checks.
116+
*/
117+
public <R extends MqlValue> BranchesIntermediary<T, R> lte(final T v, final Function<? super T, ? extends R> mapping) {
118+
Assertions.notNull("v", v);
119+
Assertions.notNull("mapping", mapping);
120+
return is(value -> value.lte(v), mapping);
121+
}
122+
123+
// is type
124+
125+
/**
126+
* A successful check for
127+
* {@linkplain MqlValue#isBooleanOr(MqlBoolean) being a boolean}
128+
* produces a value specified by the {@code mapping}.
129+
*
130+
* @param mapping the mapping.
131+
* @return the appended sequence of checks.
132+
* @param <R> the type of the produced value.
133+
*/
134+
public <R extends MqlValue> BranchesIntermediary<T, R> isBoolean(final Function<? super MqlBoolean, ? extends R> mapping) {
135+
Assertions.notNull("mapping", mapping);
136+
return is(v -> mqlEx(v).isBoolean(), v -> mapping.apply((MqlBoolean) v));
137+
}
138+
139+
/**
140+
* A successful check for
141+
* {@linkplain MqlValue#isNumberOr(MqlNumber) being a number}
142+
* produces a value specified by the {@code mapping}.
143+
*
144+
* @mongodb.server.release 4.4
145+
* @param mapping the mapping.
146+
* @return the appended sequence of checks.
147+
* @param <R> the type of the produced value.
148+
*/
149+
public <R extends MqlValue> BranchesIntermediary<T, R> isNumber(final Function<? super MqlNumber, ? extends R> mapping) {
150+
Assertions.notNull("mapping", mapping);
151+
return is(v -> mqlEx(v).isNumber(), v -> mapping.apply((MqlNumber) v));
152+
}
153+
154+
/**
155+
* A successful check for
156+
* {@linkplain MqlValue#isIntegerOr(MqlInteger) being an integer}
157+
* produces a value specified by the {@code mapping}.
158+
*
159+
* @mongodb.server.release 4.4
160+
* @param mapping the mapping.
161+
* @return the appended sequence of checks.
162+
* @param <R> the type of the produced value.
163+
*/
164+
public <R extends MqlValue> BranchesIntermediary<T, R> isInteger(final Function<? super MqlInteger, ? extends R> mapping) {
165+
Assertions.notNull("mapping", mapping);
166+
return is(v -> mqlEx(v).isInteger(), v -> mapping.apply((MqlInteger) v));
167+
}
168+
169+
/**
170+
* A successful check for
171+
* {@linkplain MqlValue#isStringOr(MqlString) being a string}
172+
* produces a value specified by the {@code mapping}.
173+
*
174+
* @param mapping the mapping.
175+
* @return the appended sequence of checks.
176+
* @param <R> the type of the produced value.
177+
*/
178+
public <R extends MqlValue> BranchesIntermediary<T, R> isString(final Function<? super MqlString, ? extends R> mapping) {
179+
Assertions.notNull("mapping", mapping);
180+
return is(v -> mqlEx(v).isString(), v -> mapping.apply((MqlString) v));
181+
}
182+
183+
/**
184+
* A successful check for
185+
* {@linkplain MqlValue#isDateOr(MqlDate) being a date}
186+
* produces a value specified by the {@code mapping}.
187+
*
188+
* @param mapping the mapping.
189+
* @return the appended sequence of checks.
190+
* @param <R> the type of the produced value.
191+
*/
192+
public <R extends MqlValue> BranchesIntermediary<T, R> isDate(final Function<? super MqlDate, ? extends R> mapping) {
193+
Assertions.notNull("mapping", mapping);
194+
return is(v -> mqlEx(v).isDate(), v -> mapping.apply((MqlDate) v));
195+
}
196+
197+
/**
198+
* A successful check for
199+
* {@linkplain MqlValue#isArrayOr(MqlArray) being an array}
200+
* produces a value specified by the {@code mapping}.
201+
*
202+
* <p>Warning: The type argument of the array is not
203+
* enforced by the API. The use of this method is an
204+
* unchecked assertion that the type argument is correct.
205+
*
206+
* @param mapping the mapping.
207+
* @return the appended sequence of checks.
208+
* @param <R> the type of the produced value.
209+
* @param <Q> the type of the array.
210+
*/
211+
@SuppressWarnings("unchecked")
212+
public <R extends MqlValue, Q extends MqlValue> BranchesIntermediary<T, R> isArray(final Function<? super MqlArray<@MqlUnchecked(TYPE_ARGUMENT) Q>, ? extends R> mapping) {
213+
Assertions.notNull("mapping", mapping);
214+
return is(v -> mqlEx(v).isArray(), v -> mapping.apply((MqlArray<Q>) v));
215+
}
216+
217+
/**
218+
* A successful check for
219+
* {@linkplain MqlValue#isDocumentOr(MqlDocument) being a document}
220+
* (or document-like value, see
221+
* {@link MqlMap} and {@link MqlEntry})
222+
* produces a value specified by the {@code mapping}.
223+
*
224+
* @param mapping the mapping.
225+
* @return the appended sequence of checks.
226+
* @param <R> the type of the produced value.
227+
*/
228+
public <R extends MqlValue> BranchesIntermediary<T, R> isDocument(final Function<? super MqlDocument, ? extends R> mapping) {
229+
Assertions.notNull("mapping", mapping);
230+
return is(v -> mqlEx(v).isDocumentOrMap(), v -> mapping.apply((MqlDocument) v));
231+
}
232+
233+
/**
234+
* A successful check for
235+
* {@linkplain MqlValue#isMapOr(MqlMap) being a map}
236+
* (or map-like value, see
237+
* {@link MqlDocument} and {@link MqlEntry})
238+
* produces a value specified by the {@code mapping}.
239+
*
240+
* <p>Warning: The type argument of the map is not
241+
* enforced by the API. The use of this method is an
242+
* unchecked assertion that the type argument is correct.
243+
*
244+
* @param mapping the mapping.
245+
* @return the appended sequence of checks.
246+
* @param <R> the type of the produced value.
247+
* @param <Q> the type of the array.
248+
*/
249+
@SuppressWarnings("unchecked")
250+
public <R extends MqlValue, Q extends MqlValue> BranchesIntermediary<T, R> isMap(final Function<? super MqlMap<@MqlUnchecked(TYPE_ARGUMENT) Q>, ? extends R> mapping) {
251+
Assertions.notNull("mapping", mapping);
252+
return is(v -> mqlEx(v).isDocumentOrMap(), v -> mapping.apply((MqlMap<Q>) v));
253+
}
254+
255+
/**
256+
* A successful check for
257+
* {@linkplain MqlValues#ofNull()} being the null value}
258+
* produces a value specified by the {@code mapping}.
259+
*
260+
* @param mapping the mapping.
261+
* @return the appended sequence of checks.
262+
* @param <R> the type of the produced value.
263+
*/
264+
public <R extends MqlValue> BranchesIntermediary<T, R> isNull(final Function<? super MqlValue, ? extends R> mapping) {
265+
Assertions.notNull("mapping", mapping);
266+
return is(v -> mqlEx(v).isNull(), v -> mapping.apply(v));
267+
}
268+
}

0 commit comments

Comments
 (0)