1 package org.lsst.ccs.utilities.beanutils;
2
3 import java.lang.reflect.Constructor;
4 import java.lang.reflect.Method;
5 import java.util.ArrayList;
6 import java.util.HashMap;
7 import java.util.LinkedHashMap;
8 import java.util.List;
9
10
11
12
13
14
15 public abstract class BeanProxyFor<T> implements BeanFor<T> {
16
17 protected class ProxyAgent {
18 class Descriptor {
19 boolean get;
20 boolean set;
21 boolean assigned;
22 Method setMethod;
23 Method getMethod;
24 Object value;
25 public String toString(){
26 return "get=" + get
27 + ";set=" + set
28 + ";assigned=" + assigned
29 + (set? ";" + setMethod.getName(): "")
30 + (get? ";" + getMethod.getName(): "") ;
31
32 }
33 }
34
35
36 HashMap<String, Descriptor> delegateMethods = new HashMap<String, Descriptor>();
37 LinkedHashMap<String, Descriptor> ctorArgs = new LinkedHashMap<String, Descriptor>();
38 Constructor<T> minimumCtor;
39 int nbArgsCtor;
40 int nbArgsSet;
41
42 ProxyAgent() {
43 String beanName = BeanProxyFor.this.getClass().getCanonicalName();
44 String className = beanName.replace("Bean", "");
45 try {
46 Class klass = Class.forName(className);
47
48 Method[] methods = klass.getMethods();
49 for (Method method : methods) {
50 String name = method.getName();
51 if (name.startsWith("set")) {
52 String propertyName = name.replace("set", "").toLowerCase();
53 Descriptor descriptor = delegateMethods.get(propertyName);
54 if (descriptor == null) {
55 descriptor = new Descriptor();
56 delegateMethods.put(propertyName, descriptor);
57 }
58 descriptor.set = true;
59 descriptor.setMethod = method;
60
61 } else if (name.startsWith("get")) {
62 String propertyName = name.replace("get", "").toLowerCase();
63 Descriptor descriptor = delegateMethods.get(propertyName);
64 if (descriptor == null) {
65 descriptor = new Descriptor();
66 delegateMethods.put(propertyName, descriptor);
67 }
68 descriptor.get = true;
69 descriptor.getMethod = method;
70 }
71 }
72
73 Constructor[] constructors = klass.getConstructors();
74 for (Constructor constructor : constructors) {
75 CriticalCtor minimumDesc = (CriticalCtor) constructor.getAnnotation(CriticalCtor.class);
76 if (minimumDesc != null) {
77 this.minimumCtor = constructor;
78 String[] names = minimumDesc.value();
79 this.nbArgsCtor = names.length;
80 ctorArgs = new LinkedHashMap<String, Descriptor>(this.nbArgsCtor);
81 for (String name : names) {
82 Descriptor descriptor = new Descriptor();
83 descriptor.set = descriptor.get = true;
84 ctorArgs.put(name.toLowerCase(), descriptor);
85 }
86 return;
87 }
88
89 }
90
91 } catch (RuntimeException exc) {
92 throw exc;
93 } catch (Exception e) {
94 throw new WrappedException(e);
95 }
96
97 }
98
99
100
101
102
103
104
105 private boolean checkForDelegateCreation() {
106 if (delegate != null) return false;
107 if (nbArgsCtor == nbArgsSet) {
108 List<Object> listArgs = new ArrayList<Object>(nbArgsCtor);
109 for (Descriptor desc : ctorArgs.values()) {
110 listArgs.add(desc.value);
111 }
112 Object[] args = listArgs.toArray();
113 try {
114 delegate = minimumCtor.newInstance(args);
115 for (Descriptor descriptor : delegateMethods.values()) {
116
117 if (descriptor.assigned && descriptor.set) {
118 try {
119 descriptor.setMethod.invoke(delegate, descriptor.value);
120 } catch (Exception exc) {
121 throw new WrappedBeanMethodInvocationException(
122 exc, descriptor.setMethod, descriptor.value);
123 }
124 }
125 }
126 } catch (RuntimeException e) {
127 throw e ;
128 } catch (Exception e) {
129 throw new WrappedBeanMethodInvocationException(e, minimumCtor, args);
130 }
131 return true;
132 }
133 return false;
134 }
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149 public void setProperty(String proptyName, Object value) {
150 methodsCalled = true;
151 String propertyName = proptyName.toLowerCase();
152 Descriptor descriptor;
153 if (delegate == null) {
154
155 descriptor = ctorArgs.get(propertyName);
156 if (descriptor != null) {
157
158 descriptor.value = value;
159 if (!descriptor.assigned) this.nbArgsSet++;
160 descriptor.assigned = true;
161
162 boolean created = checkForDelegateCreation();
163 if (created) return;
164 } else {
165 descriptor = delegateMethods.get(propertyName);
166 if (descriptor != null) {
167 descriptor.value = value;
168 descriptor.assigned = true;
169 } else {
170 throw new UnsupportedOperationException("set" + proptyName);
171 }
172 }
173
174 } else {
175 descriptor = delegateMethods.get(propertyName);
176 if ((descriptor != null) && descriptor.set) {
177 try {
178 descriptor.setMethod.invoke(delegate, value);
179 } catch (Exception e) {
180 throw new WrappedBeanMethodInvocationException(e, descriptor.setMethod, value);
181 }
182 } else {
183 throw new UnsupportedOperationException("set" + proptyName);
184 }
185
186 }
187 }
188
189 public Object getProperty(String proptyName) {
190 methodsCalled = true;
191 String propertyName = proptyName.toLowerCase();
192
193 Descriptor descriptor;
194 if (delegate == null) {
195 descriptor = ctorArgs.get(propertyName);
196 if ((descriptor != null) && descriptor.get) {
197 return descriptor.value;
198 } else {
199 descriptor = delegateMethods.get(propertyName);
200 if ((descriptor != null) && descriptor.get) {
201 return descriptor.value;
202 } else {
203 throw new UnsupportedOperationException("get" + proptyName);
204 }
205 }
206
207 } else {
208 descriptor = delegateMethods.get(propertyName);
209 if ((descriptor != null) && descriptor.get) {
210 try {
211 return descriptor.getMethod.invoke(delegate);
212 } catch (Exception e) {
213 throw new WrappedBeanMethodInvocationException(e, descriptor.getMethod);
214 }
215 } else {
216 throw new UnsupportedOperationException("get" + proptyName);
217 }
218 }
219
220 }
221 }
222
223
224 protected final ProxyAgent agent;
225 protected T delegate;
226 protected boolean methodsCalled;
227
228 public BeanProxyFor() throws WrappedException {
229 agent = new ProxyAgent();
230 }
231
232 public BeanProxyFor(T delegate) throws WrappedException {
233 this.delegate = delegate;
234 agent = new ProxyAgent();
235 }
236
237 public T get() {
238 return this.delegate;
239 }
240
241 }