1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.callbackparams.combine.annotation;
18
19 import java.lang.annotation.Annotation;
20 import java.lang.reflect.Field;
21 import java.lang.reflect.Method;
22 import java.util.AbstractCollection;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.Iterator;
26 import java.util.Map;
27 import org.callbackparams.ParameterizedValue;
28 import org.callbackparams.combine.CombineStrategy;
29 import org.callbackparams.combine.reflect.CallbackRecordsFactory;
30 import org.callbackparams.combine.reflect.Combined;
31 import org.callbackparams.support.ExceptionUtil;
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 public class AnnotationAwareCallbackRecordsFactory
47 extends CallbackRecordsFactory {
48
49 @Override
50 public CombineStrategy retrieveCombineStrategy(Class testClass) {
51 final CombineConfig combineConfig = (CombineConfig)
52 testClass.getAnnotation(CombineConfig.class);
53
54 if (null == combineConfig) {
55 return super.retrieveCombineStrategy(testClass);
56
57 } else {
58 final CombineStrategy combineStrategy;
59 try {
60 combineStrategy = combineConfig.strategy().newInstance();
61 } catch (Exception x) {
62 throw ExceptionUtil.unchecked(x);
63 }
64 if (0 <= combineConfig.maxCount()) {
65 combineStrategy.setMaxCount(combineConfig.maxCount());
66 }
67 if (-1 != combineConfig.randomSeed()) {
68 combineStrategy.setRandomSeed(combineConfig.randomSeed());
69 }
70 return combineStrategy;
71 }
72 }
73
74
75
76
77
78
79
80
81
82
83
84
85
86 @Override
87 public Collection collectCallbackRecordsReflectively(final Class testClass) {
88 final Class combineConfigAnnotatedSuperClass =
89 findCombineConfigAnnotatedSuperClass(testClass);
90
91 Collection combinedRecords = null;
92 for (Class c = testClass ; null == combinedRecords
93 ; c = c.getSuperclass()) {
94 if (combineConfigAnnotatedSuperClass == c) {
95 combinedRecords = super
96 .collectCallbackRecordsReflectively(testClass);
97 }
98
99 for (Method m : c.getDeclaredMethods()) {
100 if (m.isAnnotationPresent(CallbackRecords.class)) {
101 try {
102 m.setAccessible(true);
103 } catch (SecurityException x) {
104
105 }
106 try {
107 return new LazilyQueedCollection(
108 (Collection) m.invoke(null, (Object[])null),
109 combinedRecords);
110 } catch (Exception x) {
111 throw new Error("Failed to execute the @CallbackRecords "
112 + "annotated method. Make sure it is a static "
113 + "method!!", x);
114 }
115 }
116 }
117 }
118
119 return combinedRecords;
120 }
121
122 private Class findCombineConfigAnnotatedSuperClass(Class testSuperClass) {
123 if (Object.class == testSuperClass) {
124 return Object.class;
125
126 } else {
127 for (Annotation a : testSuperClass.getDeclaredAnnotations()) {
128 if (a instanceof CombineConfig) {
129 return testSuperClass;
130 }
131 }
132 return findCombineConfigAnnotatedSuperClass(
133 testSuperClass.getSuperclass());
134 }
135 }
136
137 @Override
138 protected Map<Field,Class<?>> collectValueInjections(final Class testClass) {
139 Map injections = super.collectValueInjections(testClass);
140 for (Class<?> c = testClass; Object.class != c; c = c.getSuperclass()) {
141 for (Field f : c.getDeclaredFields()) {
142 if (f.isAnnotationPresent(ParameterizedValue.class)) {
143 injections.put(f, f.getType());
144 }
145 }
146 }
147 return injections;
148 }
149
150
151
152
153
154
155
156 @Override
157 protected boolean isValueAlsoAvailableAsCallback(Field f) {
158 if (false == super.isValueAlsoAvailableAsCallback(f)) {
159 return false;
160 } else {
161 ParameterizedValue pv = f.getAnnotation(ParameterizedValue.class);
162 return null == pv || pv.alsoAvailableAsCallback();
163 }
164 }
165
166
167
168
169
170
171 private static class LazilyQueedCollection
172 extends AbstractCollection<Combined[]> {
173 private final Collection[] que;
174
175 LazilyQueedCollection(Collection... que) {
176 this.que = que;
177 }
178
179 public Iterator<Combined[]> iterator() {
180 return new Iterator<Combined[]>() {
181
182 Iterator currentIterator = Collections.EMPTY_LIST.iterator();
183 int queIndex = -1;
184 Object next;
185
186
187 {
188 prepareNext();
189 }
190
191 public boolean hasNext() {
192 return null != currentIterator;
193 }
194 public Combined[] next() {
195 try {
196 return asCombinedArray(next);
197
198 } finally {
199 prepareNext();
200 }
201 }
202 public void remove() {
203 throw new UnsupportedOperationException("Not supported yet.");
204 }
205
206 private void prepareNext() {
207 while (false == currentIterator.hasNext()
208 && ++queIndex < que.length) {
209 if (null != que[queIndex]) {
210 currentIterator = que[queIndex].iterator();
211 }
212 }
213 if (currentIterator.hasNext()) {
214 next = currentIterator.next();
215 } else {
216 next = null;
217 currentIterator = null;
218 }
219 }
220 };
221 }
222
223 public int size() {
224 int size = 0;
225 for (Collection c : que) {
226 if (null != c) {
227 size += c.size();
228 }
229 }
230 return size;
231 }
232 }
233 }