View Javadoc

1   package org.apache.torque.map;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.Collections;
23  import java.util.Iterator;
24  import java.util.Map;
25  import java.util.StringTokenizer;
26  
27  import org.apache.commons.collections.map.ListOrderedMap;
28  import org.apache.commons.lang.StringUtils;
29  import org.apache.torque.adapter.IDMethod;
30  import org.apache.torque.oid.IdGenerator;
31  
32  /***
33   * TableMap is used to model a table in a database.
34   *
35   * @author <a href="mailto:jmcnally@collab.net">John D. McNally</a>
36   * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
37   * @author <a href="mailto:greg.monroe@dukece.com">Greg Monroe</a>
38   * @version $Id: TableMap.java 473821 2006-11-11 22:37:25Z tv $
39   */
40  public class TableMap implements IDMethod, java.io.Serializable
41  {
42      /*** The serialVersionUID for this class. */
43      private static final long serialVersionUID = -9053174532511492818L;
44  
45      /*** The list of valid ID generation methods. */
46      protected static final String[] VALID_ID_METHODS =
47      {
48          NATIVE, AUTO_INCREMENT, SEQUENCE, ID_BROKER, NO_ID_METHOD
49      };
50  
51      /*** The columns in the table. XML Order is preserved. */
52      private Map columns;
53  
54      /*** The database this table belongs to. */
55      private DatabaseMap dbMap;
56  
57      /*** The name of the table. */
58      private String tableName;
59  
60      /*** The JavaName of the table as defined in XML */
61      private String javaName;
62  
63      /*** The prefix on the table name. */
64      private String prefix;
65  
66      /*** The primary key generation method. */
67      private String primaryKeyMethod = NO_ID_METHOD;
68  
69      /*** The table description info. */
70      private String description = "";
71  
72      /*** The Peer Class for this table. */
73      private Class peerClass;
74  
75      /*** The OM Root Class for this table. */
76      private Class omClass;
77  
78      /*** Whether any column uses Inheritance. */
79      private boolean useInheritance = false;
80  
81      /*** Whether cache managers are used. */
82      private boolean useManager = false;
83  
84      /*** The associated cache manager class. */
85      private Class managerClass;
86  
87      /***
88       * Object to store information that is needed if the
89       * for generating primary keys.
90       */
91      private Object pkInfo = null;
92  
93      /***
94       * Required by proxy. Not used.
95       */
96      public TableMap()
97      {
98      }
99  
100     /***
101      * Constructor.
102      *
103      * @param tableName The name of the table.
104      * @param numberOfColumns The number of columns in the table.
105      * @param containingDB A DatabaseMap that this table belongs to.
106      */
107     public TableMap(String tableName,
108                     int numberOfColumns,
109                     DatabaseMap containingDB)
110     {
111         this.tableName = tableName;
112         dbMap = containingDB;
113         columns = Collections.synchronizedMap(new ListOrderedMap());
114     }
115 
116     /***
117      * Constructor.
118      *
119      * @param tableName The name of the table.
120      * @param containingDB A DatabaseMap that this table belongs to.
121      */
122     public TableMap(String tableName, DatabaseMap containingDB)
123     {
124         this.tableName = tableName;
125         dbMap = containingDB;
126         columns = Collections.synchronizedMap(new ListOrderedMap());
127     }
128 
129     /***
130      * Constructor.
131      *
132      * @param tableName The name of the table.
133      * @param prefix The prefix for the table name (ie: SCARAB for
134      * SCARAB_PROJECT).
135      * @param containingDB A DatabaseMap that this table belongs to.
136      */
137     public TableMap(String tableName,
138                     String prefix,
139                     DatabaseMap containingDB)
140     {
141         this.tableName = tableName;
142         this.prefix = prefix;
143         dbMap = containingDB;
144         columns = Collections.synchronizedMap(new ListOrderedMap());
145     }
146 
147     /***
148      * Does this table contain the specified column?
149      *
150      * @param column A ColumnMap.
151      * @return True if the table contains the column.
152      */
153     public boolean containsColumn(ColumnMap column)
154     {
155         return containsColumn(column.getColumnName());
156     }
157 
158     /***
159      * Does this table contain the specified column?
160      *
161      * @param name A String with the name of the column.
162      * @return True if the table contains the column.
163      */
164     public boolean containsColumn(String name)
165     {
166         if (name.indexOf('.') > 0)
167         {
168             name = name.substring(name.indexOf('.') + 1);
169         }
170         return columns.containsKey(name);
171     }
172 
173     /***
174      * Get the DatabaseMap containing this TableMap.
175      *
176      * @return A DatabaseMap.
177      */
178     public DatabaseMap getDatabaseMap()
179     {
180         return dbMap;
181     }
182 
183     /***
184      * Returns true if this tableMap contains a column with object
185      * data.  If the type of the column is not a string, a number or a
186      * date, it is assumed that it is object data.
187      *
188      * @return True if map contains a column with object data.
189      */
190     public boolean containsObjectColumn()
191     {
192         synchronized (columns)
193         {
194             Iterator it = columns.values().iterator();
195             while (it.hasNext())
196             {
197                 Object theType = ((ColumnMap) it.next()).getType();
198             if (!(theType instanceof String || theType instanceof Number
199                     || theType instanceof java.util.Date))
200                 {
201                     return true;
202                 }
203             }
204         }
205         return false;
206     }
207 
208     /***
209      * Get the name of the Table.
210      *
211      * @return A String with the name of the table.
212      */
213     public String getName()
214     {
215         return tableName;
216     }
217 
218     /***
219      * Get the Java name of the table as defined in XML.
220      *
221      * @return A String with the Java name of the table.
222      */
223     public String getJavaName()
224     {
225         return javaName;
226     }
227 
228     /***
229      * Set the Java name of the table as defined by generator/XML.
230      *
231      * @param value A String with the Java name of the table.
232      */
233     public void setJavaName(String value)
234     {
235         this.javaName = value;
236     }
237 
238     /***
239      * Get table prefix name.
240      *
241      * @return A String with the prefix.
242      */
243     public String getPrefix()
244     {
245         return this.prefix;
246     }
247 
248     /***
249      * Set table prefix name.
250      *
251      * @param prefix The prefix for the table name (ie: SCARAB for
252      * SCARAB_PROJECT).
253      */
254     public void setPrefix(String prefix)
255     {
256         this.prefix = prefix;
257     }
258 
259     /***
260      * Get the method used to generate primary keys for this table.
261      *
262      * @return A String with the method.
263      */
264     public String getPrimaryKeyMethod()
265     {
266         return primaryKeyMethod;
267     }
268 
269     /***
270      * Get the value of idGenerator.
271      * @return value of idGenerator.
272      * @deprecated use DatabaseInfo.getIdGenerator(getPrimaryKeyMethod())
273      *             instead. Will be removed in a future version of Torque.
274      */
275     public IdGenerator getIdGenerator()
276     {
277         return getDatabaseMap().getIdGenerator(primaryKeyMethod);
278     }
279 
280     /***
281      * Get the information used to generate a primary key
282      *
283      * @return An Object.
284      */
285     public Object getPrimaryKeyMethodInfo()
286     {
287         return pkInfo;
288     }
289 
290     /***
291      * Get a ColumnMap[] of the columns in this table.
292      *
293      * @return A ColumnMap[].
294      */
295     public ColumnMap[] getColumns()
296     {
297         ColumnMap[] tableColumns = new ColumnMap[columns.size()];
298         synchronized (columns)
299         {
300             Iterator it = columns.values().iterator();
301             int i = 0;
302             while (it.hasNext())
303             {
304                 tableColumns[i++] = (ColumnMap) it.next();
305             }
306         }
307         return tableColumns;
308     }
309 
310     /***
311      * Get a ColumnMap for the named table.
312      *
313      * @param name A String with the name of the table.
314      * @return A ColumnMap.
315      */
316     public ColumnMap getColumn(String name)
317     {
318         try
319         {
320             return (ColumnMap) columns.get(name);
321         }
322         catch (Exception e)
323         {
324             return null;
325         }
326     }
327 
328     /***
329      * Add a pre-created column to this table.  It will replace any
330      * existing column.
331      *
332      * @param cmap A ColumnMap.
333      */
334     public void addColumn(ColumnMap cmap)
335     {
336         columns.put(cmap.getColumnName(), cmap);
337     }
338 
339     /***
340      * Add a column to this table of a certain type.
341      *
342      * @param columnName A String with the column name.
343      * @param type An Object specifying the type.
344      * @deprecated Associated Column maps should be populated using it's
345      *             set methods, then added to table via addColumn(ColumnMap).
346      *             This method will be removed in a future version of Torque.
347      */
348     public void addColumn(String columnName, Object type)
349     {
350         addColumn(columnName, type, false, null, null, 0);
351     }
352 
353     /***
354      * Add a column to this table of a certain type, size, and scale.
355      *
356      * @param columnName A String with the column name.
357      * @param type An Object specifying the type.
358      * @param size An int specifying the size.
359      * @param scale An int specifying the scale.
360      * @deprecated Associated Column maps should be populated using it's set
361      *             methods, then added to table via addColumn(ColumnMap).
362      *             This method will be removed in a future version of Torque.
363      */
364     public void addColumn(String columnName, Object type, int size, int scale)
365     {
366         addColumn(columnName, type, false, null, null, size, scale);
367     }
368 
369     /***
370      * Add a column to this table of a certain type and size.
371      *
372      * @param columnName A String with the column name.
373      * @param type An Object specifying the type.
374      * @param size An int specifying the size.
375      * @deprecated Associated Column maps should be populated using it's set
376      *             methods, then added to table via addColumn(ColumnMap).
377      *             This method will be removed in a future version of Torque.
378      */
379     public void addColumn(String columnName, Object type, int size)
380     {
381         addColumn(columnName, type, false, null, null, size);
382     }
383 
384     /***
385      * Add a primary key column to this Table.
386      *
387      * @param columnName A String with the column name.
388      * @param type An Object specifying the type.
389      * @deprecated Associated Column maps should be populated using it's set
390      *             methods, then added to table via addColumn(ColumnMap).
391      *             This method will be removed in a future version of Torque.
392      */
393     public void addPrimaryKey(String columnName, Object type)
394     {
395         addColumn(columnName, type, true, null, null, 0);
396     }
397 
398     /***
399      * Add a primary key column to this Table.
400      *
401      * @param columnName A String with the column name.
402      * @param type An Object specifying the type.
403      * @param size An int specifying the size.
404      * @deprecated Associated Column maps should be populated using it's set
405      *             methods, then added to table via addColumn(ColumnMap).
406      *             This method will be removed in a future version of Torque.
407      */
408     public void addPrimaryKey(String columnName, Object type, int size)
409     {
410         addColumn(columnName, type, true, null, null, size);
411     }
412 
413     /***
414      * Add a foreign key column to the table.
415      *
416      * @param columnName A String with the column name.
417      * @param type An Object specifying the type.
418      * @param fkTable A String with the foreign key table name.
419      * @param fkColumn A String with the foreign key column name.
420      * @deprecated Associated Column maps should be populated using it's set
421      *             methods, then added to table via addColumn(ColumnMap).
422      *             This method will be removed in a future version of Torque.
423      */
424     public void addForeignKey(String columnName,
425                               Object type,
426                               String fkTable,
427                               String fkColumn)
428     {
429         addColumn(columnName, type, false, fkTable, fkColumn, 0);
430     }
431 
432     /***
433      * Add a foreign key column to the table.
434      *
435      * @param columnName A String with the column name.
436      * @param type An Object specifying the type.
437      * @param fkTable A String with the foreign key table name.
438      * @param fkColumn A String with the foreign key column name.
439      * @param size An int specifying the size.
440      * @deprecated Associated Column maps should be populated using it's set
441      *             methods, then added to table via addColumn(ColumnMap).
442      *             This method will be removed in a future version of Torque.
443      */
444     public void addForeignKey(String columnName,
445                               Object type,
446                               String fkTable,
447                                String fkColumn,
448                                int size)
449     {
450         addColumn(columnName, type, false, fkTable, fkColumn, size);
451     }
452 
453     /***
454      * Add a foreign primary key column to the table.
455      *
456      * @param columnName A String with the column name.
457      * @param type An Object specifying the type.
458      * @param fkTable A String with the foreign key table name.
459      * @param fkColumn A String with the foreign key column name.
460      * @deprecated Associated Column maps should be populated using it's set
461      *             methods, then added to table via addColumn(ColumnMap).
462      *             This method will be removed in a future version of Torque.
463      */
464     public void addForeignPrimaryKey(String columnName,
465                                      Object type,
466                                      String fkTable,
467                                      String fkColumn)
468     {
469         addColumn(columnName, type, true, fkTable, fkColumn, 0);
470     }
471 
472     /***
473      * Add a foreign primary key column to the table.
474      *
475      * @param columnName A String with the column name.
476      * @param type An Object specifying the type.
477      * @param fkTable A String with the foreign key table name.
478      * @param fkColumn A String with the foreign key column name.
479      * @param size An int specifying the size.
480      * @deprecated Associated Column maps should be populated using it's set
481      *             methods, then added to table via addColumn(ColumnMap).
482      *             This method will be removed in a future version of Torque.
483      */
484     public void addForeignPrimaryKey(String columnName,
485                                      Object type,
486                                      String fkTable,
487                                      String fkColumn,
488                                      int size)
489     {
490         addColumn(columnName, type, true, fkTable, fkColumn, size);
491     }
492 
493     /***
494      * Add a column to the table.
495      *
496      * @param name A String with the column name.
497      * @param type An Object specifying the type.
498      * @param pk True if column is a primary key.
499      * @param fkTable A String with the foreign key table name.
500      * @param fkColumn A String with the foreign key column name.
501      * @param size An int specifying the size.
502      * @deprecated Associated Column maps should be populated using it's set
503      *             methods, then added to table via addColumn(ColumnMap).
504      *             This method will be removed in a future version of Torque.
505      */
506     private void addColumn(String name,
507                            Object type,
508                            boolean pk,
509                            String fkTable,
510                            String fkColumn,
511                            int size)
512     {
513         addColumn(name, type, pk, fkTable, fkColumn, size, 0);
514     }
515 
516     /***
517      * Add a column to the table.
518      *
519      * @param name A String with the column name.
520      * @param type An Object specifying the type.
521      * @param pk True if column is a primary key.
522      * @param fkTable A String with the foreign key table name.
523      * @param fkColumn A String with the foreign key column name.
524      * @param size An int specifying the size.
525      * @param scale An int specifying the scale.
526      * @deprecated Associated Column maps should be populated using it's set
527      *             methods, then added to table via addColumn(ColumnMap).
528      *             This method will be removed in a future version of Torque.
529      */
530     private void addColumn(String name,
531                            Object type,
532                            boolean pk,
533                            String fkTable,
534                            String fkColumn,
535                            int size,
536                            int scale)
537     {
538         // If the tablename is prefixed with the name of the column,
539         // remove it ie: SCARAB_PROJECT.PROJECT_ID remove the
540         // SCARAB_PROJECT.
541         if (name.indexOf('.') > 0 && name.indexOf(getName()) != -1)
542         {
543             name = name.substring(getName().length() + 1);
544         }
545         if (fkTable != null && fkTable.length() > 0 && fkColumn != null
546                 && fkColumn.length() > 0)
547         {
548             if (fkColumn.indexOf('.') > 0 && fkColumn.indexOf(fkTable) != -1)
549             {
550                 fkColumn = fkColumn.substring(fkTable.length() + 1);
551             }
552         }
553         ColumnMap col = new ColumnMap(name, this);
554         col.setType(type);
555         col.setPrimaryKey(pk);
556         col.setForeignKey(fkTable, fkColumn);
557         col.setSize(size);
558         col.setScale(scale);
559         columns.put(name, col);
560     }
561 
562     /***
563      * Sets the method used to generate a key for this table.  Valid
564      * values are as specified in the {@link
565      * org.apache.torque.adapter.IDMethod} interface.
566      *
567      * @param method The ID generation method type name.
568      */
569     public void setPrimaryKeyMethod(String method)
570     {
571         primaryKeyMethod = NO_ID_METHOD;
572 
573         // Validate ID generation method.
574         for (int i = 0; i < VALID_ID_METHODS.length; i++)
575         {
576             if (VALID_ID_METHODS[i].equalsIgnoreCase(method))
577             {
578                 primaryKeyMethod = method;
579                 break;
580             }
581         }
582         if (ID_BROKER.equalsIgnoreCase(method))
583         {
584             getDatabaseMap().startIdBroker();
585         }
586     }
587 
588     /***
589      * Sets the pk information needed to generate a key
590      *
591      * @param pkInfo information needed to generate a key
592      */
593     public void setPrimaryKeyMethodInfo(Object pkInfo)
594     {
595         this.pkInfo = pkInfo;
596     }
597 
598     //---Utility methods for doing intelligent lookup of table names
599 
600     /***
601      * Tell me if i have PREFIX in my string.
602      *
603      * @param data A String.
604      * @return True if prefix is contained in data.
605      */
606     private boolean hasPrefix(String data)
607     {
608         return (data.indexOf(getPrefix()) != -1);
609     }
610 
611     /***
612      * Removes the PREFIX.
613      *
614      * @param data A String.
615      * @return A String with data, but with prefix removed.
616      */
617     private String removePrefix(String data)
618     {
619         return data.substring(getPrefix().length());
620     }
621 
622     /***
623      * Removes the PREFIX, removes the underscores and makes
624      * first letter caps.
625      *
626      * SCARAB_FOO_BAR becomes FooBar.
627      *
628      * @param data A String.
629      * @return A String with data processed.
630      */
631     public final String removeUnderScores(String data)
632     {
633         String tmp = null;
634         StringBuffer out = new StringBuffer();
635         if (hasPrefix(data))
636         {
637             tmp = removePrefix(data);
638         }
639         else
640         {
641             tmp = data;
642         }
643 
644         StringTokenizer st = new StringTokenizer(tmp, "_");
645         while (st.hasMoreTokens())
646         {
647             String element = ((String) st.nextElement()).toLowerCase();
648             out.append(StringUtils.capitalize(element));
649         }
650         return out.toString();
651     }
652 
653     /***
654      * Returns the table description info.
655      *
656      * @return Returns the description.
657      */
658     public String getDescription()
659     {
660         return description;
661     }
662 
663     /***
664      * Sets the table description.
665      *
666      * @param description The description to set.
667      */
668     public void setDescription(String description)
669     {
670         this.description = description;
671     }
672 
673     /***
674      * Returns the OM class for this table.
675      *
676      * @return the OM class.
677      */
678     public Class getOMClass()
679     {
680         return omClass;
681     }
682 
683     /***
684      * Sets the OM root class for this table.
685      *
686      * @param omClass The OM root class for this table.
687      */
688     public void setOMClass(Class omClass)
689     {
690         this.omClass = omClass;
691     }
692 
693     /***
694      * Returns the Peer Class for this table.
695      *
696      * @return The peerClass for this table.
697      */
698     public Class getPeerClass()
699     {
700         return peerClass;
701     }
702 
703     /***
704      * Sets the Peer class for this table.
705      *
706      * @param peerClass The peerClass to set.
707      */
708     public void setPeerClass(Class peerClass)
709     {
710         this.peerClass = peerClass;
711     }
712 
713     /***
714      * Returns the database map for this table.
715      *
716      * @return the database map for this table.
717      */
718     public DatabaseMap getDbMap()
719     {
720         return dbMap;
721     }
722 
723     /***
724      * Returns whether this table uses inheritance.
725      *
726      * @return whether inheritance is used.
727      */
728     public boolean isUseInheritance()
729     {
730         return useInheritance;
731     }
732 
733     /***
734      * Sets whether this table uses inheritance.
735      *
736      * @param useInheritance whether this table uses inheritance.
737      */
738     public void setUseInheritance(boolean useInheritance)
739     {
740         this.useInheritance = useInheritance;
741     }
742 
743     /***
744      * Returns whether managers are used for this table.
745      *
746      * @return whether managers are used for this table.
747      */
748     public boolean isUseManager()
749     {
750         return useManager;
751     }
752 
753     /***
754      * Sets whether managers are used for this table.
755      *
756      * @param useManager whether managers are used for this table.
757      */
758     public void setUseManager(boolean useManager)
759     {
760         this.useManager = useManager;
761     }
762 
763     /***
764      * Returns the manager class for this table.
765      *
766      * @return the managerClass.
767      */
768     public Class getManagerClass()
769     {
770         return managerClass;
771     }
772 
773     /***
774      * Sets the manager class for this table.
775      *
776      * @param managerClass the manager class for this table.
777      */
778     public void setManagerClass(Class managerClass)
779     {
780         this.managerClass = managerClass;
781     }
782 }