1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.callbackparams.sandbox;
18
19 import java.beans.IntrospectionException;
20 import java.beans.Introspector;
21 import java.beans.PropertyDescriptor;
22 import java.beans.PropertyEditor;
23 import java.beans.PropertyEditorManager;
24 import java.lang.annotation.ElementType;
25 import java.lang.annotation.Retention;
26 import java.lang.annotation.RetentionPolicy;
27 import java.lang.annotation.Target;
28 import java.lang.reflect.Method;
29 import org.callbackparams.CallbackFactory;
30 import org.callbackparams.ext.WrappingCallbackImpls;
31 import org.callbackparams.wrap.WrappingSupport;
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94 public class Property {
95
96 @Retention(RetentionPolicy.RUNTIME)
97 @Target({ElementType.FIELD, ElementType.TYPE})
98 public @interface BeanClass {
99 java.lang.Class value();
100 }
101
102 @Retention(RetentionPolicy.RUNTIME)
103 @Target({ElementType.FIELD, ElementType.TYPE})
104 public @interface Name {
105 String value();
106 }
107
108 @Retention(RetentionPolicy.RUNTIME)
109 @Target({ElementType.FIELD, ElementType.TYPE})
110 @WrappingCallbackImpls(BasicImpl.class)
111 public @interface Value {
112 String value();
113 }
114
115 public interface Callback<T> {
116 void setValues(T bean);
117 void assertValues(T bean);
118 }
119
120 protected static class BasicImpl<T> extends WrappingSupport<T>
121 implements CallbackFactory, Callback<T> {
122
123
124
125
126 protected BeanClass beanClass;
127 protected Name propertyName;
128 protected Value propertyValue;
129
130
131
132
133 final PropertyDescriptor descriptor = lookupPropertyDescriptor();
134 final Object[] setterArgument = {createSetterArgument()};
135
136
137
138
139 BasicImpl() throws IntrospectionException {}
140
141 private PropertyDescriptor lookupPropertyDescriptor()
142 throws IntrospectionException {
143 if (null != beanClass && null != propertyName) {
144 for (PropertyDescriptor pd : Introspector
145 .getBeanInfo(beanClass.value())
146 .getPropertyDescriptors()) {
147 if (pd.getName().equals(propertyName.value())) {
148 return pd;
149 }
150 }
151 }
152 return null;
153 }
154
155 private Object createSetterArgument() {
156 if (null == descriptor) {
157 return null;
158 }
159 PropertyEditor editor = PropertyEditorManager
160 .findEditor(descriptor.getPropertyType());
161 editor.setAsText(propertyValue.value());
162 return editor.getValue();
163 }
164
165 private static Object invoke(Method m, Object bean, Object[] args) {
166 try {
167 try {
168 m.setAccessible(true);
169 } catch (SecurityException ignore) {
170
171 }
172 return m.invoke(bean, args);
173
174 } catch (Exception x) {
175
176 throw org.callbackparams.support.ExceptionUtil.unchecked(x);
177 }
178 }
179
180
181
182
183
184
185
186
187
188
189
190
191 public Callback<T> getCallback() {
192 if (null == propertyValue) {
193 throw new IllegalStateException("Wrapped value - "
194 + wrappedValue()
195 + " - does not have annotation '@Value'");
196
197 } else if (null == propertyName) {
198 System.err.println(wrappedValue()
199 + " does not have annotation '@Name'");
200 return null;
201
202 } else if (null == beanClass) {
203 System.err.println(wrappedValue()
204 + " does not have annotation '@BeanClass'");
205 return null;
206 }
207 return this;
208 }
209
210 public void setValues(Object bean) {
211 if (beanClass.value().isInstance(bean)) {
212 invoke(descriptor.getWriteMethod(), bean, setterArgument);
213 }
214 }
215
216 public void assertValues(Object bean) {
217 if (beanClass.value().isInstance(bean)) {
218 Object actual = invoke(descriptor.getReadMethod(), bean, null);
219 if (false == setterArgument[0].equals(actual)) {
220 throw new AssertionError("Value for property \""
221 + descriptor.getName() + "\" on " + bean
222 + ": expected <" + setterArgument[0]
223 + "> but was <" + actual + ">");
224 }
225 }
226 }
227 }
228
229 private Property() {}
230 }