1919import java .util .List ;
2020
2121import org .aopalliance .intercept .MethodInterceptor ;
22+ import org .aopalliance .intercept .MethodInvocation ;
23+ import org .apache .commons .logging .Log ;
24+ import org .apache .commons .logging .LogFactory ;
2225import org .bson .Document ;
2326import org .springframework .aop .framework .ProxyFactory ;
2427import org .springframework .data .mongodb .core .query .Collation ;
2528import org .springframework .data .mongodb .core .query .Query ;
2629import org .springframework .data .repository .query .QueryMethodEvaluationContextProvider ;
2730import org .springframework .expression .ExpressionParser ;
31+ import org .springframework .lang .NonNull ;
2832import org .springframework .lang .Nullable ;
2933import org .springframework .util .ClassUtils ;
3034
3741 * @since 2.1
3842 * @currentRead Assassin's Apprentice - Robin Hobb
3943 */
40- class QueryUtils {
44+ public class QueryUtils {
45+
46+ protected static final Log LOGGER = LogFactory .getLog (QueryUtils .class );
4147
4248 /**
4349 * Decorate {@link Query} and add a default sort expression to the given {@link Query}. Attributes of the given
@@ -47,28 +53,27 @@ class QueryUtils {
4753 * @param defaultSort the default sort expression to apply to the query.
4854 * @return the query having the given {@code sort} applied.
4955 */
50- static Query decorateSort (Query query , Document defaultSort ) {
56+ public static Query decorateSort (Query query , Document defaultSort ) {
5157
5258 if (defaultSort .isEmpty ()) {
5359 return query ;
5460 }
5561
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 );
6964 return (Query ) factory .getProxy (query .getClass ().getClassLoader ());
7065 }
7166
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+
7277 /**
7378 * Apply a collation extracted from the given {@literal collationExpression} to the given {@link Query}. Potentially
7479 * replace parameter placeholders with values from the {@link ConvertingParameterAccessor accessor}.
@@ -124,4 +129,35 @@ static int indexOfAssignableParameter(Class<?> type, List<Class<?>> parameters)
124129 }
125130 return -1 ;
126131 }
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+ }
127163}
0 commit comments