1 package org.apache.torque.engine.database.model;
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.ArrayList;
58 import java.util.Hashtable;
59 import java.util.Iterator;
60 import java.util.List;
61
62 import org.apache.commons.lang.StringUtils;
63
64 import org.apache.commons.logging.Log;
65 import org.apache.commons.logging.LogFactory;
66
67 import org.apache.torque.engine.EngineException;
68
69 import org.xml.sax.Attributes;
70
71 /***
72 * Data about a table used in an application.
73 *
74 * @author <a href="mailto:leon@opticode.co.za">Leon Messerschmidt</a>
75 * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
76 * @author <a href="mailto:mpoeschl@marmot.at>Martin Poeschl</a>
77 * @author <a href="mailto:jmcnally@collab.net>John McNally</a>
78 * @author <a href="mailto:dlr@collab.net>Daniel Rall</a>
79 * @author <a href="mailto:byron_foster@byron_foster@yahoo.com>Byron Foster</a>
80 * @version $Id: Table.java,v 1.3 2003/06/26 22:09:41 dlr Exp $
81 */
82 public class Table implements IDMethod
83 {
84 /*** Logging class from commons.logging */
85 private static Log log = LogFactory.getLog(Table.class);
86
87 //private AttributeListImpl attributes;
88 private List columnList;
89 private List foreignKeys;
90 private List indices;
91 private List unices;
92 private List idMethodParameters;
93 private String name;
94 private String description;
95 private String javaName;
96 private String idMethod;
97 private String javaNamingMethod;
98 private Database tableParent;
99 private List referrers;
100 private List foreignTableNames;
101 private boolean containsForeignPK;
102 private Column inheritanceColumn;
103 private boolean skipSql;
104 private boolean abstractValue;
105 private String alias;
106 private String enterface;
107 private String pkg;
108 private String baseClass;
109 private String basePeer;
110 private Hashtable columnsByName;
111 private Hashtable columnsByJavaName;
112 private boolean needsTransactionInPostgres;
113 private boolean heavyIndexing;
114 private boolean forReferenceOnly;
115
116
117 /***
118 * Default Constructor
119 */
120 public Table()
121 {
122 this(null);
123 }
124
125 /***
126 * Constructs a table object with a name
127 *
128 * @param name table name
129 */
130 public Table(String name)
131 {
132 this.name = name;
133 columnList = new ArrayList();
134 foreignKeys = new ArrayList(5);
135 indices = new ArrayList(5);
136 unices = new ArrayList(5);
137 columnsByName = new Hashtable();
138 columnsByJavaName = new Hashtable();
139 }
140
141 /***
142 * Load the table object from an xml tag.
143 *
144 * @param attrib xml attributes
145 * @param defaultIdMethod defined at db level
146 */
147 public void loadFromXML(Attributes attrib, String defaultIdMethod)
148 {
149 name = attrib.getValue("name");
150 javaName = attrib.getValue("javaName");
151 idMethod = attrib.getValue("idMethod");
152
153 // retrieves the method for converting from specified name to
154 // a java name.
155 javaNamingMethod = attrib.getValue("javaNamingMethod");
156 if (javaNamingMethod == null)
157 {
158 javaNamingMethod = getDatabase().getDefaultJavaNamingMethod();
159 }
160
161 if ("null".equals(idMethod))
162 {
163 idMethod = defaultIdMethod;
164 }
165 if ("autoincrement".equals(idMethod) || "sequence".equals(idMethod))
166 {
167 log.warn("The value '" + idMethod + "' for Torque's "
168 + "table.idMethod attribute has been deprecated in favor "
169 + "of '" + NATIVE + "'. Please adjust your "
170 + "Torque XML schema accordingly.");
171 idMethod = NATIVE;
172 }
173 skipSql = "true".equals(attrib.getValue("skipSql"));
174 // pkg = attrib.getValue("package");
175 abstractValue = "true".equals(attrib.getValue("abstract"));
176 baseClass = attrib.getValue("baseClass");
177 basePeer = attrib.getValue("basePeer");
178 alias = attrib.getValue("alias");
179 heavyIndexing = "true".equals(attrib.getValue("heavyIndexing"))
180 || (!"false".equals(attrib.getValue("heavyIndexing"))
181 && getDatabase().isHeavyIndexing());
182 description = attrib.getValue("description");
183 enterface = attrib.getValue("interface");
184 }
185
186 /***
187 * <p>A hook for the SAX XML parser to call when this table has
188 * been fully loaded from the XML, and all nested elements have
189 * been processed.</p>
190 *
191 * <p>Performs heavy indexing and naming of elements which weren't
192 * provided with a name.</p>
193 */
194 public void doFinalInitialization()
195 {
196 // Heavy indexing must wait until after all columns composing
197 // a table's primary key have been parsed.
198 if (heavyIndexing)
199 {
200 doHeavyIndexing();
201 }
202
203 // Name any indices which are missing a name using the
204 // appropriate algorithm.
205 doNaming();
206 }
207
208 /***
209 * <p>Adds extra indices for multi-part primary key columns.</p>
210 *
211 * <p>For databases like MySQL, values in a where clause must
212 * match key part order from the left to right. So, in the key
213 * definition <code>PRIMARY KEY (FOO_ID, BAR_ID)</code>,
214 * <code>FOO_ID</code> <i>must</i> be the first element used in
215 * the <code>where</code> clause of the SQL query used against
216 * this table for the primary key index to be used. This feature
217 * could cause problems under MySQL with heavily indexed tables,
218 * as MySQL currently only supports 16 indices per table (i.e. it
219 * might cause too many indices to be created).</p>
220 *
221 * <p>See <a href="http://www.mysql.com/doc/E/X/EXPLAIN.html">the
222 * manual</a> for a better description of why heavy indexing is
223 * useful for quickly searchable database tables.</p>
224 */
225 private void doHeavyIndexing()
226 {
227 if (log.isDebugEnabled())
228 {
229 log.debug("doHeavyIndex() called on table " + name);
230 }
231
232 List pk = getPrimaryKey();
233 int size = pk.size();
234
235 try
236 {
237 // We start at an offset of 1 because the entire column
238 // list is generally implicitly indexed by the fact that
239 // it's a primary key.
240 for (int i = 1; i < size; i++)
241 {
242 addIndex(new Index(this, pk.subList(i, size)));
243 }
244 }
245 catch (EngineException e)
246 {
247 log.error(e, e);
248 }
249 }
250
251 /***
252 * Names composing objects which haven't yet been named. This
253 * currently consists of foreign-key and index entities.
254 */
255 private void doNaming()
256 {
257 int i;
258 int size;
259 String name;
260
261 // Assure names are unique across all databases.
262 try
263 {
264 for (i = 0, size = foreignKeys.size(); i < size; i++)
265 {
266 ForeignKey fk = (ForeignKey) foreignKeys.get(i);
267 name = fk.getName();
268 if (StringUtils.isEmpty(name))
269 {
270 name = acquireConstraintName("FK", i + 1);
271 fk.setName(name);
272 }
273 }
274
275 for (i = 0, size = indices.size(); i < size; i++)
276 {
277 Index index = (Index) indices.get(i);
278 name = index.getName();
279 if (StringUtils.isEmpty(name))
280 {
281 name = acquireConstraintName("I", i + 1);
282 index.setName(name);
283 }
284 }
285
286 // NOTE: Most RDBMSes can apparently name unique column
287 // constraints/indices themselves (using MySQL and Oracle
288 // as test cases), so we'll assume that we needn't add an
289 // entry to the system name list for these.
290 }
291 catch (EngineException nameAlreadyInUse)
292 {
293 log.error(nameAlreadyInUse, nameAlreadyInUse);
294 }
295 }
296
297 /***
298 * Macro to a constraint name.
299 *
300 * @param nameType constraint type
301 * @param nbr unique number for this constraint type
302 * @return unique name for constraint
303 * @throws EngineException
304 */
305 private final String acquireConstraintName(String nameType, int nbr)
306 throws EngineException
307 {
308 List inputs = new ArrayList(4);
309 inputs.add(getDatabase());
310 inputs.add(getName());
311 inputs.add(nameType);
312 inputs.add(new Integer(nbr));
313 return NameFactory.generateName(NameFactory.CONSTRAINT_GENERATOR,
314 inputs);
315 }
316
317 /***
318 * Gets the value of base class for classes produced from this table.
319 *
320 * @return The base class for classes produced from this table.
321 */
322 public String getBaseClass()
323 {
324 if (isAlias() && baseClass == null)
325 {
326 return alias;
327 }
328 else if (baseClass == null)
329 {
330 return getDatabase().getBaseClass();
331 }
332 else
333 {
334 return baseClass;
335 }
336 }
337
338 /***
339 * Set the value of baseClass.
340 * @param v Value to assign to baseClass.
341 */
342 public void setBaseClass(String v)
343 {
344 this.baseClass = v;
345 }
346
347 /***
348 * Get the value of basePeer.
349 * @return value of basePeer.
350 */
351 public String getBasePeer()
352 {
353 if (isAlias() && basePeer == null)
354 {
355 return alias + "Peer";
356 }
357 else if (basePeer == null)
358 {
359 return getDatabase().getBasePeer();
360 }
361 else
362 {
363 return basePeer;
364 }
365 }
366
367 /***
368 * Set the value of basePeer.
369 * @param v Value to assign to basePeer.
370 */
371 public void setBasePeer(String v)
372 {
373 this.basePeer = v;
374 }
375
376 /***
377 * A utility function to create a new column from attrib and add it to this
378 * table.
379 *
380 * @param attrib xml attributes for the column to add
381 * @return the added column
382 */
383 public Column addColumn(Attributes attrib)
384 {
385 Column col = new Column();
386 col.setTable(this);
387 col.loadFromXML(attrib);
388 addColumn(col);
389 return col;
390 }
391
392 /***
393 * Adds a new column to the column list and set the
394 * parent table of the column to the current table
395 *
396 * @param col the column to add
397 */
398 public void addColumn(Column col)
399 {
400 col.setTable (this);
401 if (col.isInheritance())
402 {
403 inheritanceColumn = col;
404 }
405 columnList.add(col);
406 columnsByName.put(col.getName(), col);
407 columnsByJavaName.put(col.getJavaName(), col);
408 col.setPosition(columnList.size());
409 needsTransactionInPostgres |= col.requiresTransactionInPostgres();
410 }
411
412 /***
413 * A utility function to create a new foreign key
414 * from attrib and add it to this table.
415 *
416 * @param attrib the xml attributes
417 * @return the created ForeignKey
418 */
419 public ForeignKey addForeignKey(Attributes attrib)
420 {
421 ForeignKey fk = new ForeignKey();
422 fk.loadFromXML(attrib);
423 addForeignKey(fk);
424 return fk;
425 }
426
427 /***
428 * Gets the column that subclasses of the class representing this
429 * table can be produced from.
430 */
431 public Column getChildrenColumn()
432 {
433 return inheritanceColumn;
434 }
435
436 /***
437 * Get the objects that can be created from this table.
438 */
439 public List getChildrenNames()
440 {
441 if (inheritanceColumn == null
442 || !inheritanceColumn.isEnumeratedClasses())
443 {
444 return null;
445 }
446 List children = inheritanceColumn.getChildren();
447 List names = new ArrayList(children.size());
448 for (int i = 0; i < children.size(); i++)
449 {
450 names.add(((Inheritance) children.get(i)).getClassName());
451 }
452 return names;
453 }
454
455 /***
456 * Adds the foreign key from another table that refers to this table.
457 *
458 * @param fk A foreign key refering to this table
459 */
460 public void addReferrer(ForeignKey fk)
461 {
462 if (referrers == null)
463 {
464 referrers = new ArrayList(5);
465 }
466 referrers.add(fk);
467 }
468
469 /***
470 * Get list of references to this table.
471 *
472 * @return A list of references to this table
473 */
474 public List getReferrers()
475 {
476 return referrers;
477 }
478
479 /***
480 * Set whether this table contains a foreign PK
481 *
482 * @param b
483 */
484 public void setContainsForeignPK(boolean b)
485 {
486 containsForeignPK = b;
487 }
488
489 /***
490 * Determine if this table contains a foreign PK
491 */
492 public boolean getContainsForeignPK()
493 {
494 return containsForeignPK;
495 }
496
497 /***
498 * A list of tables referenced by foreign keys in this table
499 *
500 * @return A list of tables
501 */
502 public List getForeignTableNames()
503 {
504 if (foreignTableNames == null)
505 {
506 foreignTableNames = new ArrayList(1);
507 }
508 return foreignTableNames;
509 }
510
511 /***
512 * Adds a new FK to the FK list and set the
513 * parent table of the column to the current table
514 *
515 * @param fk A foreign key
516 */
517 public void addForeignKey(ForeignKey fk)
518 {
519 fk.setTable (this);
520 foreignKeys.add(fk);
521
522 if (foreignTableNames == null)
523 {
524 foreignTableNames = new ArrayList(5);
525 }
526 if (foreignTableNames.contains(fk.getForeignTableName()))
527 {
528 foreignTableNames.add(fk.getForeignTableName());
529 }
530 }
531
532 /***
533 * Return true if the column requires a transaction in Postgres
534 */
535 public boolean requiresTransactionInPostgres()
536 {
537 return needsTransactionInPostgres;
538 }
539
540 /***
541 * A utility function to create a new id method parameter
542 * from attrib and add it to this table.
543 */
544 public IdMethodParameter addIdMethodParameter(Attributes attrib)
545 {
546 IdMethodParameter imp = new IdMethodParameter();
547 imp.loadFromXML(attrib);
548 addIdMethodParameter(imp);
549 return imp;
550 }
551
552
553 /***
554 * Adds a new ID method parameter to the list and sets the parent
555 * table of the column associated with the supplied parameter to this table.
556 *
557 * @param imp The column to add as an ID method parameter.
558 */
559 public void addIdMethodParameter(IdMethodParameter imp)
560 {
561 imp.setTable(this);
562 if (idMethodParameters == null)
563 {
564 idMethodParameters = new ArrayList(2);
565 }
566 idMethodParameters.add(imp);
567 }
568
569 /***
570 * Adds a new index to the index list and set the
571 * parent table of the column to the current table
572 */
573 public void addIndex(Index index)
574 {
575 index.setTable (this);
576 indices.add(index);
577 }
578
579 /***
580 * A utility function to create a new index
581 * from attrib and add it to this table.
582 */
583 public Index addIndex(Attributes attrib)
584 {
585 Index index = new Index();
586 index.loadFromXML(attrib);
587 addIndex(index);
588 return index;
589 }
590
591 /***
592 * Adds a new Unique to the Unique list and set the
593 * parent table of the column to the current table
594 */
595 public void addUnique(Unique unique)
596 {
597 unique.setTable(this);
598 unices.add(unique);
599 }
600
601 /***
602 * A utility function to create a new Unique
603 * from attrib and add it to this table.
604 *
605 * @param attrib the xml attributes
606 */
607 public Unique addUnique(Attributes attrib)
608 {
609 Unique unique = new Unique();
610 unique.loadFromXML(attrib);
611 addUnique(unique);
612 return unique;
613 }
614
615 /***
616 * Get the name of the Table
617 */
618 public String getName()
619 {
620 return name;
621 }
622
623 /***
624 * Set the name of the Table
625 */
626 public void setName(String newName)
627 {
628 name = newName;
629 }
630
631 /***
632 * Get the description for the Table
633 */
634 public String getDescription()
635 {
636 return description;
637 }
638
639 /***
640 * Set the description for the Table
641 *
642 * @param newDescription description for the Table
643 */
644 public void setDescription(String newDescription)
645 {
646 description = newDescription;
647 }
648
649 /***
650 * Get name to use in Java sources
651 */
652 public String getJavaName()
653 {
654 if (javaName == null)
655 {
656 List inputs = new ArrayList(2);
657 inputs.add(name);
658 inputs.add(javaNamingMethod);
659 try
660 {
661 javaName = NameFactory.generateName(NameFactory.JAVA_GENERATOR,
662 inputs);
663 }
664 catch (EngineException e)
665 {
666 log.error(e, e);
667 }
668 }
669 return javaName;
670 }
671
672 /***
673 * Set name to use in Java sources
674 */
675 public void setJavaName(String javaName)
676 {
677 this.javaName = javaName;
678 }
679
680 /***
681 * Get the method for generating pk's
682 */
683 public String getIdMethod()
684 {
685 if (idMethod == null)
686 {
687 return IDMethod.NO_ID_METHOD;
688 }
689 else
690 {
691 return idMethod;
692 }
693 }
694
695 /***
696 * Set the method for generating pk's
697 */
698 public void setIdMethod(String idMethod)
699 {
700 this.idMethod = idMethod;
701 }
702
703 /***
704 * Skip generating sql for this table (in the event it should
705 * not be created from scratch).
706 * @return value of skipSql.
707 */
708 public boolean isSkipSql()
709 {
710 return (skipSql || isAlias() || isForReferenceOnly());
711 }
712
713 /***
714 * Set whether this table should have its creation sql generated.
715 * @param v Value to assign to skipSql.
716 */
717 public void setSkipSql(boolean v)
718 {
719 this.skipSql = v;
720 }
721
722 /***
723 * JavaName of om object this entry references.
724 * @return value of external.
725 */
726 public String getAlias()
727 {
728 return alias;
729 }
730
731 /***
732 * Is this table specified in the schema or is there just
733 * a foreign key reference to it.
734 * @return value of external.
735 */
736 public boolean isAlias()
737 {
738 return (alias != null);
739 }
740
741 /***
742 * Set whether this table specified in the schema or is there just
743 * a foreign key reference to it.
744 * @param v Value to assign to alias.
745 */
746 public void setAlias(String v)
747 {
748 this.alias = v;
749 }
750
751
752 /***
753 * Interface which objects for this table will implement
754 * @return value of interface.
755 */
756 public String getInterface()
757 {
758 return enterface;
759 }
760
761 /***
762 * Interface which objects for this table will implement
763 * @param v Value to assign to interface.
764 */
765 public void setInterface(String v)
766 {
767 this.enterface = v;
768 }
769
770 /***
771 * When a table is abstract, it marks the business object class that is
772 * generated as being abstract. If you have a table called "FOO", then the
773 * Foo BO will be <code>public abstract class Foo</code>
774 * This helps support class hierarchies
775 *
776 * @return value of abstractValue.
777 */
778 public boolean isAbstract()
779 {
780 return abstractValue;
781 }
782
783 /***
784 * When a table is abstract, it marks the business object
785 * class that is generated as being abstract. If you have a
786 * table called "FOO", then the Foo BO will be
787 * <code>public abstract class Foo</code>
788 * This helps support class hierarchies
789 *
790 * @param v Value to assign to abstractValue.
791 */
792 public void setAbstract(boolean v)
793 {
794 this.abstractValue = v;
795 }
796
797 /***
798 * Get the value of package.
799 *
800 * @return value of package.
801 */
802 public String getPackage()
803 {
804 if (pkg != null)
805 {
806 return pkg;
807 }
808 else
809 {
810 return this.getDatabase().getPackage();
811 }
812 }
813
814 /***
815 * Set the value of package.
816 *
817 * @param v Value to assign to package.
818 */
819 public void setPackage(String v)
820 {
821 this.pkg = v;
822 }
823
824 /***
825 * Returns an Array containing all the columns in the table
826 */
827 public Column[] getColumns()
828 {
829 int size = columnList.size();
830 Column[] tbls = new Column[size];
831 for (int i = 0; i < size; i++)
832 {
833 tbls[i] = (Column) columnList.get(i);
834 }
835 return tbls;
836 }
837
838 /***
839 * Utility method to get the number of columns in this table
840 */
841 public int getNumColumns()
842 {
843 return columnList.size();
844 }
845
846 /***
847 * Returns an Array containing all the FKs in the table
848 */
849 public ForeignKey[] getForeignKeys()
850 {
851 int size = foreignKeys.size();
852 ForeignKey[] tbls = new ForeignKey[size];
853 for (int i = 0; i < size; i++)
854 {
855 tbls[i] = (ForeignKey) foreignKeys.get(i);
856 }
857 return tbls;
858 }
859
860 /***
861 * Returns a Collection of parameters relevant for the chosen
862 * id generation method.
863 */
864 public List getIdMethodParameters()
865 {
866 return idMethodParameters;
867 }
868
869 /***
870 * A name to use for creating a sequence if one is not specified.
871 *
872 * @return name of the sequence
873 */
874 public String getSequenceName()
875 {
876 String result = null;
877 if (getIdMethod().equals(NATIVE))
878 {
879 List idMethodParams = getIdMethodParameters();
880 if (idMethodParams == null)
881 {
882 result = getName() + "_SEQ";
883 }
884 else
885 {
886 result = ((IdMethodParameter) idMethodParams.get(0)).getValue();
887 }
888 }
889 return result;
890 }
891
892 /***
893 * Returns an Array containing all the indices in the table
894 *
895 * @return An array containing all the indices
896 */
897 public Index[] getIndices()
898 {
899 int size = indices.size();
900 Index[] tbls = new Index[size];
901 for (int i = 0; i < size; i++)
902 {
903 tbls[i] = (Index) indices.get(i);
904 }
905 return tbls;
906 }
907
908 /***
909 * Returns an Array containing all the UKs in the table
910 *
911 * @return An array containing all the UKs
912 */
913 public Unique[] getUnices()
914 {
915 int size = unices.size();
916 Unique[] tbls = new Unique[size];
917 for (int i = 0; i < size; i++)
918 {
919 tbls[i] = (Unique) unices.get(i);
920 }
921 return tbls;
922 }
923
924 /***
925 * Returns a specified column.
926 *
927 * @param name name of the column
928 * @return Return a Column object or null if it does not exist.
929 */
930 public Column getColumn(String name)
931 {
932 return (Column) columnsByName.get(name);
933 }
934
935 /***
936 * Returns a specified column.
937 *
938 * @param javaName java name of the column
939 * @return Return a Column object or null if it does not exist.
940 */
941 public Column getColumnByJavaName(String javaName)
942 {
943 return (Column) columnsByJavaName.get(javaName);
944 }
945
946 /***
947 * Return the first foreign key that includes col in it's list
948 * of local columns. Eg. Foreign key (a,b,c) refrences tbl(x,y,z)
949 * will be returned of col is either a,b or c.
950 *
951 * @param col column name included in the key
952 * @return Return a Column object or null if it does not exist.
953 */
954 public ForeignKey getForeignKey(String col)
955 {
956 ForeignKey firstFK = null;
957 for (Iterator iter = foreignKeys.iterator(); iter.hasNext();)
958 {
959 ForeignKey key = (ForeignKey) iter.next();
960 if (key.getLocalColumns().contains(col))
961 {
962 if (firstFK == null)
963 {
964 firstFK = key;
965 }
966 else
967 {
968 //System.out.println(col+" is in multiple FKs. This is not"
969 // + " being handled properly.");
970 //throw new IllegalStateException("Cannot call method if " +
971 // "column is referenced multiple times");
972 }
973 }
974 }
975 return firstFK;
976 }
977
978 /***
979 * Returns true if the table contains a specified column
980 *
981 * @param col the column
982 * @return true if the table contains the column
983 */
984 public boolean containsColumn(Column col)
985 {
986 return columnList.contains(col);
987 }
988
989 /***
990 * Returns true if the table contains a specified column
991 *
992 * @param name name of the column
993 * @return true if the table contains the column
994 */
995 public boolean containsColumn(String name)
996 {
997 return (getColumn(name) != null);
998 }
999
1000 /***
1001 * Set the parent of the table
1002 *
1003 * @param parent the parant database
1004 */
1005 public void setDatabase(Database parent)
1006 {
1007 tableParent = parent;
1008 }
1009
1010 /***
1011 * Get the parent of the table
1012 *
1013 * @return the parant database
1014 */
1015 public Database getDatabase()
1016 {
1017 return tableParent;
1018 }
1019
1020 /***
1021 * Flag to determine if code/sql gets created for this table.
1022 * Table will be skipped, if return true.
1023 * @return value of forReferenceOnly.
1024 */
1025 public boolean isForReferenceOnly()
1026 {
1027 return forReferenceOnly;
1028 }
1029
1030 /***
1031 * Flag to determine if code/sql gets created for this table.
1032 * Table will be skipped, if set to true.
1033 * @param v Value to assign to forReferenceOnly.
1034 */
1035 public void setForReferenceOnly(boolean v)
1036 {
1037 this.forReferenceOnly = v;
1038 }
1039
1040 /***
1041 * Returns a XML representation of this table.
1042 *
1043 * @return XML representation of this table
1044 */
1045 public String toString()
1046 {
1047 StringBuffer result = new StringBuffer();
1048
1049 result.append ("<table name=\"")
1050 .append(name)
1051 .append('\"');
1052
1053 if (javaName != null)
1054 {
1055 result.append(" javaName=\"")
1056 .append(javaName)
1057 .append('\"');
1058 }
1059
1060 if (idMethod != null)
1061 {
1062 result.append(" idMethod=\"")
1063 .append(idMethod)
1064 .append('\"');
1065 }
1066
1067 if (skipSql)
1068 {
1069 result.append(" skipSql=\"")
1070 .append(new Boolean(skipSql))
1071 .append('\"');
1072 }
1073
1074 if (abstractValue)
1075 {
1076 result.append(" abstract=\"")
1077 .append(new Boolean(abstractValue))
1078 .append('\"');
1079 }
1080
1081 if (baseClass != null)
1082 {
1083 result.append(" baseClass=\"")
1084 .append(baseClass)
1085 .append('\"');
1086 }
1087
1088 if (basePeer != null)
1089 {
1090 result.append(" basePeer=\"")
1091 .append(basePeer)
1092 .append('\"');
1093 }
1094
1095 result.append(">\n");
1096
1097 if (columnList != null)
1098 {
1099 for (Iterator iter = columnList.iterator(); iter.hasNext();)
1100 {
1101 result.append(iter.next());
1102 }
1103 }
1104
1105 if (foreignKeys != null)
1106 {
1107 for (Iterator iter = foreignKeys.iterator(); iter.hasNext();)
1108 {
1109 result.append(iter.next());
1110 }
1111 }
1112
1113 if (idMethodParameters != null)
1114 {
1115 Iterator iter = idMethodParameters.iterator();
1116 while (iter.hasNext())
1117 {
1118 result.append(iter.next());
1119 }
1120 }
1121
1122 result.append ("</table>\n");
1123
1124 return result.toString();
1125 }
1126
1127 /***
1128 * Returns the collection of Columns which make up the single primary
1129 * key for this table.
1130 *
1131 * @return A list of the primary key parts.
1132 */
1133 public List getPrimaryKey()
1134 {
1135 List pk = new ArrayList(columnList.size());
1136
1137 Iterator iter = columnList.iterator();
1138 while (iter.hasNext())
1139 {
1140 Column col = (Column) iter.next();
1141 if (col.isPrimaryKey())
1142 {
1143 pk.add(col);
1144 }
1145 }
1146 return pk;
1147 }
1148
1149 /***
1150 * Determine whether this table has a primary key.
1151 *
1152 * @return Whether this table has any primary key parts.
1153 */
1154 public boolean hasPrimaryKey()
1155 {
1156 return (getPrimaryKey().size() > 0);
1157 }
1158
1159 /***
1160 * Returns all parts of the primary key, separated by commas.
1161 *
1162 * @return A CSV list of primary key parts.
1163 */
1164 public String printPrimaryKey()
1165 {
1166 return printList(columnList);
1167 }
1168
1169 /***
1170 * Returns the elements of the list, separated by commas.
1171 *
1172 * @param list a list of Columns
1173 * @return A CSV list.
1174 */
1175 private String printList(List list)
1176 {
1177 StringBuffer result = new StringBuffer();
1178 boolean comma = false;
1179 for (Iterator iter = list.iterator(); iter.hasNext();)
1180 {
1181 Column col = (Column) iter.next();
1182 if (col.isPrimaryKey())
1183 {
1184 if (comma)
1185 {
1186 result.append(',');
1187 }
1188 else
1189 {
1190 comma = true;
1191 }
1192 result.append(col.getName());
1193 }
1194 }
1195 return result.toString();
1196 }
1197 }
This page was automatically generated by Maven