View Javadoc

1   package org.apache.torque.map;
2   
3   /* ====================================================================
4    * The Apache Software License, Version 1.1
5    *
6    * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
7    * reserved.
8    *
9    * Redistribution and use in source and binary forms, with or without
10   * modification, are permitted provided that the following conditions
11   * are met:
12   *
13   * 1. Redistributions of source code must retain the above copyright
14   *    notice, this list of conditions and the following disclaimer.
15   *
16   * 2. Redistributions in binary form must reproduce the above copyright
17   *    notice, this list of conditions and the following disclaimer in
18   *    the documentation and/or other materials provided with the
19   *    distribution.
20   *
21   * 3. The end-user documentation included with the redistribution,
22   *    if any, must include the following acknowledgment:
23   *       "This product includes software developed by the
24   *        Apache Software Foundation (http://www.apache.org/)."
25   *    Alternately, this acknowledgment may appear in the software itself,
26   *    if and wherever such third-party acknowledgments normally appear.
27   *
28   * 4. The names "Apache" and "Apache Software Foundation" and
29   *    "Apache Turbine" must not be used to endorse or promote products
30   *    derived from this software without prior written permission. For
31   *    written permission, please contact apache@apache.org.
32   *
33   * 5. Products derived from this software may not be called "Apache",
34   *    "Apache Turbine", nor may "Apache" appear in their name, without
35   *    prior written permission of the Apache Software Foundation.
36   *
37   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48   * SUCH DAMAGE.
49   * ====================================================================
50   *
51   * This software consists of voluntary contributions made by many
52   * individuals on behalf of the Apache Software Foundation.  For more
53   * information on the Apache Software Foundation, please see
54   * <http://www.apache.org/>.
55   */
56  
57  import java.util.Iterator;
58  import java.util.Hashtable;
59  import java.util.StringTokenizer;
60  
61  import org.apache.commons.lang.StringUtils;
62  
63  import org.apache.torque.adapter.IDMethod;
64  import org.apache.torque.oid.IdGenerator;
65  
66  /***
67   * TableMap is used to model a table in a database.
68   *
69   * @author <a href="mailto:jmcnally@collab.net">John D. McNally</a>
70   * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
71   * @version $Id: TableMap.java,v 1.13 2003/08/23 13:18:54 mpoeschl Exp $
72   */
73  public class TableMap implements IDMethod, java.io.Serializable
74  {
75      /*** The list of valid ID generation methods. */
76      protected static final String[] VALID_ID_METHODS =
77      {
78          NATIVE, AUTO_INCREMENT, SEQUENCE, ID_BROKER, NO_ID_METHOD
79      };
80  
81      /*** The columns in the table. */
82      private Hashtable columns;
83  
84      /*** The database this table belongs to. */
85      private DatabaseMap dbMap;
86  
87      /*** The name of the table. */
88      private String tableName;
89  
90      /*** The prefix on the table name. */
91      private String prefix;
92  
93      /*** The primary key generation method. */
94      private String primaryKeyMethod = NO_ID_METHOD;
95  
96      /***
97       * Object to store information that is needed if the
98       * for generating primary keys.
99       */
100     private Object pkInfo = null;
101 
102     /***
103      * Required by proxy. Not used.
104      */
105     public TableMap()
106     {
107     }
108 
109     /***
110      * Constructor.
111      *
112      * @param tableName The name of the table.
113      * @param numberOfColumns The number of columns in the table.
114      * @param containingDB A DatabaseMap that this table belongs to.
115      */
116     public TableMap(String tableName,
117                     int numberOfColumns,
118                     DatabaseMap containingDB)
119     {
120         this.tableName = tableName;
121         dbMap = containingDB;
122         columns = new Hashtable((int) (1.25 * numberOfColumns) + 1);
123     }
124 
125     /***
126      * Constructor.
127      *
128      * @param tableName The name of the table.
129      * @param containingDB A DatabaseMap that this table belongs to.
130      */
131     public TableMap(String tableName, DatabaseMap containingDB)
132     {
133         this.tableName = tableName;
134         dbMap = containingDB;
135         columns = new Hashtable(20);
136     }
137 
138     /***
139      * Constructor.
140      *
141      * @param tableName The name of the table.
142      * @param prefix The prefix for the table name (ie: SCARAB for
143      * SCARAB_PROJECT).
144      * @param containingDB A DatabaseMap that this table belongs to.
145      */
146     public TableMap(String tableName,
147                     String prefix,
148                     DatabaseMap containingDB)
149     {
150         this.tableName = tableName;
151         this.prefix = prefix;
152         dbMap = containingDB;
153         columns = new Hashtable(20);
154     }
155 
156     /***
157      * Does this table contain the specified column?
158      *
159      * @param column A ColumnMap.
160      * @return True if the table contains the column.
161      */
162     public boolean containsColumn(ColumnMap column)
163     {
164         return containsColumn(column.getColumnName());
165     }
166 
167     /***
168      * Does this table contain the specified column?
169      *
170      * @param name A String with the name of the column.
171      * @return True if the table contains the column.
172      */
173     public boolean containsColumn(String name)
174     {
175         if (name.indexOf('.') > 0)
176         {
177             name = name.substring(name.indexOf('.') + 1);
178         }
179         return columns.containsKey(name);
180     }
181 
182     /***
183      * Get the DatabaseMap containing this TableMap.
184      *
185      * @return A DatabaseMap.
186      */
187     public DatabaseMap getDatabaseMap()
188     {
189         return dbMap;
190     }
191 
192     /***
193      * Returns true if this tableMap contains a column with object
194      * data.  If the type of the column is not a string, a number or a
195      * date, it is assumed that it is object data.
196      *
197      * @return True if map contains a column with object data.
198      */
199     public boolean containsObjectColumn()
200     {
201         Iterator it = columns.values().iterator();
202         while (it.hasNext())
203         {
204             Object theType = ((ColumnMap) it.next()).getType();
205             if (!(theType instanceof String || theType instanceof Number
206                     || theType instanceof java.util.Date))
207             {
208                 return true;
209             }
210         }
211         return false;
212     }
213 
214     /***
215      * Get the name of the Table.
216      *
217      * @return A String with the name of the table.
218      */
219     public String getName()
220     {
221         return tableName;
222     }
223 
224     /***
225      * Get table prefix name.
226      *
227      * @return A String with the prefix.
228      */
229     public String getPrefix()
230     {
231         return this.prefix;
232     }
233 
234     /***
235      * Set table prefix name.
236      *
237      * @param prefix The prefix for the table name (ie: SCARAB for
238      * SCARAB_PROJECT).
239      */
240     public void setPrefix(String prefix)
241     {
242         this.prefix = prefix;
243     }
244 
245     /***
246      * Get the method used to generate primary keys for this table.
247      *
248      * @return A String with the method.
249      */
250     public String getPrimaryKeyMethod()
251     {
252         return primaryKeyMethod;
253     }
254 
255     /***
256      * Get the value of idGenerator.
257      * @return value of idGenerator.
258      */
259     public IdGenerator getIdGenerator()
260     {
261         return getDatabaseMap().getIdGenerator(primaryKeyMethod);
262     }
263 
264     /***
265      * Get the information used to generate a primary key
266      *
267      * @return An Object.
268      */
269     public Object getPrimaryKeyMethodInfo()
270     {
271         return pkInfo;
272     }
273 
274     /***
275      * Get a ColumnMap[] of the columns in this table.
276      *
277      * @return A ColumnMap[].
278      */
279     public ColumnMap[] getColumns()
280     {
281         ColumnMap[] tableColumns = new ColumnMap[columns.size()];
282         Iterator it = columns.values().iterator();
283         int i = 0;
284         while (it.hasNext())
285         {
286             tableColumns[i++] = (ColumnMap) it.next();
287         }
288         return tableColumns;
289     }
290 
291     /***
292      * Get a ColumnMap for the named table.
293      *
294      * @param name A String with the name of the table.
295      * @return A ColumnMap.
296      */
297     public ColumnMap getColumn(String name)
298     {
299         try
300         {
301             return (ColumnMap) columns.get(name);
302         }
303         catch (Exception e)
304         {
305             return null;
306         }
307     }
308 
309     /***
310      * Add a pre-created column to this table.  It will replace any
311      * existing column.
312      *
313      * @param cmap A ColumnMap.
314      */
315     public void addColumn (ColumnMap cmap)
316     {
317         columns.put (cmap.getColumnName(), cmap);
318     }
319 
320     /***
321      * Add a column to this table of a certain type.
322      *
323      * @param columnName A String with the column name.
324      * @param type An Object specifying the type.
325      */
326     public void addColumn(String columnName, Object type)
327     {
328         addColumn(columnName, type, false, null, null, 0);
329     }
330 
331     /***
332      * Add a column to this table of a certain type and size.
333      *
334      * @param columnName A String with the column name.
335      * @param type An Object specifying the type.
336      * @param size An int specifying the size.
337      */
338     public void addColumn(String columnName, Object type, int size)
339     {
340         addColumn(columnName, type, false, null, null, size);
341     }
342 
343     /***
344      * Add a primary key column to this Table.
345      *
346      * @param columnName A String with the column name.
347      * @param type An Object specifying the type.
348      */
349     public void addPrimaryKey(String columnName, Object type)
350     {
351         addColumn(columnName, type, true, null, null, 0);
352     }
353 
354     /***
355      * Add a primary key column to this Table.
356      *
357      * @param columnName A String with the column name.
358      * @param type An Object specifying the type.
359      * @param size An int specifying the size.
360      */
361     public void addPrimaryKey(String columnName, Object type, int size)
362     {
363         addColumn(columnName, type, true, null, null, size);
364     }
365 
366     /***
367      * Add a foreign key column to the table.
368      *
369      * @param columnName A String with the column name.
370      * @param type An Object specifying the type.
371      * @param fkTable A String with the foreign key table name.
372      * @param fkColumn A String with the foreign key column name.
373      */
374     public void addForeignKey(String columnName,
375                               Object type,
376                               String fkTable,
377                               String fkColumn)
378     {
379         addColumn(columnName, type, false, fkTable, fkColumn, 0);
380     }
381 
382     /***
383      * Add a foreign key column to the table.
384      *
385      * @param columnName A String with the column name.
386      * @param type An Object specifying the type.
387      * @param fkTable A String with the foreign key table name.
388      * @param fkColumn A String with the foreign key column name.
389      * @param size An int specifying the size.
390      */
391     public void addForeignKey(String columnName,
392                               Object type,
393                               String fkTable,
394                               String fkColumn,
395                               int size)
396     {
397         addColumn(columnName, type, false, fkTable, fkColumn, size);
398     }
399 
400     /***
401      * Add a foreign primary key column to the table.
402      *
403      * @param columnName A String with the column name.
404      * @param type An Object specifying the type.
405      * @param fkTable A String with the foreign key table name.
406      * @param fkColumn A String with the foreign key column name.
407      */
408     public void addForeignPrimaryKey(String columnName,
409                                      Object type,
410                                      String fkTable,
411                                      String fkColumn)
412     {
413         addColumn(columnName, type, true, fkTable, fkColumn, 0);
414     }
415 
416     /***
417      * Add a foreign primary key column to the table.
418      *
419      * @param columnName A String with the column name.
420      * @param type An Object specifying the type.
421      * @param fkTable A String with the foreign key table name.
422      * @param fkColumn A String with the foreign key column name.
423      * @param size An int specifying the size.
424      */
425     public void addForeignPrimaryKey(String columnName,
426                                      Object type,
427                                      String fkTable,
428                                      String fkColumn,
429                                      int size)
430     {
431         addColumn(columnName, type, true, fkTable, fkColumn, size);
432     }
433 
434     /***
435      * Add a column to the table.
436      *
437      * @param name A String with the column name.
438      * @param type An Object specifying the type.
439      * @param pk True if column is a primary key.
440      * @param fkTable A String with the foreign key table name.
441      * @param fkColumn A String with the foreign key column name.
442      * @param size An int specifying the size.
443      */
444     private void addColumn(String name,
445                            Object type,
446                            boolean pk,
447                            String fkTable,
448                            String fkColumn,
449                            int size)
450     {
451         // If the tablename is prefixed with the name of the column,
452         // remove it ie: SCARAB_PROJECT.PROJECT_ID remove the
453         // SCARAB_PROJECT.
454         if (name.indexOf('.') > 0 && name.indexOf(getName()) != -1)
455         {
456             name = name.substring(getName().length() + 1);
457         }
458         if (fkTable != null && fkTable.length() > 0 && fkColumn != null
459                 && fkColumn.length() > 0)
460         {
461             if (fkColumn.indexOf('.') > 0 && fkColumn.indexOf(fkTable) != -1)
462             {
463                 fkColumn = fkColumn.substring(fkTable.length() + 1);
464             }
465         }
466         ColumnMap col = new ColumnMap(name, this);
467         col.setType(type);
468         col.setPrimaryKey(pk);
469         col.setForeignKey(fkTable, fkColumn);
470         col.setSize(size);
471         columns.put(name, col);
472     }
473 
474     /***
475      * Sets the method used to generate a key for this table.  Valid
476      * values are as specified in the {@link
477      * org.apache.torque.adapter.IDMethod} interface.
478      *
479      * @param method The ID generation method type name.
480      */
481     public void setPrimaryKeyMethod(String method)
482     {
483         primaryKeyMethod = NO_ID_METHOD;
484 
485         // Validate ID generation method.
486         for (int i = 0; i < VALID_ID_METHODS.length; i++)
487         {
488             if (VALID_ID_METHODS[i].equalsIgnoreCase(method))
489             {
490                 primaryKeyMethod = method;
491                 break;
492             }
493         }
494     }
495 
496     /***
497      * Sets the pk information needed to generate a key
498      *
499      * @param pkInfo information needed to generate a key
500      */
501     public void setPrimaryKeyMethodInfo(Object pkInfo)
502     {
503         this.pkInfo = pkInfo;
504     }
505 
506     //---Utility methods for doing intelligent lookup of table names
507 
508     /***
509      * Tell me if i have PREFIX in my string.
510      *
511      * @param data A String.
512      * @return True if prefix is contained in data.
513      */
514     private final boolean hasPrefix(String data)
515     {
516         return (data.indexOf(getPrefix()) != -1);
517     }
518 
519     /***
520      * Removes the PREFIX.
521      *
522      * @param data A String.
523      * @return A String with data, but with prefix removed.
524      */
525     private final String removePrefix(String data)
526     {
527         return data.substring(getPrefix().length());
528     }
529 
530     /***
531      * Removes the PREFIX, removes the underscores and makes
532      * first letter caps.
533      *
534      * SCARAB_FOO_BAR becomes FooBar.
535      *
536      * @param data A String.
537      * @return A String with data processed.
538      */
539     public final String removeUnderScores(String data)
540     {
541         String tmp = null;
542         StringBuffer out = new StringBuffer();
543         if (hasPrefix(data))
544         {
545             tmp = removePrefix(data);
546         }
547         else
548         {
549             tmp = data;
550         }
551 
552         StringTokenizer st = new StringTokenizer(tmp, "_");
553         while (st.hasMoreTokens())
554         {
555             String element = ((String) st.nextElement()).toLowerCase();
556             out.append (StringUtils.capitalise(element));
557         }
558         return out.toString();
559     }
560 }