1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 package org.melati.poem;
45
46 import java.lang.reflect.Method;
47 import java.lang.reflect.Modifier;
48 import java.util.Collection;
49 import java.util.Enumeration;
50 import java.util.Hashtable;
51 import java.util.Map;
52
53 import org.melati.poem.util.ClassUtils;
54 import org.melati.poem.util.StringUtils;
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 public final class TableFactory {
72
73
74
75
76 private TableFactory() {
77 }
78
79
80
81
82
83
84
85
86 public static Table<?> fromInstance(Database db, Object pojo) {
87 return fromClass(db, pojo.getClass());
88 }
89
90
91
92
93
94
95
96
97 public static Table<?> fromClass(Database db, Class<?> clazz) {
98 if (clazz.isPrimitive())
99 throw new IllegalArgumentException(
100 "Cannot create a Table for a primitive type: " + clazz.getName());
101 if (clazz.isInterface())
102 throw new IllegalArgumentException(
103 "Cannot create a Table for an interface: " + clazz.getName());
104 if(!Modifier.isPublic(clazz.getModifiers()))
105 throw new IllegalArgumentException(
106 "Cannot create a Table for a non public type: "+ clazz.getName());
107 if (clazz.isArray() && !(clazz == byte[].class))
108 throw new IllegalArgumentException("Cannot create a Table for an array: " + clazz.getName());
109 String name = clazz.getName();
110 String simpleName = name.substring(name.lastIndexOf('.') + 1);
111 try {
112 return db.getTable(simpleName);
113 } catch (NoSuchTablePoemException e) {
114 System.err.println("Creating a table for : " + name);
115 }
116
117 TableInfo tableInfo = (TableInfo)db.getTableInfoTable().newPersistent();
118 tableInfo.setName(simpleName);
119 tableInfo.setDisplayname(simpleName);
120 tableInfo.setDescription(simpleName + " introspected table");
121 tableInfo.setDisplayorder(13);
122 tableInfo.setSeqcached(Boolean.FALSE);
123 tableInfo.setCategory(db.getTableCategoryTable().NORMAL);
124 tableInfo.setCachelimit(555);
125 tableInfo.makePersistent();
126
127 Table<Persistent> table = new JdbcTable<Persistent>(db, simpleName, DefinitionSource.runtime);
128 String troidName = "id";
129 if (ClassUtils.getNoArgMethod(clazz, "getId") != null &&
130 !(Persistent.class.isAssignableFrom(clazz)))
131 troidName = "poemId";
132 table.defineColumn(new ExtraColumn<Integer>(table, troidName, TroidPoemType.it,
133 DefinitionSource.runtime, table.getNextExtrasIndex()));
134 table.setTableInfo(tableInfo);
135 table.unifyWithColumnInfo();
136 table.unifyWithDB(null,troidName);
137
138 PoemThread.commit();
139 db.defineTable(table);
140 Hashtable<String,Prop> props = new Hashtable<String,Prop>();
141
142 Method[] methods = clazz.getMethods();
143
144 for (int i = 0; i < methods.length; i++) {
145 if (Modifier.isPublic(methods[i].getModifiers())) {
146 if (methods[i].getName().startsWith("set")
147 && ! methods[i].getName().equals("set")
148 && Character.isUpperCase(methods[i].getName().toCharArray()[3])
149 && methods[i].getParameterTypes().length == 1
150 && (methods[i].getParameterTypes()[0] == byte[].class ||
151 ! methods[i].getParameterTypes()[0].isArray())
152 && !methods[i].getParameterTypes()[0].isInterface()
153 && ! Collection.class.isAssignableFrom(methods[i].getParameterTypes()[0])
154 && ! Map.class.isAssignableFrom(methods[i].getParameterTypes()[0])
155 ) {
156 String propName = methods[i].getName().substring(3);
157 propName = StringUtils.uncapitalised(propName);
158 Prop p = (Prop)props.get(propName);
159 Class<?> setClass = methods[i].getParameterTypes()[0];
160 if (p == null) {
161 p = new Prop(propName);
162 p.setSet(setClass);
163 } else {
164 if (p.getGot() != null) {
165 if(p.getGot() == setClass)
166 p.setSet(setClass);
167 } else {
168 p.setSet(setClass);
169 }
170 }
171 props.put(propName, p);
172 }
173
174 if (methods[i].getParameterTypes().length == 0
175 && ! methods[i].getReturnType().isInterface()
176 && (methods[i].getReturnType() == byte[].class ||
177 !methods[i].getReturnType().isArray())
178 && !Collection.class.isAssignableFrom(methods[i].getReturnType())
179 && !Map.class.isAssignableFrom(methods[i].getReturnType())
180 ) {
181 String propName = null;
182 if ((methods[i].getName().startsWith("get")) &&
183 Character.isUpperCase(methods[i].getName().toCharArray()[3]))
184 propName = methods[i].getName().substring(3);
185 else if (methods[i].getName().startsWith("is") &&
186 Character.isUpperCase(methods[i].getName().toCharArray()[2]))
187 propName = methods[i].getName().substring(2);
188 if (propName != null) {
189 propName = StringUtils.uncapitalised(propName);
190 Prop p = (Prop)props.get(propName);
191 Class<?> gotClass = methods[i].getReturnType();
192 if (p == null) {
193 p = new Prop(propName);
194 p.setGot(gotClass);
195 } else {
196 p.setGot(gotClass);
197 }
198 props.put(propName, p);
199 }
200 }
201 }
202 }
203 Enumeration<Prop> propsEn = props.elements();
204 while (propsEn.hasMoreElements()) {
205 Prop p = (Prop)propsEn.nextElement();
206 if (p.getGot() != null &&
207 p.getGot() == p.getSet()) {
208 addColumn(table, p.getName(), p.getGot(), p.getGot() == p.getSet());
209 }
210 }
211 return table;
212 }
213
214 private static void addColumn(Table<?> table, String name, Class<?> fieldClass,
215 boolean hasSetter) {
216 ColumnInfo columnInfo = (ColumnInfo)table.getDatabase()
217 .getColumnInfoTable().newPersistent();
218 columnInfo.setTableinfo(table.getInfo());
219 columnInfo.setName(name);
220
221 columnInfo.setDisplayname(name);
222 columnInfo.setDisplayorder(99);
223 columnInfo.setSearchability(Searchability.yes);
224 columnInfo.setIndexed(false);
225 columnInfo.setUnique(false);
226 columnInfo.setDescription("An introspected member");
227 columnInfo.setUsercreateable(hasSetter);
228 columnInfo.setUsereditable(hasSetter);
229 columnInfo.setSize(8);
230 columnInfo.setWidth(20);
231 columnInfo.setHeight(1);
232 columnInfo.setPrecision(0);
233 columnInfo.setScale(0);
234 columnInfo.setNullable(true);
235 columnInfo.setDisplaylevel(DisplayLevel.record);
236 if (fieldClass == java.lang.Boolean.class) {
237 columnInfo.setTypefactory(PoemTypeFactory.BOOLEAN);
238 columnInfo.setSize(1);
239 columnInfo.setWidth(10);
240 } else if (fieldClass == boolean.class) {
241 columnInfo.setTypefactory(PoemTypeFactory.BOOLEAN);
242 columnInfo.setSize(1);
243 columnInfo.setWidth(10);
244 } else if (fieldClass == java.lang.Integer.class) {
245 columnInfo.setTypefactory(PoemTypeFactory.INTEGER);
246 } else if (fieldClass == int.class) {
247 columnInfo.setTypefactory(PoemTypeFactory.INTEGER);
248 } else if (fieldClass == java.lang.Double.class) {
249 columnInfo.setTypefactory(PoemTypeFactory.DOUBLE);
250 } else if (fieldClass == double.class) {
251 columnInfo.setTypefactory(PoemTypeFactory.DOUBLE);
252 } else if (fieldClass == java.lang.Long.class) {
253 columnInfo.setTypefactory(PoemTypeFactory.LONG);
254 } else if (fieldClass == long.class) {
255 columnInfo.setTypefactory(PoemTypeFactory.LONG);
256 } else if (fieldClass == java.math.BigDecimal.class) {
257 columnInfo.setTypefactory(PoemTypeFactory.BIGDECIMAL);
258 columnInfo.setPrecision(22);
259 columnInfo.setScale(2);
260 } else if (fieldClass == java.lang.String.class) {
261 columnInfo.setTypefactory(PoemTypeFactory.STRING);
262 columnInfo.setSize(-1);
263 } else if (fieldClass == java.sql.Date.class) {
264 columnInfo.setTypefactory(PoemTypeFactory.DATE);
265 } else if (fieldClass == java.sql.Timestamp.class) {
266 columnInfo.setTypefactory(PoemTypeFactory.TIMESTAMP);
267 } else if (fieldClass == byte[].class) {
268 columnInfo.setTypefactory(PoemTypeFactory.BINARY);
269 }
270 else {
271 Table<?> referredTable = fromClass(table.getDatabase(), fieldClass);
272 columnInfo.setTypefactory(PoemTypeFactory.forCode(table.getDatabase(),
273 referredTable.getInfo().troid().intValue()));
274 }
275 columnInfo.makePersistent();
276 table.addColumnAndCommit(columnInfo);
277 }
278
279
280
281
282 static final class Prop {
283 String name = null;
284 Class<?> set = null;
285 Class<?> got = null;
286
287 Prop(String name) {
288 this.name = name;
289 }
290
291
292
293
294 public String getName() {
295 return name;
296 }
297
298
299
300
301 public Class<?> getGot() {
302 return got;
303 }
304
305
306
307
308
309 public void setGot(Class<?> got) {
310 this.got = got;
311 }
312
313
314
315
316 public Class<?> getSet() {
317 return set;
318 }
319
320
321
322
323
324 public void setSet(Class<?> set) {
325 this.set = set;
326 }
327
328 }
329 }