1 | |
package org.kuali.student.common.dictionary.service.impl; |
2 | |
|
3 | |
import java.beans.BeanInfo; |
4 | |
import java.beans.IntrospectionException; |
5 | |
import java.beans.Introspector; |
6 | |
import java.beans.PropertyDescriptor; |
7 | |
import java.io.File; |
8 | |
import java.io.FileNotFoundException; |
9 | |
import java.io.FileOutputStream; |
10 | |
import java.io.IOException; |
11 | |
import java.io.OutputStream; |
12 | |
import java.lang.reflect.ParameterizedType; |
13 | |
import java.util.Date; |
14 | |
import java.util.HashSet; |
15 | |
import java.util.List; |
16 | |
import java.util.Set; |
17 | |
|
18 | |
import org.kuali.student.common.dictionary.dto.FieldDefinition; |
19 | |
import org.kuali.student.common.dto.Idable; |
20 | |
import org.kuali.student.common.dto.MetaInfo; |
21 | |
|
22 | 0 | public class DictionaryCreator |
23 | |
{ |
24 | |
|
25 | |
private static final String OBJECT_STRUCTURE_CLASS = |
26 | |
"objectStructureDefinition"; |
27 | 0 | private static final String FIELD_DEFINITION_CLASS = |
28 | |
FieldDefinition.class.getSimpleName (); |
29 | |
private static final String ATTRIBUTES = "attributes"; |
30 | |
private static final String NAME = "name"; |
31 | |
private static final String HAS_META_DATA = "hasMetaData"; |
32 | |
private static final String DATA_OBJECT_STRUCTURE = "dataObjectStructure"; |
33 | |
private static final String BASE_INTEGER_REPEATING = "baseIntegerRepeating"; |
34 | |
private static final String BASE_LONG_REPEATING = "baseLongRepeating"; |
35 | |
private static final String BASE_DOUBLE_REPEATING = "baseDoubleRepeating"; |
36 | |
private static final String BASE_FLOAT_REPEATING = "baseFloatRepeating"; |
37 | |
private static final String BASE_BOOLEAN_REPEATING = "baseBooleanRepeating"; |
38 | |
private static final String BASE_DATE_REPEATING = "baseDateRepeating"; |
39 | |
private static final String BASE_STRING_REPEATING = "baseStringRepeating"; |
40 | |
private static final String BASE_COMPLEX_REPEATING = "baseComplexRepeating"; |
41 | |
private static final String BASE_INTEGER = "baseInteger"; |
42 | |
private static final String BASE_LONG = "baseLong"; |
43 | |
private static final String BASE_DOUBLE = "baseDouble"; |
44 | |
private static final String BASE_FLOAT = "baseFloat"; |
45 | |
private static final String BASE_BOOLEAN = "baseBoolean"; |
46 | |
private static final String BASE_DATE = "baseDate"; |
47 | |
private static final String BASE_STRING = "baseString"; |
48 | |
private static final String BASE_COMPLEX = "baseComplex"; |
49 | |
private static final String BASE_KUALI_ID = "baseKualiId"; |
50 | |
private static final String BASE_KUALI_ORG_ID = "baseKualiOrgId"; |
51 | |
private static final String BASE_KUALI_CLU_ID = "baseKualiCluId"; |
52 | |
private static final String BASE_KUALI_PERSON_ID = "baseKualiPersonId"; |
53 | |
private static final String BASE_KUALI_TYPE = "baseKualiType"; |
54 | |
private static final String BASE_KUALI_STATE = "baseKualiState"; |
55 | |
private static final String BASE_KUALI_EFFECTIVE_DATE = |
56 | |
"baseKualiEffectiveDate"; |
57 | |
private static final String BASE_KUALI_EXPIRATION_DATE = |
58 | |
"baseKualiExpirationDate"; |
59 | |
|
60 | |
|
61 | |
public void execute (Class<?> clazz, String outputFileName) |
62 | |
{ |
63 | |
|
64 | 0 | File file = new File (outputFileName); |
65 | |
OutputStream os; |
66 | |
try |
67 | |
{ |
68 | 0 | os = new FileOutputStream (file); |
69 | |
} |
70 | 0 | catch (FileNotFoundException ex) |
71 | |
{ |
72 | 0 | throw new IllegalArgumentException (ex); |
73 | 0 | } |
74 | 0 | StringBuffer s = new StringBuffer (); |
75 | 0 | addSpringHeaderOpen (s); |
76 | |
|
77 | 0 | System.out.println (clazz.getName ()); |
78 | 0 | addObjectStructure (clazz, s, new HashSet<Class<?>> ()); |
79 | |
|
80 | 0 | addSpringHeaderClose (s); |
81 | |
try |
82 | |
{ |
83 | 0 | os.write (s.toString ().getBytes ()); |
84 | |
} |
85 | 0 | catch (IOException ex) |
86 | |
{ |
87 | 0 | throw new IllegalArgumentException (ex); |
88 | 0 | } |
89 | 0 | } |
90 | |
|
91 | |
private void addObjectStructure (Class<?> clazz, StringBuffer s, |
92 | |
Set<Class<?>> processed) |
93 | |
{ |
94 | |
|
95 | 0 | if (processed.contains (clazz)) |
96 | |
{ |
97 | 0 | return; |
98 | |
} |
99 | 0 | processed.add (clazz); |
100 | |
|
101 | |
|
102 | 0 | s.append ("\n\n<!-- " + clazz.getSimpleName () + "-->"); |
103 | 0 | s.append ("\n<bean id=\"" + clazz.getName () |
104 | |
+ "-parent\" abstract=\"true\" parent=\"" + OBJECT_STRUCTURE_CLASS |
105 | |
+ "\">"); |
106 | 0 | addProperty (NAME, clazz.getName (), s); |
107 | 0 | s.append ("\n<property name=\"" + ATTRIBUTES + "\">"); |
108 | 0 | s.append ("\n<list>"); |
109 | |
BeanInfo beanInfo; |
110 | |
try |
111 | |
{ |
112 | 0 | beanInfo = Introspector.getBeanInfo (clazz); |
113 | |
} |
114 | 0 | catch (IntrospectionException ex) |
115 | |
{ |
116 | 0 | throw new IllegalArgumentException (ex); |
117 | 0 | } |
118 | 0 | boolean hasMetaData = false; |
119 | 0 | for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors ()) |
120 | |
{ |
121 | 0 | if ( ! MetaInfo.class.equals (pd.getPropertyType ()) && ! Class.class.equals ( |
122 | |
pd.getPropertyType ()) && ! ATTRIBUTES.equals (pd.getName ())) |
123 | |
{ |
124 | 0 | String fieldName = clazz.getSimpleName ().substring (0, 1).toLowerCase () + clazz.getSimpleName ().substring ( |
125 | |
1) + "." + pd.getName (); |
126 | 0 | s.append ("\n<ref bean=\"" + fieldName + "\"/>"); |
127 | 0 | } |
128 | |
else |
129 | |
{ |
130 | 0 | hasMetaData = true; |
131 | |
} |
132 | |
} |
133 | 0 | s.append ("\n</list>"); |
134 | 0 | s.append ("\n</property>"); |
135 | |
|
136 | 0 | addProperty (HAS_META_DATA, String.valueOf (hasMetaData), s); |
137 | 0 | s.append ("\n</bean>"); |
138 | |
|
139 | |
|
140 | 0 | s.append ("\n<bean id=\"" + clazz.getName () + "\" parent=\"" |
141 | |
+ clazz.getName () + "-parent\"/>"); |
142 | |
|
143 | 0 | Set<Class<?>> dependantStructures = new HashSet<Class<?>> (); |
144 | 0 | for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors ()) |
145 | |
{ |
146 | 0 | if ( ! MetaInfo.class.equals (pd.getPropertyType ()) && ! Class.class.equals ( |
147 | |
pd.getPropertyType ()) && ! ATTRIBUTES.equals (pd.getName ())) |
148 | |
{ |
149 | 0 | dependantStructures.addAll (addField (clazz, pd, s, processed)); |
150 | |
} |
151 | |
} |
152 | |
|
153 | 0 | for (Class<?> dependantClass : dependantStructures) |
154 | |
{ |
155 | 0 | addObjectStructure (dependantClass, s, processed); |
156 | |
} |
157 | |
|
158 | 0 | } |
159 | |
|
160 | |
private Set<Class<?>> addField (Class<?> clazz, PropertyDescriptor pd, |
161 | |
StringBuffer s, Set<Class<?>> processed) |
162 | |
{ |
163 | 0 | Set<Class<?>> dependantStructures = new HashSet<Class<?>> (); |
164 | |
|
165 | |
|
166 | 0 | String fieldName = clazz.getSimpleName ().substring (0, 1).toLowerCase () + clazz.getSimpleName ().substring ( |
167 | |
1) + "." + pd.getName (); |
168 | 0 | Class<?> pt = pd.getPropertyType (); |
169 | 0 | String parentField = FIELD_DEFINITION_CLASS; |
170 | 0 | boolean isComplex = false; |
171 | 0 | if (clazz.isAssignableFrom (Idable.class) && "id".equals (pd.getName ())) |
172 | |
{ |
173 | 0 | parentField = BASE_KUALI_ID; |
174 | |
} |
175 | 0 | else if (pd.getName ().endsWith ("orgId")) |
176 | |
{ |
177 | 0 | parentField = BASE_KUALI_ORG_ID; |
178 | |
} |
179 | 0 | else if (pd.getName ().endsWith ("personId")) |
180 | |
{ |
181 | 0 | parentField = BASE_KUALI_PERSON_ID; |
182 | |
} |
183 | 0 | else if (pd.getName ().endsWith ("cluId")) |
184 | |
{ |
185 | 0 | parentField = BASE_KUALI_CLU_ID; |
186 | |
} |
187 | 0 | else if (List.class.equals (pt)) |
188 | |
{ |
189 | |
try |
190 | |
{ |
191 | 0 | pt = |
192 | |
(Class<?>) ((ParameterizedType) clazz.getDeclaredField (pd.getName ()).getGenericType ()).getActualTypeArguments ()[0]; |
193 | |
} |
194 | 0 | catch (NoSuchFieldException ex) |
195 | |
{ |
196 | 0 | throw new IllegalArgumentException (ex); |
197 | |
} |
198 | 0 | catch (SecurityException ex) |
199 | |
{ |
200 | 0 | throw new IllegalArgumentException (ex); |
201 | 0 | } |
202 | 0 | if (int.class.equals (pt) || Integer.class.equals (pt)) |
203 | |
{ |
204 | 0 | parentField = BASE_INTEGER_REPEATING; |
205 | |
} |
206 | 0 | else if (long.class.equals (pt) || Long.class.equals (pt)) |
207 | |
{ |
208 | 0 | parentField = BASE_LONG_REPEATING; |
209 | |
} |
210 | 0 | else if (double.class.equals (pt) || Double.class.equals (pt)) |
211 | |
{ |
212 | 0 | parentField = BASE_DOUBLE_REPEATING; |
213 | |
} |
214 | 0 | else if (float.class.equals (pt) || Float.class.equals (pt)) |
215 | |
{ |
216 | 0 | parentField = BASE_FLOAT_REPEATING; |
217 | |
} |
218 | 0 | else if (boolean.class.equals (pt) || Boolean.class.equals (pt)) |
219 | |
{ |
220 | 0 | parentField = BASE_BOOLEAN_REPEATING; |
221 | |
} |
222 | 0 | else if (Date.class.equals (pt)) |
223 | |
{ |
224 | 0 | parentField = BASE_DATE_REPEATING; |
225 | |
} |
226 | 0 | else if (String.class.equals (pt)) |
227 | |
{ |
228 | 0 | parentField = BASE_STRING_REPEATING; |
229 | |
} |
230 | 0 | else if (List.class.equals (pt)) |
231 | |
{ |
232 | 0 | throw new RuntimeException ("Can't have a list of lists, List<List<?>> for property: " |
233 | |
+ fieldName); |
234 | |
} |
235 | |
else |
236 | |
{ |
237 | 0 | parentField = BASE_COMPLEX_REPEATING; |
238 | 0 | isComplex = true; |
239 | 0 | dependantStructures.add (pt); |
240 | |
} |
241 | |
} |
242 | |
else |
243 | |
{ |
244 | 0 | if (int.class.equals (pt) || Integer.class.equals (pt)) |
245 | |
{ |
246 | 0 | parentField = BASE_INTEGER; |
247 | |
} |
248 | 0 | else if (long.class.equals (pt) || Long.class.equals (pt)) |
249 | |
{ |
250 | 0 | parentField = BASE_LONG; |
251 | |
} |
252 | 0 | else if (double.class.equals (pt) || Double.class.equals (pt)) |
253 | |
{ |
254 | 0 | parentField = BASE_DOUBLE; |
255 | |
} |
256 | 0 | else if (float.class.equals (pt) || Float.class.equals (pt)) |
257 | |
{ |
258 | 0 | parentField = BASE_FLOAT; |
259 | |
} |
260 | 0 | else if (boolean.class.equals (pt) || Boolean.class.equals (pt)) |
261 | |
{ |
262 | 0 | parentField = BASE_BOOLEAN; |
263 | |
} |
264 | 0 | else if (Date.class.equals (pt)) |
265 | |
{ |
266 | 0 | parentField = BASE_DATE; |
267 | |
} |
268 | 0 | else if (String.class.equals (pt)) |
269 | |
{ |
270 | 0 | parentField = BASE_STRING; |
271 | |
} |
272 | |
else |
273 | |
{ |
274 | 0 | parentField = BASE_COMPLEX; |
275 | 0 | isComplex = true; |
276 | 0 | dependantStructures.add (pt); |
277 | |
} |
278 | |
} |
279 | |
|
280 | |
|
281 | 0 | s.append ("\n\n<bean id=\"" + fieldName |
282 | |
+ "-parent\" abstract=\"true\" parent=\"" + parentField + "\">"); |
283 | 0 | addProperty (NAME, pd.getName (), s); |
284 | 0 | if (isComplex) |
285 | |
{ |
286 | 0 | addPropertyRef (DATA_OBJECT_STRUCTURE, pt.getName (), s); |
287 | |
} |
288 | |
|
289 | 0 | s.append ("\n</bean>"); |
290 | |
|
291 | |
|
292 | 0 | s.append ("\n<bean id=\"" + fieldName + "\" parent=\"" + fieldName |
293 | |
+ "-parent\"/>"); |
294 | |
|
295 | 0 | return dependantStructures; |
296 | |
} |
297 | |
|
298 | |
private void addProperty (String propertyName, String propertyValue, |
299 | |
StringBuffer s) |
300 | |
{ |
301 | 0 | s.append ("\n<property name=\"" + propertyName + "\" value=\"" + propertyValue |
302 | |
+ "\"/>"); |
303 | 0 | } |
304 | |
|
305 | |
private static void addPropertyRef (String propertyName, String propertyValue, |
306 | |
StringBuffer s) |
307 | |
{ |
308 | 0 | s.append ("\n<property name=\"" + propertyName + "\" ref=\"" + propertyValue |
309 | |
+ "\"/>"); |
310 | 0 | } |
311 | |
|
312 | |
private void addSpringHeaderClose (StringBuffer s) |
313 | |
{ |
314 | 0 | s.append ("\n</beans>"); |
315 | 0 | } |
316 | |
|
317 | |
public void addSpringHeaderOpen (StringBuffer s) |
318 | |
{ |
319 | 0 | s.append ("<beans xmlns=\"http://www.springframework.org/schema/beans\"" |
320 | |
+ "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" |
321 | |
+ "xsi:schemaLocation=\"" |
322 | |
+ "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd" |
323 | |
+ "\">"); |
324 | 0 | s.append ("\n<import resource=\"classpath:ks-base-dictionary-context.xml\"/>"); |
325 | 0 | } |
326 | |
} |