View Javadoc

1   package org.apache.torque.map;
2   
3   /*
4    * Copyright 2001-2005 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License")
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
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 326224 2005-10-18 20:35:33Z tfischer $
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, size, and scale.
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      * @param scale An int specifying the scale.
300      */
301     public void addColumn(String columnName, Object type, int size, int scale)
302     {
303         addColumn(columnName, type, false, null, null, size, scale);
304     }
305     
306     /***
307      * Add a column to this table of a certain type and size.
308      *
309      * @param columnName A String with the column name.
310      * @param type An Object specifying the type.
311      * @param size An int specifying the size.
312      */
313     public void addColumn(String columnName, Object type, int size)
314     {
315         addColumn(columnName, type, false, null, null, size);
316     }
317 
318     /***
319      * Add a primary key column to this Table.
320      *
321      * @param columnName A String with the column name.
322      * @param type An Object specifying the type.
323      */
324     public void addPrimaryKey(String columnName, Object type)
325     {
326         addColumn(columnName, type, true, null, null, 0);
327     }
328 
329     /***
330      * Add a primary key column to this Table.
331      *
332      * @param columnName A String with the column name.
333      * @param type An Object specifying the type.
334      * @param size An int specifying the size.
335      */
336     public void addPrimaryKey(String columnName, Object type, int size)
337     {
338         addColumn(columnName, type, true, null, null, size);
339     }
340 
341     /***
342      * Add a foreign key column to the table.
343      *
344      * @param columnName A String with the column name.
345      * @param type An Object specifying the type.
346      * @param fkTable A String with the foreign key table name.
347      * @param fkColumn A String with the foreign key column name.
348      */
349     public void addForeignKey(String columnName,
350                               Object type,
351                               String fkTable,
352                               String fkColumn)
353     {
354         addColumn(columnName, type, false, fkTable, fkColumn, 0);
355     }
356 
357     /***
358      * Add a foreign key column to the table.
359      *
360      * @param columnName A String with the column name.
361      * @param type An Object specifying the type.
362      * @param fkTable A String with the foreign key table name.
363      * @param fkColumn A String with the foreign key column name.
364      * @param size An int specifying the size.
365      */
366     public void addForeignKey(String columnName,
367                               Object type,
368                               String fkTable,
369                               String fkColumn,
370                               int size)
371     {
372         addColumn(columnName, type, false, fkTable, fkColumn, size);
373     }
374 
375     /***
376      * Add a foreign primary key column to the table.
377      *
378      * @param columnName A String with the column name.
379      * @param type An Object specifying the type.
380      * @param fkTable A String with the foreign key table name.
381      * @param fkColumn A String with the foreign key column name.
382      */
383     public void addForeignPrimaryKey(String columnName,
384                                      Object type,
385                                      String fkTable,
386                                      String fkColumn)
387     {
388         addColumn(columnName, type, true, fkTable, fkColumn, 0);
389     }
390 
391     /***
392      * Add a foreign primary key column to the table.
393      *
394      * @param columnName A String with the column name.
395      * @param type An Object specifying the type.
396      * @param fkTable A String with the foreign key table name.
397      * @param fkColumn A String with the foreign key column name.
398      * @param size An int specifying the size.
399      */
400     public void addForeignPrimaryKey(String columnName,
401                                      Object type,
402                                      String fkTable,
403                                      String fkColumn,
404                                      int size)
405     {
406         addColumn(columnName, type, true, fkTable, fkColumn, size);
407     }
408 
409     /***
410      * Add a column to the table.
411      *
412      * @param name A String with the column name.
413      * @param type An Object specifying the type.
414      * @param pk True if column is a primary key.
415      * @param fkTable A String with the foreign key table name.
416      * @param fkColumn A String with the foreign key column name.
417      * @param size An int specifying the size.
418      */
419     private void addColumn(String name,
420                            Object type,
421                            boolean pk,
422                            String fkTable,
423                            String fkColumn,
424                            int size)
425     {
426         addColumn(name, type, pk, fkTable,fkColumn, size, 0 );
427     }
428 
429     /***
430      * Add a column to the table.
431      *
432      * @param name A String with the column name.
433      * @param type An Object specifying the type.
434      * @param pk True if column is a primary key.
435      * @param fkTable A String with the foreign key table name.
436      * @param fkColumn A String with the foreign key column name.
437      * @param size An int specifying the size.
438      * @param scale An int specifying the scale.
439      */
440     private void addColumn(String name,
441                            Object type,
442                            boolean pk,
443                            String fkTable,
444                            String fkColumn,
445                            int size,
446                            int scale)
447     {
448         // If the tablename is prefixed with the name of the column,
449         // remove it ie: SCARAB_PROJECT.PROJECT_ID remove the
450         // SCARAB_PROJECT.
451         if (name.indexOf('.') > 0 && name.indexOf(getName()) != -1)
452         {
453             name = name.substring(getName().length() + 1);
454         }
455         if (fkTable != null && fkTable.length() > 0 && fkColumn != null
456                 && fkColumn.length() > 0)
457         {
458             if (fkColumn.indexOf('.') > 0 && fkColumn.indexOf(fkTable) != -1)
459             {
460                 fkColumn = fkColumn.substring(fkTable.length() + 1);
461             }
462         }
463         ColumnMap col = new ColumnMap(name, this);
464         col.setType(type);
465         col.setPrimaryKey(pk);
466         col.setForeignKey(fkTable, fkColumn);
467         col.setSize(size);
468         col.setScale(scale);
469         columns.put(name, col);
470     }
471 
472     /***
473      * Sets the method used to generate a key for this table.  Valid
474      * values are as specified in the {@link
475      * org.apache.torque.adapter.IDMethod} interface.
476      *
477      * @param method The ID generation method type name.
478      */
479     public void setPrimaryKeyMethod(String method)
480     {
481         primaryKeyMethod = NO_ID_METHOD;
482 
483         // Validate ID generation method.
484         for (int i = 0; i < VALID_ID_METHODS.length; i++)
485         {
486             if (VALID_ID_METHODS[i].equalsIgnoreCase(method))
487             {
488                 primaryKeyMethod = method;
489                 break;
490             }
491         }
492     }
493 
494     /***
495      * Sets the pk information needed to generate a key
496      *
497      * @param pkInfo information needed to generate a key
498      */
499     public void setPrimaryKeyMethodInfo(Object pkInfo)
500     {
501         this.pkInfo = pkInfo;
502     }
503 
504     //---Utility methods for doing intelligent lookup of table names
505 
506     /***
507      * Tell me if i have PREFIX in my string.
508      *
509      * @param data A String.
510      * @return True if prefix is contained in data.
511      */
512     private final boolean hasPrefix(String data)
513     {
514         return (data.indexOf(getPrefix()) != -1);
515     }
516 
517     /***
518      * Removes the PREFIX.
519      *
520      * @param data A String.
521      * @return A String with data, but with prefix removed.
522      */
523     private final String removePrefix(String data)
524     {
525         return data.substring(getPrefix().length());
526     }
527 
528     /***
529      * Removes the PREFIX, removes the underscores and makes
530      * first letter caps.
531      *
532      * SCARAB_FOO_BAR becomes FooBar.
533      *
534      * @param data A String.
535      * @return A String with data processed.
536      */
537     public final String removeUnderScores(String data)
538     {
539         String tmp = null;
540         StringBuffer out = new StringBuffer();
541         if (hasPrefix(data))
542         {
543             tmp = removePrefix(data);
544         }
545         else
546         {
547             tmp = data;
548         }
549 
550         StringTokenizer st = new StringTokenizer(tmp, "_");
551         while (st.hasMoreTokens())
552         {
553             String element = ((String) st.nextElement()).toLowerCase();
554             out.append(StringUtils.capitalize(element));
555         }
556         return out.toString();
557     }
558 }