19
19
import java .util .List ;
20
20
21
21
import org .aopalliance .intercept .MethodInterceptor ;
22
+ import org .aopalliance .intercept .MethodInvocation ;
23
+ import org .apache .commons .logging .Log ;
24
+ import org .apache .commons .logging .LogFactory ;
22
25
import org .bson .Document ;
23
26
import org .springframework .aop .framework .ProxyFactory ;
24
27
import org .springframework .data .mongodb .core .query .Collation ;
25
28
import org .springframework .data .mongodb .core .query .Query ;
26
29
import org .springframework .data .repository .query .QueryMethodEvaluationContextProvider ;
27
30
import org .springframework .expression .ExpressionParser ;
31
+ import org .springframework .lang .NonNull ;
28
32
import org .springframework .lang .Nullable ;
29
33
import org .springframework .util .ClassUtils ;
30
34
37
41
* @since 2.1
38
42
* @currentRead Assassin's Apprentice - Robin Hobb
39
43
*/
40
- class QueryUtils {
44
+ public class QueryUtils {
45
+
46
+ protected static final Log LOGGER = LogFactory .getLog (QueryUtils .class );
41
47
42
48
/**
43
49
* Decorate {@link Query} and add a default sort expression to the given {@link Query}. Attributes of the given
@@ -47,28 +53,27 @@ class QueryUtils {
47
53
* @param defaultSort the default sort expression to apply to the query.
48
54
* @return the query having the given {@code sort} applied.
49
55
*/
50
- static Query decorateSort (Query query , Document defaultSort ) {
56
+ public static Query decorateSort (Query query , Document defaultSort ) {
51
57
52
58
if (defaultSort .isEmpty ()) {
53
59
return query ;
54
60
}
55
61
56
- ProxyFactory factory = new ProxyFactory (query );
57
- factory .addAdvice ((MethodInterceptor ) invocation -> {
58
-
59
- if (!invocation .getMethod ().getName ().equals ("getSortObject" )) {
60
- return invocation .proceed ();
61
- }
62
-
63
- Document combinedSort = new Document (defaultSort );
64
- combinedSort .putAll ((Document ) invocation .proceed ());
65
- return combinedSort ;
66
- });
67
- factory .setInterfaces (new Class [0 ]);
68
-
62
+ ProxyFactory factory = prepareQueryProxy (query .getClass (), defaultSort );
63
+ factory .setTarget (query );
69
64
return (Query ) factory .getProxy (query .getClass ().getClassLoader ());
70
65
}
71
66
67
+ /**
68
+ * Decorate {@link Query} and add a default sort expression to the given {@link Query}. Attributes of the given
69
+ * {@code sort} may be overwritten by the sort explicitly defined by the {@link Query} itself.
70
+ *
71
+ * @param classLoader the {@link ClassLoader} to use for generating the proxy type with.
72
+ */
73
+ public static Class <?> queryProxyType (Class <? extends Query > baseType , ClassLoader classLoader ) {
74
+ return prepareQueryProxy (baseType , new Document ()).getProxyClass (classLoader );
75
+ }
76
+
72
77
/**
73
78
* Apply a collation extracted from the given {@literal collationExpression} to the given {@link Query}. Potentially
74
79
* replace parameter placeholders with values from the {@link ConvertingParameterAccessor accessor}.
@@ -124,4 +129,35 @@ static int indexOfAssignableParameter(Class<?> type, List<Class<?>> parameters)
124
129
}
125
130
return -1 ;
126
131
}
132
+
133
+ private static ProxyFactory prepareQueryProxy (Class <? extends Query > query , Document defaultSort ) {
134
+
135
+ ProxyFactory factory = new ProxyFactory ();
136
+ factory .setTargetClass (query );
137
+ factory .addAdvice (new DefaultSortingInterceptor (defaultSort ));
138
+ factory .setInterfaces (new Class [0 ]);
139
+ return factory ;
140
+ }
141
+
142
+ static class DefaultSortingInterceptor implements MethodInterceptor {
143
+
144
+ private final Document defaultSort ;
145
+
146
+ public DefaultSortingInterceptor (Document defaultSort ) {
147
+ this .defaultSort = defaultSort ;
148
+ }
149
+
150
+ @ Nullable
151
+ @ Override
152
+ public Object invoke (@ NonNull MethodInvocation invocation ) throws Throwable {
153
+
154
+ if (!invocation .getMethod ().getName ().equals ("getSortObject" )) {
155
+ return invocation .proceed ();
156
+ }
157
+
158
+ Document combinedSort = new Document (defaultSort );
159
+ combinedSort .putAll ((Document ) invocation .proceed ());
160
+ return combinedSort ;
161
+ }
162
+ }
127
163
}
0 commit comments