View Javadoc

1   package org.apache.torque.map;
2   
3   /*
4    * Copyright 2001-2004 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,v 1.16 2005/01/31 19:43:54 tfischer Exp $
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         // If the tablename is prefixed with the name of the column,
414         // remove it ie: SCARAB_PROJECT.PROJECT_ID remove the
415         // SCARAB_PROJECT.
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         // Validate ID generation method.
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     //---Utility methods for doing intelligent lookup of table names
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 }