1 package org.apache.torque.map;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import java.util.Iterator;
20 import java.util.Hashtable;
21 import java.util.StringTokenizer;
22
23 import org.apache.commons.lang.StringUtils;
24
25 import org.apache.torque.adapter.IDMethod;
26 import org.apache.torque.oid.IdGenerator;
27
28 /***
29 * TableMap is used to model a table in a database.
30 *
31 * @author <a href="mailto:jmcnally@collab.net">John D. McNally</a>
32 * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
33 * @version $Id: TableMap.java 239630 2005-08-24 12:25:32Z henning $
34 */
35 public class TableMap implements IDMethod, java.io.Serializable
36 {
37 /*** The list of valid ID generation methods. */
38 protected static final String[] VALID_ID_METHODS =
39 {
40 NATIVE, AUTO_INCREMENT, SEQUENCE, ID_BROKER, NO_ID_METHOD
41 };
42
43 /*** The columns in the table. */
44 private Hashtable columns;
45
46 /*** The database this table belongs to. */
47 private DatabaseMap dbMap;
48
49 /*** The name of the table. */
50 private String tableName;
51
52 /*** The prefix on the table name. */
53 private String prefix;
54
55 /*** The primary key generation method. */
56 private String primaryKeyMethod = NO_ID_METHOD;
57
58 /***
59 * Object to store information that is needed if the
60 * for generating primary keys.
61 */
62 private Object pkInfo = null;
63
64 /***
65 * Required by proxy. Not used.
66 */
67 public TableMap()
68 {
69 }
70
71 /***
72 * Constructor.
73 *
74 * @param tableName The name of the table.
75 * @param numberOfColumns The number of columns in the table.
76 * @param containingDB A DatabaseMap that this table belongs to.
77 */
78 public TableMap(String tableName,
79 int numberOfColumns,
80 DatabaseMap containingDB)
81 {
82 this.tableName = tableName;
83 dbMap = containingDB;
84 columns = new Hashtable((int) (1.25 * numberOfColumns) + 1);
85 }
86
87 /***
88 * Constructor.
89 *
90 * @param tableName The name of the table.
91 * @param containingDB A DatabaseMap that this table belongs to.
92 */
93 public TableMap(String tableName, DatabaseMap containingDB)
94 {
95 this.tableName = tableName;
96 dbMap = containingDB;
97 columns = new Hashtable(20);
98 }
99
100 /***
101 * Constructor.
102 *
103 * @param tableName The name of the table.
104 * @param prefix The prefix for the table name (ie: SCARAB for
105 * SCARAB_PROJECT).
106 * @param containingDB A DatabaseMap that this table belongs to.
107 */
108 public TableMap(String tableName,
109 String prefix,
110 DatabaseMap containingDB)
111 {
112 this.tableName = tableName;
113 this.prefix = prefix;
114 dbMap = containingDB;
115 columns = new Hashtable(20);
116 }
117
118 /***
119 * Does this table contain the specified column?
120 *
121 * @param column A ColumnMap.
122 * @return True if the table contains the column.
123 */
124 public boolean containsColumn(ColumnMap column)
125 {
126 return containsColumn(column.getColumnName());
127 }
128
129 /***
130 * Does this table contain the specified column?
131 *
132 * @param name A String with the name of the column.
133 * @return True if the table contains the column.
134 */
135 public boolean containsColumn(String name)
136 {
137 if (name.indexOf('.') > 0)
138 {
139 name = name.substring(name.indexOf('.') + 1);
140 }
141 return columns.containsKey(name);
142 }
143
144 /***
145 * Get the DatabaseMap containing this TableMap.
146 *
147 * @return A DatabaseMap.
148 */
149 public DatabaseMap getDatabaseMap()
150 {
151 return dbMap;
152 }
153
154 /***
155 * Returns true if this tableMap contains a column with object
156 * data. If the type of the column is not a string, a number or a
157 * date, it is assumed that it is object data.
158 *
159 * @return True if map contains a column with object data.
160 */
161 public boolean containsObjectColumn()
162 {
163 Iterator it = columns.values().iterator();
164 while (it.hasNext())
165 {
166 Object theType = ((ColumnMap) it.next()).getType();
167 if (!(theType instanceof String || theType instanceof Number
168 || theType instanceof java.util.Date))
169 {
170 return true;
171 }
172 }
173 return false;
174 }
175
176 /***
177 * Get the name of the Table.
178 *
179 * @return A String with the name of the table.
180 */
181 public String getName()
182 {
183 return tableName;
184 }
185
186 /***
187 * Get table prefix name.
188 *
189 * @return A String with the prefix.
190 */
191 public String getPrefix()
192 {
193 return this.prefix;
194 }
195
196 /***
197 * Set table prefix name.
198 *
199 * @param prefix The prefix for the table name (ie: SCARAB for
200 * SCARAB_PROJECT).
201 */
202 public void setPrefix(String prefix)
203 {
204 this.prefix = prefix;
205 }
206
207 /***
208 * Get the method used to generate primary keys for this table.
209 *
210 * @return A String with the method.
211 */
212 public String getPrimaryKeyMethod()
213 {
214 return primaryKeyMethod;
215 }
216
217 /***
218 * Get the value of idGenerator.
219 * @return value of idGenerator.
220 */
221 public IdGenerator getIdGenerator()
222 {
223 return getDatabaseMap().getIdGenerator(primaryKeyMethod);
224 }
225
226 /***
227 * Get the information used to generate a primary key
228 *
229 * @return An Object.
230 */
231 public Object getPrimaryKeyMethodInfo()
232 {
233 return pkInfo;
234 }
235
236 /***
237 * Get a ColumnMap[] of the columns in this table.
238 *
239 * @return A ColumnMap[].
240 */
241 public ColumnMap[] getColumns()
242 {
243 ColumnMap[] tableColumns = new ColumnMap[columns.size()];
244 Iterator it = columns.values().iterator();
245 int i = 0;
246 while (it.hasNext())
247 {
248 tableColumns[i++] = (ColumnMap) it.next();
249 }
250 return tableColumns;
251 }
252
253 /***
254 * Get a ColumnMap for the named table.
255 *
256 * @param name A String with the name of the table.
257 * @return A ColumnMap.
258 */
259 public ColumnMap getColumn(String name)
260 {
261 try
262 {
263 return (ColumnMap) columns.get(name);
264 }
265 catch (Exception e)
266 {
267 return null;
268 }
269 }
270
271 /***
272 * Add a pre-created column to this table. It will replace any
273 * existing column.
274 *
275 * @param cmap A ColumnMap.
276 */
277 public void addColumn (ColumnMap cmap)
278 {
279 columns.put (cmap.getColumnName(), cmap);
280 }
281
282 /***
283 * Add a column to this table of a certain type.
284 *
285 * @param columnName A String with the column name.
286 * @param type An Object specifying the type.
287 */
288 public void addColumn(String columnName, Object type)
289 {
290 addColumn(columnName, type, false, null, null, 0);
291 }
292
293 /***
294 * Add a column to this table of a certain type and size.
295 *
296 * @param columnName A String with the column name.
297 * @param type An Object specifying the type.
298 * @param size An int specifying the size.
299 */
300 public void addColumn(String columnName, Object type, int size)
301 {
302 addColumn(columnName, type, false, null, null, size);
303 }
304
305 /***
306 * Add a primary key column to this Table.
307 *
308 * @param columnName A String with the column name.
309 * @param type An Object specifying the type.
310 */
311 public void addPrimaryKey(String columnName, Object type)
312 {
313 addColumn(columnName, type, true, null, null, 0);
314 }
315
316 /***
317 * Add a primary key column to this Table.
318 *
319 * @param columnName A String with the column name.
320 * @param type An Object specifying the type.
321 * @param size An int specifying the size.
322 */
323 public void addPrimaryKey(String columnName, Object type, int size)
324 {
325 addColumn(columnName, type, true, null, null, size);
326 }
327
328 /***
329 * Add a foreign key column to the table.
330 *
331 * @param columnName A String with the column name.
332 * @param type An Object specifying the type.
333 * @param fkTable A String with the foreign key table name.
334 * @param fkColumn A String with the foreign key column name.
335 */
336 public void addForeignKey(String columnName,
337 Object type,
338 String fkTable,
339 String fkColumn)
340 {
341 addColumn(columnName, type, false, fkTable, fkColumn, 0);
342 }
343
344 /***
345 * Add a foreign key column to the table.
346 *
347 * @param columnName A String with the column name.
348 * @param type An Object specifying the type.
349 * @param fkTable A String with the foreign key table name.
350 * @param fkColumn A String with the foreign key column name.
351 * @param size An int specifying the size.
352 */
353 public void addForeignKey(String columnName,
354 Object type,
355 String fkTable,
356 String fkColumn,
357 int size)
358 {
359 addColumn(columnName, type, false, fkTable, fkColumn, size);
360 }
361
362 /***
363 * Add a foreign primary key column to the table.
364 *
365 * @param columnName A String with the column name.
366 * @param type An Object specifying the type.
367 * @param fkTable A String with the foreign key table name.
368 * @param fkColumn A String with the foreign key column name.
369 */
370 public void addForeignPrimaryKey(String columnName,
371 Object type,
372 String fkTable,
373 String fkColumn)
374 {
375 addColumn(columnName, type, true, fkTable, fkColumn, 0);
376 }
377
378 /***
379 * Add a foreign primary key column to the table.
380 *
381 * @param columnName A String with the column name.
382 * @param type An Object specifying the type.
383 * @param fkTable A String with the foreign key table name.
384 * @param fkColumn A String with the foreign key column name.
385 * @param size An int specifying the size.
386 */
387 public void addForeignPrimaryKey(String columnName,
388 Object type,
389 String fkTable,
390 String fkColumn,
391 int size)
392 {
393 addColumn(columnName, type, true, fkTable, fkColumn, size);
394 }
395
396 /***
397 * Add a column to the table.
398 *
399 * @param name A String with the column name.
400 * @param type An Object specifying the type.
401 * @param pk True if column is a primary key.
402 * @param fkTable A String with the foreign key table name.
403 * @param fkColumn A String with the foreign key column name.
404 * @param size An int specifying the size.
405 */
406 private void addColumn(String name,
407 Object type,
408 boolean pk,
409 String fkTable,
410 String fkColumn,
411 int size)
412 {
413
414
415
416 if (name.indexOf('.') > 0 && name.indexOf(getName()) != -1)
417 {
418 name = name.substring(getName().length() + 1);
419 }
420 if (fkTable != null && fkTable.length() > 0 && fkColumn != null
421 && fkColumn.length() > 0)
422 {
423 if (fkColumn.indexOf('.') > 0 && fkColumn.indexOf(fkTable) != -1)
424 {
425 fkColumn = fkColumn.substring(fkTable.length() + 1);
426 }
427 }
428 ColumnMap col = new ColumnMap(name, this);
429 col.setType(type);
430 col.setPrimaryKey(pk);
431 col.setForeignKey(fkTable, fkColumn);
432 col.setSize(size);
433 columns.put(name, col);
434 }
435
436 /***
437 * Sets the method used to generate a key for this table. Valid
438 * values are as specified in the {@link
439 * org.apache.torque.adapter.IDMethod} interface.
440 *
441 * @param method The ID generation method type name.
442 */
443 public void setPrimaryKeyMethod(String method)
444 {
445 primaryKeyMethod = NO_ID_METHOD;
446
447
448 for (int i = 0; i < VALID_ID_METHODS.length; i++)
449 {
450 if (VALID_ID_METHODS[i].equalsIgnoreCase(method))
451 {
452 primaryKeyMethod = method;
453 break;
454 }
455 }
456 }
457
458 /***
459 * Sets the pk information needed to generate a key
460 *
461 * @param pkInfo information needed to generate a key
462 */
463 public void setPrimaryKeyMethodInfo(Object pkInfo)
464 {
465 this.pkInfo = pkInfo;
466 }
467
468
469
470 /***
471 * Tell me if i have PREFIX in my string.
472 *
473 * @param data A String.
474 * @return True if prefix is contained in data.
475 */
476 private final boolean hasPrefix(String data)
477 {
478 return (data.indexOf(getPrefix()) != -1);
479 }
480
481 /***
482 * Removes the PREFIX.
483 *
484 * @param data A String.
485 * @return A String with data, but with prefix removed.
486 */
487 private final String removePrefix(String data)
488 {
489 return data.substring(getPrefix().length());
490 }
491
492 /***
493 * Removes the PREFIX, removes the underscores and makes
494 * first letter caps.
495 *
496 * SCARAB_FOO_BAR becomes FooBar.
497 *
498 * @param data A String.
499 * @return A String with data processed.
500 */
501 public final String removeUnderScores(String data)
502 {
503 String tmp = null;
504 StringBuffer out = new StringBuffer();
505 if (hasPrefix(data))
506 {
507 tmp = removePrefix(data);
508 }
509 else
510 {
511 tmp = data;
512 }
513
514 StringTokenizer st = new StringTokenizer(tmp, "_");
515 while (st.hasMoreTokens())
516 {
517 String element = ((String) st.nextElement()).toLowerCase();
518 out.append(StringUtils.capitalize(element));
519 }
520 return out.toString();
521 }
522 }