001: package org.apache.torque.map;
002:
003: /*
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021:
022: import java.util.Collections;
023: import java.util.Iterator;
024: import java.util.Map;
025: import java.util.StringTokenizer;
026:
027: import org.apache.commons.collections.map.ListOrderedMap;
028: import org.apache.commons.lang.StringUtils;
029: import org.apache.torque.adapter.IDMethod;
030: import org.apache.torque.oid.IdGenerator;
031:
032: /**
033: * TableMap is used to model a table in a database.
034: *
035: * @author <a href="mailto:jmcnally@collab.net">John D. McNally</a>
036: * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
037: * @author <a href="mailto:greg.monroe@dukece.com">Greg Monroe</a>
038: * @version $Id: TableMap.java 473821 2006-11-11 22:37:25Z tv $
039: */
040: public class TableMap implements IDMethod, java.io.Serializable {
041: /** The serialVersionUID for this class. */
042: private static final long serialVersionUID = -9053174532511492818L;
043:
044: /** The list of valid ID generation methods. */
045: protected static final String[] VALID_ID_METHODS = { NATIVE,
046: AUTO_INCREMENT, SEQUENCE, ID_BROKER, NO_ID_METHOD };
047:
048: /** The columns in the table. XML Order is preserved. */
049: private Map columns;
050:
051: /** The database this table belongs to. */
052: private DatabaseMap dbMap;
053:
054: /** The name of the table. */
055: private String tableName;
056:
057: /** The JavaName of the table as defined in XML */
058: private String javaName;
059:
060: /** The prefix on the table name. */
061: private String prefix;
062:
063: /** The primary key generation method. */
064: private String primaryKeyMethod = NO_ID_METHOD;
065:
066: /** The table description info. */
067: private String description = "";
068:
069: /** The Peer Class for this table. */
070: private Class peerClass;
071:
072: /** The OM Root Class for this table. */
073: private Class omClass;
074:
075: /** Whether any column uses Inheritance. */
076: private boolean useInheritance = false;
077:
078: /** Whether cache managers are used. */
079: private boolean useManager = false;
080:
081: /** The associated cache manager class. */
082: private Class managerClass;
083:
084: /**
085: * Object to store information that is needed if the
086: * for generating primary keys.
087: */
088: private Object pkInfo = null;
089:
090: /**
091: * Required by proxy. Not used.
092: */
093: public TableMap() {
094: }
095:
096: /**
097: * Constructor.
098: *
099: * @param tableName The name of the table.
100: * @param numberOfColumns The number of columns in the table.
101: * @param containingDB A DatabaseMap that this table belongs to.
102: */
103: public TableMap(String tableName, int numberOfColumns,
104: DatabaseMap containingDB) {
105: this .tableName = tableName;
106: dbMap = containingDB;
107: columns = Collections.synchronizedMap(new ListOrderedMap());
108: }
109:
110: /**
111: * Constructor.
112: *
113: * @param tableName The name of the table.
114: * @param containingDB A DatabaseMap that this table belongs to.
115: */
116: public TableMap(String tableName, DatabaseMap containingDB) {
117: this .tableName = tableName;
118: dbMap = containingDB;
119: columns = Collections.synchronizedMap(new ListOrderedMap());
120: }
121:
122: /**
123: * Constructor.
124: *
125: * @param tableName The name of the table.
126: * @param prefix The prefix for the table name (ie: SCARAB for
127: * SCARAB_PROJECT).
128: * @param containingDB A DatabaseMap that this table belongs to.
129: */
130: public TableMap(String tableName, String prefix,
131: DatabaseMap containingDB) {
132: this .tableName = tableName;
133: this .prefix = prefix;
134: dbMap = containingDB;
135: columns = Collections.synchronizedMap(new ListOrderedMap());
136: }
137:
138: /**
139: * Does this table contain the specified column?
140: *
141: * @param column A ColumnMap.
142: * @return True if the table contains the column.
143: */
144: public boolean containsColumn(ColumnMap column) {
145: return containsColumn(column.getColumnName());
146: }
147:
148: /**
149: * Does this table contain the specified column?
150: *
151: * @param name A String with the name of the column.
152: * @return True if the table contains the column.
153: */
154: public boolean containsColumn(String name) {
155: if (name.indexOf('.') > 0) {
156: name = name.substring(name.indexOf('.') + 1);
157: }
158: return columns.containsKey(name);
159: }
160:
161: /**
162: * Get the DatabaseMap containing this TableMap.
163: *
164: * @return A DatabaseMap.
165: */
166: public DatabaseMap getDatabaseMap() {
167: return dbMap;
168: }
169:
170: /**
171: * Returns true if this tableMap contains a column with object
172: * data. If the type of the column is not a string, a number or a
173: * date, it is assumed that it is object data.
174: *
175: * @return True if map contains a column with object data.
176: */
177: public boolean containsObjectColumn() {
178: synchronized (columns) {
179: Iterator it = columns.values().iterator();
180: while (it.hasNext()) {
181: Object theType = ((ColumnMap) it.next()).getType();
182: if (!(theType instanceof String
183: || theType instanceof Number || theType instanceof java.util.Date)) {
184: return true;
185: }
186: }
187: }
188: return false;
189: }
190:
191: /**
192: * Get the name of the Table.
193: *
194: * @return A String with the name of the table.
195: */
196: public String getName() {
197: return tableName;
198: }
199:
200: /**
201: * Get the Java name of the table as defined in XML.
202: *
203: * @return A String with the Java name of the table.
204: */
205: public String getJavaName() {
206: return javaName;
207: }
208:
209: /**
210: * Set the Java name of the table as defined by generator/XML.
211: *
212: * @param value A String with the Java name of the table.
213: */
214: public void setJavaName(String value) {
215: this .javaName = value;
216: }
217:
218: /**
219: * Get table prefix name.
220: *
221: * @return A String with the prefix.
222: */
223: public String getPrefix() {
224: return this .prefix;
225: }
226:
227: /**
228: * Set table prefix name.
229: *
230: * @param prefix The prefix for the table name (ie: SCARAB for
231: * SCARAB_PROJECT).
232: */
233: public void setPrefix(String prefix) {
234: this .prefix = prefix;
235: }
236:
237: /**
238: * Get the method used to generate primary keys for this table.
239: *
240: * @return A String with the method.
241: */
242: public String getPrimaryKeyMethod() {
243: return primaryKeyMethod;
244: }
245:
246: /**
247: * Get the value of idGenerator.
248: * @return value of idGenerator.
249: * @deprecated use DatabaseInfo.getIdGenerator(getPrimaryKeyMethod())
250: * instead. Will be removed in a future version of Torque.
251: */
252: public IdGenerator getIdGenerator() {
253: return getDatabaseMap().getIdGenerator(primaryKeyMethod);
254: }
255:
256: /**
257: * Get the information used to generate a primary key
258: *
259: * @return An Object.
260: */
261: public Object getPrimaryKeyMethodInfo() {
262: return pkInfo;
263: }
264:
265: /**
266: * Get a ColumnMap[] of the columns in this table.
267: *
268: * @return A ColumnMap[].
269: */
270: public ColumnMap[] getColumns() {
271: ColumnMap[] tableColumns = new ColumnMap[columns.size()];
272: synchronized (columns) {
273: Iterator it = columns.values().iterator();
274: int i = 0;
275: while (it.hasNext()) {
276: tableColumns[i++] = (ColumnMap) it.next();
277: }
278: }
279: return tableColumns;
280: }
281:
282: /**
283: * Get a ColumnMap for the named table.
284: *
285: * @param name A String with the name of the table.
286: * @return A ColumnMap.
287: */
288: public ColumnMap getColumn(String name) {
289: try {
290: return (ColumnMap) columns.get(name);
291: } catch (Exception e) {
292: return null;
293: }
294: }
295:
296: /**
297: * Add a pre-created column to this table. It will replace any
298: * existing column.
299: *
300: * @param cmap A ColumnMap.
301: */
302: public void addColumn(ColumnMap cmap) {
303: columns.put(cmap.getColumnName(), cmap);
304: }
305:
306: /**
307: * Add a column to this table of a certain type.
308: *
309: * @param columnName A String with the column name.
310: * @param type An Object specifying the type.
311: * @deprecated Associated Column maps should be populated using it's
312: * set methods, then added to table via addColumn(ColumnMap).
313: * This method will be removed in a future version of Torque.
314: */
315: public void addColumn(String columnName, Object type) {
316: addColumn(columnName, type, false, null, null, 0);
317: }
318:
319: /**
320: * Add a column to this table of a certain type, size, and scale.
321: *
322: * @param columnName A String with the column name.
323: * @param type An Object specifying the type.
324: * @param size An int specifying the size.
325: * @param scale An int specifying the scale.
326: * @deprecated Associated Column maps should be populated using it's set
327: * methods, then added to table via addColumn(ColumnMap).
328: * This method will be removed in a future version of Torque.
329: */
330: public void addColumn(String columnName, Object type, int size,
331: int scale) {
332: addColumn(columnName, type, false, null, null, size, scale);
333: }
334:
335: /**
336: * Add a column to this table of a certain type and size.
337: *
338: * @param columnName A String with the column name.
339: * @param type An Object specifying the type.
340: * @param size An int specifying the size.
341: * @deprecated Associated Column maps should be populated using it's set
342: * methods, then added to table via addColumn(ColumnMap).
343: * This method will be removed in a future version of Torque.
344: */
345: public void addColumn(String columnName, Object type, int size) {
346: addColumn(columnName, type, false, null, null, size);
347: }
348:
349: /**
350: * Add a primary key column to this Table.
351: *
352: * @param columnName A String with the column name.
353: * @param type An Object specifying the type.
354: * @deprecated Associated Column maps should be populated using it's set
355: * methods, then added to table via addColumn(ColumnMap).
356: * This method will be removed in a future version of Torque.
357: */
358: public void addPrimaryKey(String columnName, Object type) {
359: addColumn(columnName, type, true, null, null, 0);
360: }
361:
362: /**
363: * Add a primary key column to this Table.
364: *
365: * @param columnName A String with the column name.
366: * @param type An Object specifying the type.
367: * @param size An int specifying the size.
368: * @deprecated Associated Column maps should be populated using it's set
369: * methods, then added to table via addColumn(ColumnMap).
370: * This method will be removed in a future version of Torque.
371: */
372: public void addPrimaryKey(String columnName, Object type, int size) {
373: addColumn(columnName, type, true, null, null, size);
374: }
375:
376: /**
377: * Add a foreign key column to the table.
378: *
379: * @param columnName A String with the column name.
380: * @param type An Object specifying the type.
381: * @param fkTable A String with the foreign key table name.
382: * @param fkColumn A String with the foreign key column name.
383: * @deprecated Associated Column maps should be populated using it's set
384: * methods, then added to table via addColumn(ColumnMap).
385: * This method will be removed in a future version of Torque.
386: */
387: public void addForeignKey(String columnName, Object type,
388: String fkTable, String fkColumn) {
389: addColumn(columnName, type, false, fkTable, fkColumn, 0);
390: }
391:
392: /**
393: * Add a foreign key column to the table.
394: *
395: * @param columnName A String with the column name.
396: * @param type An Object specifying the type.
397: * @param fkTable A String with the foreign key table name.
398: * @param fkColumn A String with the foreign key column name.
399: * @param size An int specifying the size.
400: * @deprecated Associated Column maps should be populated using it's set
401: * methods, then added to table via addColumn(ColumnMap).
402: * This method will be removed in a future version of Torque.
403: */
404: public void addForeignKey(String columnName, Object type,
405: String fkTable, String fkColumn, int size) {
406: addColumn(columnName, type, false, fkTable, fkColumn, size);
407: }
408:
409: /**
410: * Add a foreign primary key column to the table.
411: *
412: * @param columnName A String with the column name.
413: * @param type An Object specifying the type.
414: * @param fkTable A String with the foreign key table name.
415: * @param fkColumn A String with the foreign key column name.
416: * @deprecated Associated Column maps should be populated using it's set
417: * methods, then added to table via addColumn(ColumnMap).
418: * This method will be removed in a future version of Torque.
419: */
420: public void addForeignPrimaryKey(String columnName, Object type,
421: String fkTable, String fkColumn) {
422: addColumn(columnName, type, true, fkTable, fkColumn, 0);
423: }
424:
425: /**
426: * Add a foreign primary key column to the table.
427: *
428: * @param columnName A String with the column name.
429: * @param type An Object specifying the type.
430: * @param fkTable A String with the foreign key table name.
431: * @param fkColumn A String with the foreign key column name.
432: * @param size An int specifying the size.
433: * @deprecated Associated Column maps should be populated using it's set
434: * methods, then added to table via addColumn(ColumnMap).
435: * This method will be removed in a future version of Torque.
436: */
437: public void addForeignPrimaryKey(String columnName, Object type,
438: String fkTable, String fkColumn, int size) {
439: addColumn(columnName, type, true, fkTable, fkColumn, size);
440: }
441:
442: /**
443: * Add a column to the table.
444: *
445: * @param name A String with the column name.
446: * @param type An Object specifying the type.
447: * @param pk True if column is a primary key.
448: * @param fkTable A String with the foreign key table name.
449: * @param fkColumn A String with the foreign key column name.
450: * @param size An int specifying the size.
451: * @deprecated Associated Column maps should be populated using it's set
452: * methods, then added to table via addColumn(ColumnMap).
453: * This method will be removed in a future version of Torque.
454: */
455: private void addColumn(String name, Object type, boolean pk,
456: String fkTable, String fkColumn, int size) {
457: addColumn(name, type, pk, fkTable, fkColumn, size, 0);
458: }
459:
460: /**
461: * Add a column to the table.
462: *
463: * @param name A String with the column name.
464: * @param type An Object specifying the type.
465: * @param pk True if column is a primary key.
466: * @param fkTable A String with the foreign key table name.
467: * @param fkColumn A String with the foreign key column name.
468: * @param size An int specifying the size.
469: * @param scale An int specifying the scale.
470: * @deprecated Associated Column maps should be populated using it's set
471: * methods, then added to table via addColumn(ColumnMap).
472: * This method will be removed in a future version of Torque.
473: */
474: private void addColumn(String name, Object type, boolean pk,
475: String fkTable, String fkColumn, int size, int scale) {
476: // If the tablename is prefixed with the name of the column,
477: // remove it ie: SCARAB_PROJECT.PROJECT_ID remove the
478: // SCARAB_PROJECT.
479: if (name.indexOf('.') > 0 && name.indexOf(getName()) != -1) {
480: name = name.substring(getName().length() + 1);
481: }
482: if (fkTable != null && fkTable.length() > 0 && fkColumn != null
483: && fkColumn.length() > 0) {
484: if (fkColumn.indexOf('.') > 0
485: && fkColumn.indexOf(fkTable) != -1) {
486: fkColumn = fkColumn.substring(fkTable.length() + 1);
487: }
488: }
489: ColumnMap col = new ColumnMap(name, this );
490: col.setType(type);
491: col.setPrimaryKey(pk);
492: col.setForeignKey(fkTable, fkColumn);
493: col.setSize(size);
494: col.setScale(scale);
495: columns.put(name, col);
496: }
497:
498: /**
499: * Sets the method used to generate a key for this table. Valid
500: * values are as specified in the {@link
501: * org.apache.torque.adapter.IDMethod} interface.
502: *
503: * @param method The ID generation method type name.
504: */
505: public void setPrimaryKeyMethod(String method) {
506: primaryKeyMethod = NO_ID_METHOD;
507:
508: // Validate ID generation method.
509: for (int i = 0; i < VALID_ID_METHODS.length; i++) {
510: if (VALID_ID_METHODS[i].equalsIgnoreCase(method)) {
511: primaryKeyMethod = method;
512: break;
513: }
514: }
515: if (ID_BROKER.equalsIgnoreCase(method)) {
516: getDatabaseMap().startIdBroker();
517: }
518: }
519:
520: /**
521: * Sets the pk information needed to generate a key
522: *
523: * @param pkInfo information needed to generate a key
524: */
525: public void setPrimaryKeyMethodInfo(Object pkInfo) {
526: this .pkInfo = pkInfo;
527: }
528:
529: //---Utility methods for doing intelligent lookup of table names
530:
531: /**
532: * Tell me if i have PREFIX in my string.
533: *
534: * @param data A String.
535: * @return True if prefix is contained in data.
536: */
537: private boolean hasPrefix(String data) {
538: return (data.indexOf(getPrefix()) != -1);
539: }
540:
541: /**
542: * Removes the PREFIX.
543: *
544: * @param data A String.
545: * @return A String with data, but with prefix removed.
546: */
547: private String removePrefix(String data) {
548: return data.substring(getPrefix().length());
549: }
550:
551: /**
552: * Removes the PREFIX, removes the underscores and makes
553: * first letter caps.
554: *
555: * SCARAB_FOO_BAR becomes FooBar.
556: *
557: * @param data A String.
558: * @return A String with data processed.
559: */
560: public final String removeUnderScores(String data) {
561: String tmp = null;
562: StringBuffer out = new StringBuffer();
563: if (hasPrefix(data)) {
564: tmp = removePrefix(data);
565: } else {
566: tmp = data;
567: }
568:
569: StringTokenizer st = new StringTokenizer(tmp, "_");
570: while (st.hasMoreTokens()) {
571: String element = ((String) st.nextElement()).toLowerCase();
572: out.append(StringUtils.capitalize(element));
573: }
574: return out.toString();
575: }
576:
577: /**
578: * Returns the table description info.
579: *
580: * @return Returns the description.
581: */
582: public String getDescription() {
583: return description;
584: }
585:
586: /**
587: * Sets the table description.
588: *
589: * @param description The description to set.
590: */
591: public void setDescription(String description) {
592: this .description = description;
593: }
594:
595: /**
596: * Returns the OM class for this table.
597: *
598: * @return the OM class.
599: */
600: public Class getOMClass() {
601: return omClass;
602: }
603:
604: /**
605: * Sets the OM root class for this table.
606: *
607: * @param omClass The OM root class for this table.
608: */
609: public void setOMClass(Class omClass) {
610: this .omClass = omClass;
611: }
612:
613: /**
614: * Returns the Peer Class for this table.
615: *
616: * @return The peerClass for this table.
617: */
618: public Class getPeerClass() {
619: return peerClass;
620: }
621:
622: /**
623: * Sets the Peer class for this table.
624: *
625: * @param peerClass The peerClass to set.
626: */
627: public void setPeerClass(Class peerClass) {
628: this .peerClass = peerClass;
629: }
630:
631: /**
632: * Returns the database map for this table.
633: *
634: * @return the database map for this table.
635: */
636: public DatabaseMap getDbMap() {
637: return dbMap;
638: }
639:
640: /**
641: * Returns whether this table uses inheritance.
642: *
643: * @return whether inheritance is used.
644: */
645: public boolean isUseInheritance() {
646: return useInheritance;
647: }
648:
649: /**
650: * Sets whether this table uses inheritance.
651: *
652: * @param useInheritance whether this table uses inheritance.
653: */
654: public void setUseInheritance(boolean useInheritance) {
655: this .useInheritance = useInheritance;
656: }
657:
658: /**
659: * Returns whether managers are used for this table.
660: *
661: * @return whether managers are used for this table.
662: */
663: public boolean isUseManager() {
664: return useManager;
665: }
666:
667: /**
668: * Sets whether managers are used for this table.
669: *
670: * @param useManager whether managers are used for this table.
671: */
672: public void setUseManager(boolean useManager) {
673: this .useManager = useManager;
674: }
675:
676: /**
677: * Returns the manager class for this table.
678: *
679: * @return the managerClass.
680: */
681: public Class getManagerClass() {
682: return managerClass;
683: }
684:
685: /**
686: * Sets the manager class for this table.
687: *
688: * @param managerClass the manager class for this table.
689: */
690: public void setManagerClass(Class managerClass) {
691: this.managerClass = managerClass;
692: }
693: }
|