Skip to content

Commit 6ed8617

Browse files
committed
DATAMONGO-2138 - Refactor to syntax 2
1 parent c22d131 commit 6ed8617

File tree

4 files changed

+469
-471
lines changed

4 files changed

+469
-471
lines changed
Lines changed: 385 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,385 @@
1+
/*
2+
* Copyright 2010-2018 the original author or authors.
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 org.springframework.data.mongodb.core.query
18+
19+
import org.bson.BsonRegularExpression
20+
import org.bson.Document
21+
import org.springframework.data.domain.Example
22+
import org.springframework.data.geo.Circle
23+
import org.springframework.data.geo.Point
24+
import org.springframework.data.geo.Shape
25+
import org.springframework.data.mongodb.core.geo.GeoJson
26+
import org.springframework.data.mongodb.core.schema.JsonSchemaObject
27+
import org.springframework.data.mongodb.core.schema.MongoJsonSchema
28+
import java.util.regex.Pattern
29+
import kotlin.reflect.KProperty
30+
import kotlin.reflect.KProperty1
31+
32+
/**
33+
* Build [Criteria] with Property References as field names.
34+
* @author Tjeu Kayim
35+
* @since 2.2
36+
*/
37+
class TypedCriteria(
38+
val operation: Criteria.() -> Criteria,
39+
property: KProperty<*>? = null
40+
) : CriteriaDefinition {
41+
val name = property?.let(::nestedFieldName)
42+
val criteria by lazy { operation(name?.let(::Criteria) ?: Criteria()) }
43+
44+
override fun getCriteriaObject(): Document = criteria.criteriaObject
45+
46+
override fun getKey(): String? = criteria.key
47+
}
48+
49+
50+
/**
51+
* Creates a criterion using equality.
52+
* @see Criteria.isEqualTo
53+
*/
54+
infix fun <T> KProperty<T>.isEqualTo(value: T) = TypedCriteria({ isEqualTo(value) }, this)
55+
56+
/**
57+
* Creates a criterion using the $ne operator.
58+
*
59+
* See [MongoDB Query operator: $ne](https://docs.mongodb.com/manual/reference/operator/query/ne/)
60+
* @see Criteria.ne
61+
*/
62+
infix fun <T> KProperty<T>.ne(value: T) = TypedCriteria({ ne(value) }, this)
63+
64+
/**
65+
* Creates a criterion using the $lt operator.
66+
*
67+
* See [MongoDB Query operator: $lt](https://docs.mongodb.com/manual/reference/operator/query/lt/)
68+
* @see Criteria.lt
69+
*/
70+
infix fun <T> KProperty<T>.lt(value: T) = TypedCriteria({ lt(value) }, this)
71+
72+
/**
73+
* Creates a criterion using the $lte operator.
74+
*
75+
* See [MongoDB Query operator: $lte](https://docs.mongodb.com/manual/reference/operator/query/lte/)
76+
* @see Criteria.lte
77+
*/
78+
infix fun <T> KProperty<T>.lte(value: T) = TypedCriteria({ lte(value) }, this)
79+
80+
/**
81+
* Creates a criterion using the $gt operator.
82+
*
83+
* See [MongoDB Query operator: $gt](https://docs.mongodb.com/manual/reference/operator/query/gt/)
84+
* @see Criteria.gt
85+
*/
86+
infix fun <T> KProperty<T>.gt(value: T) = TypedCriteria({ gt(value) }, this)
87+
88+
/**
89+
* Creates a criterion using the $gte operator.
90+
*
91+
* See [MongoDB Query operator: $gte](https://docs.mongodb.com/manual/reference/operator/query/gte/)
92+
* @see Criteria.gte
93+
*/
94+
infix fun <T> KProperty<T>.gte(value: T) = TypedCriteria({ gte(value) }, this)
95+
96+
/**
97+
* Creates a criterion using the $in operator.
98+
*
99+
* See [MongoDB Query operator: $in](https://docs.mongodb.com/manual/reference/operator/query/in/)
100+
* @see Criteria.inValues
101+
*/
102+
fun <T> KProperty<T>.inValues(vararg o: Any) = TypedCriteria({ `in`(*o) }, this)
103+
104+
/**
105+
* Creates a criterion using the $in operator.
106+
*
107+
* See [MongoDB Query operator: $in](https://docs.mongodb.com/manual/reference/operator/query/in/)
108+
* @see Criteria.inValues
109+
*/
110+
infix fun <T> KProperty<T>.inValues(value: Collection<T>) = TypedCriteria({ `in`(value) }, this)
111+
112+
/**
113+
* Creates a criterion using the $nin operator.
114+
*
115+
* See [MongoDB Query operator: $nin](https://docs.mongodb.com/manual/reference/operator/query/nin/)
116+
* @see Criteria.nin
117+
*/
118+
fun <T> KProperty<T>.nin(vararg o: Any) = TypedCriteria({ nin(*o) }, this)
119+
120+
/**
121+
* Creates a criterion using the $nin operator.
122+
*
123+
* See [MongoDB Query operator: $nin](https://docs.mongodb.com/manual/reference/operator/query/nin/)
124+
* @see Criteria.nin
125+
*/
126+
infix fun <T> KProperty<T>.nin(value: Collection<T>) = TypedCriteria({ nin(value) }, this)
127+
128+
/**
129+
* Creates a criterion using the $mod operator.
130+
*
131+
* See [MongoDB Query operator: $mod](https://docs.mongodb.com/manual/reference/operator/query/mod/)
132+
* @see Criteria.mod
133+
*/
134+
fun KProperty<Number>.mod(value: Number, remainder: Number) = TypedCriteria({ mod(value, remainder) }, this)
135+
136+
/**
137+
* Creates a criterion using the $all operator.
138+
*
139+
* See [MongoDB Query operator: $all](https://docs.mongodb.com/manual/reference/operator/query/all/)
140+
* @see Criteria.all
141+
*/
142+
fun KProperty<*>.all(vararg o: Any) = TypedCriteria({ all(*o) }, this)
143+
144+
/**
145+
* Creates a criterion using the $all operator.
146+
*
147+
* See [MongoDB Query operator: $all](https://docs.mongodb.com/manual/reference/operator/query/all/)
148+
* @see Criteria.all
149+
*/
150+
infix fun KProperty<*>.all(value: Collection<*>) = TypedCriteria({ all(value) }, this)
151+
152+
/**
153+
* Creates a criterion using the $size operator.
154+
*
155+
* See [MongoDB Query operator: $size](https://docs.mongodb.com/manual/reference/operator/query/size/)
156+
* @see Criteria.size
157+
*/
158+
infix fun KProperty<*>.size(s: Int) = TypedCriteria({ size(s) }, this)
159+
160+
/**
161+
* Creates a criterion using the $exists operator.
162+
*
163+
* See [MongoDB Query operator: $exists](https://docs.mongodb.com/manual/reference/operator/query/exists/)
164+
* @see Criteria.exists
165+
*/
166+
infix fun KProperty<*>.exists(b: Boolean) = TypedCriteria({ exists(b) }, this)
167+
168+
/**
169+
* Creates a criterion using the $type operator.
170+
*
171+
* See [MongoDB Query operator: $type](https://docs.mongodb.com/manual/reference/operator/query/type/)
172+
* @see Criteria.type
173+
*/
174+
infix fun KProperty<*>.type(t: Int) = TypedCriteria({ type(t) }, this)
175+
176+
/**
177+
* Creates a criterion using the $type operator.
178+
*
179+
* See [MongoDB Query operator: $type](https://docs.mongodb.com/manual/reference/operator/query/type/)
180+
* @see Criteria.type
181+
*/
182+
infix fun KProperty<*>.type(t: Collection<JsonSchemaObject.Type>) = TypedCriteria({ type(*t.toTypedArray()) }, this)
183+
184+
/**
185+
* Creates a criterion using the $type operator.
186+
*
187+
* See [MongoDB Query operator: $type](https://docs.mongodb.com/manual/reference/operator/query/type/)
188+
* @see Criteria.type
189+
*/
190+
fun KProperty<*>.type(vararg t: JsonSchemaObject.Type) = TypedCriteria({ type(*t) }, this)
191+
192+
/**
193+
* Creates a criterion using the $not meta operator which affects the clause directly following
194+
*
195+
* See [MongoDB Query operator: $not](https://docs.mongodb.com/manual/reference/operator/query/not/)
196+
* @see Criteria.not
197+
*/
198+
fun KProperty<*>.not() = TypedCriteria({ not() }, this)
199+
200+
/**
201+
* Creates a criterion using a $regex operator.
202+
*
203+
* See [MongoDB Query operator: $regex](https://docs.mongodb.com/manual/reference/operator/query/regex/)
204+
* @see Criteria.regex
205+
*/
206+
infix fun KProperty<String?>.regex(re: String) = TypedCriteria({ regex(re, null) }, this)
207+
208+
/**
209+
* Creates a criterion using a $regex and $options operator.
210+
*
211+
* See [MongoDB Query operator: $regex](https://docs.mongodb.com/manual/reference/operator/query/regex/)
212+
* @see Criteria.regex
213+
*/
214+
fun KProperty<String?>.regex(re: String, options: String?) = TypedCriteria({ regex(re, options) }, this)
215+
216+
/**
217+
* Syntactical sugar for [isEqualTo] making obvious that we create a regex predicate.
218+
* @see Criteria.regex
219+
*/
220+
infix fun KProperty<String?>.regex(re: Regex) = TypedCriteria({ regex(re.toPattern()) }, this)
221+
222+
/**
223+
* Syntactical sugar for [isEqualTo] making obvious that we create a regex predicate.
224+
* @see Criteria.regex
225+
*/
226+
infix fun KProperty<String?>.regex(re: Pattern) = TypedCriteria({ regex(re) }, this)
227+
228+
/**
229+
* Syntactical sugar for [isEqualTo] making obvious that we create a regex predicate.
230+
* @see Criteria.regex
231+
*/
232+
infix fun KProperty<String?>.regex(re: BsonRegularExpression) = TypedCriteria({ regex(re) }, this)
233+
234+
/**
235+
* Creates a geospatial criterion using a $geoWithin $centerSphere operation. This is only available for
236+
* Mongo 2.4 and higher.
237+
*
238+
* See [MongoDB Query operator:
239+
* $geoWithin](https://docs.mongodb.com/manual/reference/operator/query/geoWithin/)
240+
*
241+
* See [MongoDB Query operator:
242+
* $centerSphere](https://docs.mongodb.com/manual/reference/operator/query/centerSphere/)
243+
* @see Criteria.withinSphere
244+
*/
245+
infix fun KProperty<GeoJson<*>>.withinSphere(circle: Circle) = TypedCriteria({ withinSphere(circle) }, this)
246+
247+
/**
248+
* Creates a geospatial criterion using a $geoWithin operation.
249+
*
250+
* See [MongoDB Query operator:
251+
* $geoWithin](https://docs.mongodb.com/manual/reference/operator/query/geoWithin/)
252+
* @see Criteria.within
253+
*/
254+
infix fun KProperty<GeoJson<*>>.within(shape: Shape) = TypedCriteria({ within(shape) }, this)
255+
256+
/**
257+
* Creates a geospatial criterion using a $near operation.
258+
*
259+
* See [MongoDB Query operator: $near](https://docs.mongodb.com/manual/reference/operator/query/near/)
260+
* @see Criteria.near
261+
*/
262+
infix fun KProperty<GeoJson<*>>.near(point: Point) = TypedCriteria({ near(point) }, this)
263+
264+
/**
265+
* Creates a geospatial criterion using a $nearSphere operation. This is only available for Mongo 1.7 and
266+
* higher.
267+
*
268+
* See [MongoDB Query operator:
269+
* $nearSphere](https://docs.mongodb.com/manual/reference/operator/query/nearSphere/)
270+
* @see Criteria.nearSphere
271+
*/
272+
infix fun KProperty<GeoJson<*>>.nearSphere(point: Point) = TypedCriteria({ nearSphere(point) }, this)
273+
274+
/**
275+
* Creates criterion using `$geoIntersects` operator which matches intersections of the given `geoJson`
276+
* structure and the documents one. Requires MongoDB 2.4 or better.
277+
* @see Criteria.intersects
278+
*/
279+
infix fun KProperty<GeoJson<*>>.intersects(geoJson: GeoJson<*>) = TypedCriteria({ intersects(geoJson) }, this)
280+
281+
/**
282+
* Creates a geo-spatial criterion using a $maxDistance operation, for use with $near
283+
*
284+
* See [MongoDB Query operator:
285+
* $maxDistance](https://docs.mongodb.com/manual/reference/operator/query/maxDistance/)
286+
* @see Criteria.maxDistance
287+
*/
288+
infix fun KProperty<GeoJson<*>>.maxDistance(d: Double) = TypedCriteria({ maxDistance(d) }, this)
289+
290+
/**
291+
* Creates a geospatial criterion using a $minDistance operation, for use with $near or
292+
* $nearSphere.
293+
* @see Criteria.minDistance
294+
*/
295+
infix fun KProperty<GeoJson<*>>.minDistance(d: Double) = TypedCriteria({ minDistance(d) }, this)
296+
297+
/**
298+
* Creates a criterion using the $elemMatch operator
299+
*
300+
* See [MongoDB Query operator:
301+
* $elemMatch](https://docs.mongodb.com/manual/reference/operator/query/elemMatch/)
302+
* @see Criteria.elemMatch
303+
*/
304+
infix fun KProperty<*>.elemMatch(c: Criteria) = TypedCriteria({ elemMatch(c) }, this)
305+
306+
/**
307+
* Creates a criterion using the $elemMatch operator
308+
*
309+
* See [MongoDB Query operator:
310+
* $elemMatch](https://docs.mongodb.com/manual/reference/operator/query/elemMatch/)
311+
* @see Criteria.elemMatch
312+
*/
313+
infix fun KProperty<*>.elemMatch(c: TypedCriteria) = TypedCriteria({ elemMatch(typedCriteria(c)) }, this)
314+
315+
/**
316+
* Creates a criterion using the given object as a pattern.
317+
* @see Criteria.alike
318+
*/
319+
fun alike(sample: Example<*>) = TypedCriteria({ alike(sample) })
320+
321+
/**
322+
* Creates a criterion (`$jsonSchema`) matching documents against a given structure defined by the
323+
* [MongoJsonSchema].
324+
*
325+
* See [MongoDB Query operator:
326+
* $jsonSchema](https://docs.mongodb.com/manual/reference/operator/query/jsonSchema/)
327+
* @see Criteria.andDocumentStructureMatches
328+
*/
329+
infix fun KProperty<*>.andDocumentStructureMatches(schema: MongoJsonSchema) =
330+
TypedCriteria({ andDocumentStructureMatches(schema) }, this)
331+
332+
/**
333+
* Use [Criteria.BitwiseCriteriaOperators] as gateway to create a criterion using one of the
334+
* [bitwise operators](https://docs.mongodb.com/manual/reference/operator/query-bitwise/) like
335+
* `$bitsAllClear`.
336+
*
337+
* Example:
338+
* ```
339+
* bits { allClear(123) }
340+
* ```
341+
* @see Criteria.bits
342+
*/
343+
infix fun KProperty<*>.bits(bitwiseCriteria: Criteria.BitwiseCriteriaOperators.() -> Criteria) =
344+
TypedCriteria({ bits().let(bitwiseCriteria) }, this)
345+
346+
/**
347+
* Creates an 'or' criteria using the $or operator for all of the provided criteria
348+
*
349+
* Note that mongodb doesn't support an $or operator to be wrapped in a $not operator.
350+
* @see Criteria.orOperator
351+
*/
352+
fun orOperator(vararg builders: TypedCriteria) = addOperatorWithCriteria(builders, Criteria::orOperator)
353+
354+
/**
355+
* Creates a 'nor' criteria using the $nor operator for all of the provided criteria.
356+
*
357+
* Note that mongodb doesn't support an $nor operator to be wrapped in a $not operator.
358+
* @see Criteria.norOperator
359+
*/
360+
fun norOperator(vararg builders: TypedCriteria) = addOperatorWithCriteria(builders, Criteria::norOperator)
361+
362+
/**
363+
* Creates an 'and' criteria using the $and operator for all of the provided criteria.
364+
*
365+
* Note that mongodb doesn't support an $and operator to be wrapped in a $not operator.
366+
* @see Criteria.andOperator
367+
*/
368+
fun andOperator(vararg builders: TypedCriteria) = addOperatorWithCriteria(builders, Criteria::andOperator)
369+
370+
private fun addOperatorWithCriteria(
371+
builders: Array<out TypedCriteria>,
372+
operation: Criteria.(Array<Criteria>) -> Criteria
373+
) = TypedCriteria({ operation(builders.map { it.criteria }.toTypedArray()) })
374+
375+
/**
376+
* Build nested properties.
377+
* Refer to a field in an embedded/nested document.
378+
*
379+
* For example, referring to the field "book.author":
380+
* ```
381+
* Book::author / Author::name isEqualTo "Herman Melville"
382+
* ```
383+
*/
384+
operator fun <T, U> KProperty<T>.div(other: KProperty1<T, U>) =
385+
NestedProperty(this, other)

0 commit comments

Comments
 (0)