1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package net.sf.autodao.impl;
19
20 import java.lang.annotation.Annotation;
21 import java.lang.reflect.Method;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27
28 import net.sf.autodao.Finder;
29 import net.sf.autodao.Named;
30 import net.sf.autodao.QueryArgumentTransformer;
31 import org.aopalliance.intercept.MethodInterceptor;
32 import org.aopalliance.intercept.MethodInvocation;
33 import org.jetbrains.annotations.NotNull;
34 import org.jetbrains.annotations.Nullable;
35 import org.springframework.core.annotation.AnnotationUtils;
36 import org.springframework.transaction.interceptor.TransactionAspectSupport;
37
38
39
40
41
42
43 final class FinderIntroductionInterceptor extends TransactionAspectSupport implements MethodInterceptor {
44
45 @NotNull
46 private final Map<Class<?>, QueryArgumentTransformer<?, ?>> transformers;
47
48 FinderIntroductionInterceptor(@NotNull final Map<Class<?>, QueryArgumentTransformer<?, ?>> transformers) {
49 this.transformers = transformers;
50 }
51
52
53 @Override
54 public Object invoke(@NotNull final MethodInvocation invocation) throws Throwable {
55 final Method method = invocation.getMethod();
56 final Finder finder = AnnotationUtils.getAnnotation(method, Finder.class);
57
58 if (finder == null)
59 return invocation.proceed();
60
61 final Object[] arguments = invocation.getArguments();
62 final Integer[] limit = new Integer[1];
63 final Integer[] offset = new Integer[1];
64 final List<Object> queryArgs = new ArrayList<>(arguments.length);
65 final Map<String, Object> namedArgs = new HashMap<>(arguments.length);
66 Utils.visitMethodParameters(method, new Utils.ParameterCallback() {
67 @Override
68 public void visit(final int index, @NotNull final Class<?> type, @NotNull final Annotation[] annotations) {
69 boolean processed = false;
70 final Object arg = arguments[index];
71 if (Utils.getLimit(annotations) != null) {
72 limit[0] = (Integer) arg;
73 processed = true;
74 }
75
76 if (Utils.getOffset(annotations) != null) {
77 offset[0] = (Integer) arg;
78 processed = true;
79 }
80
81 if (processed)
82 return;
83
84 final Object queryArg = transformArg(arg, method.getParameterTypes()[index]);
85 final Named named = Utils.getNamed(annotations);
86 if (named == null) {
87 queryArgs.add(queryArg);
88 } else {
89 namedArgs.put(named.value(), queryArg);
90 }
91 }
92 });
93
94 final FinderExecutor dao = (FinderExecutor) invocation.getThis();
95 if (Collection.class.isAssignableFrom(invocation.getMethod().getReturnType())) {
96 final List<Object> data;
97 if (namedArgs.isEmpty()) {
98 data = dao.executeListFinder(method, queryArgs.toArray(new Object[queryArgs.size()]), limit[0], offset[0]);
99 } else {
100 data = dao.executeListFinder(method, namedArgs, limit[0], offset[0]);
101 }
102 return convertResult(finder, data);
103 } else {
104 if (namedArgs.isEmpty()) {
105 return dao.executeSingleFinder(method, arguments);
106 } else {
107 return dao.executeSingleFinder(method, namedArgs);
108 }
109 }
110 }
111
112 @SuppressWarnings({ "unchecked", "rawtypes" })
113 @Nullable
114 private Object transformArg(@Nullable final Object arg, @NotNull final Class<?> declaredArgType) {
115 if (arg == null)
116 return null;
117
118 final QueryArgumentTransformer transformer = transformers.get(declaredArgType);
119 if (transformer == null)
120 return arg;
121
122 return transformer.transform(arg);
123 }
124
125 @SuppressWarnings({ "unchecked", "rawtypes" })
126 private static Object convertResult(final Finder finder, final List<Object> data) throws Exception {
127 final Class<? extends Collection> returnAs = finder.returnAs();
128 if (returnAs == List.class)
129 return data;
130
131 final Collection<Object> result = returnAs.newInstance();
132 result.addAll(data);
133 return result;
134 }
135 }