View Javadoc

1   package org.apache.torque.engine.database.model;
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.ArrayList;
23  import java.util.Collections;
24  import java.util.Iterator;
25  import java.util.List;
26  import java.util.Map;
27  
28  import org.apache.commons.collections.map.ListOrderedMap;
29  import org.apache.commons.lang.StringUtils;
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  import org.apache.torque.engine.EngineException;
33  import org.apache.torque.engine.platform.Platform;
34  import org.apache.torque.engine.platform.PlatformDefaultImpl;
35  import org.xml.sax.Attributes;
36  
37  /***
38   * A Class for holding data about a column used in an Application.
39   *
40   * @author <a href="mailto:leon@opticode.co.za">Leon Messerschmidt</a>
41   * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
42   * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
43   * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
44   * @author <a href="mailto:byron_foster@byron_foster@yahoo.com>Byron Foster</a>
45   * @author <a href="mailto:mpoeschl@marmot.at>Martin Poeschl</a>
46   * @author <a href="mailto:monroe@dukece.com>Greg Monroe</a>
47   * @version $Id: Column.java 476581 2006-11-18 18:14:14Z tv $
48   */
49  public class Column
50  {
51      private static final SchemaType DEFAULT_TYPE = SchemaType.VARCHAR;
52      /*** Logging class from commons.logging */
53      private static Log log = LogFactory.getLog(Column.class);
54      private String name;
55      private String description;
56      private Domain domain = new Domain();
57      private String javaName = null;
58      private String javaNamingMethod;
59      private boolean isNotNull = false;
60      private boolean isProtected = false;
61      private String javaType;
62      private Table parentTable;
63      private int position;
64      private boolean isPrimaryKey = false;
65      private boolean isUnique = false;
66      private boolean isAutoIncrement = false;
67      private List referrers;
68      // only one type is supported currently, which assumes the
69      // column either contains the classnames or a key to
70      // classnames specified in the schema.  Others may be
71      // supported later.
72      private String inheritanceType;
73      private boolean isInheritance;
74      private boolean isEnumeratedClasses;
75      private List inheritanceList;
76      private boolean needsTransactionInPostgres;
77  
78      /*** generate is... setters for boolean columns if true */
79      private boolean correctGetters = false;
80  
81      /*** class name to do input validation on this column */
82      private String inputValidator = null;
83      private Map options;
84  
85      /***
86       * Creates a new instance with a <code>null</code> name.
87       */
88      public Column()
89      {
90          this(null);
91      }
92  
93      /***
94       * Creates a new column and set the name
95       *
96       * @param name column name
97       */
98      public Column(String name)
99      {
100         this.name = name;
101         options = Collections.synchronizedMap(new ListOrderedMap());
102     }
103 
104     /***
105      * Return a comma delimited string listing the specified columns.
106      *
107      * @param columns Either a list of <code>Column</code> objects, or
108      * a list of <code>String</code> objects with column names.
109      */
110     public static String makeList(List columns)
111     {
112         Object obj = columns.get(0);
113         boolean isColumnList = (obj instanceof Column);
114         if (isColumnList)
115         {
116             obj = ((Column) obj).getName();
117         }
118         StringBuffer buf = new StringBuffer((String) obj);
119         for (int i = 1; i < columns.size(); i++)
120         {
121             obj = columns.get(i);
122             if (isColumnList)
123             {
124                 obj = ((Column) obj).getName();
125             }
126             buf.append(", ").append(obj);
127         }
128         return buf.toString();
129     }
130 
131     /***
132      * Imports a column from an XML specification
133      */
134     public void loadFromXML(Attributes attrib)
135     {
136         String dom = attrib.getValue("domain");
137         if (StringUtils.isNotEmpty(dom))
138         {
139             domain = new Domain(getTable().getDatabase().getDomain(dom));
140         }
141         else
142         {
143             domain = new Domain(getPlatform().getDomainForSchemaType(DEFAULT_TYPE));
144             setType(attrib.getValue("type"));
145         }
146         //Name
147         name = attrib.getValue("name");
148 
149         javaName = attrib.getValue("javaName");
150         javaType = attrib.getValue("javaType");
151         if (javaType != null && javaType.length() == 0)
152         {
153             javaType = null;
154         }
155 
156         // retrieves the method for converting from specified name to
157         // a java name.
158         javaNamingMethod = attrib.getValue("javaNamingMethod");
159         if (javaNamingMethod == null)
160         {
161             javaNamingMethod
162                     = parentTable.getDatabase().getDefaultJavaNamingMethod();
163         }
164 
165         //Primary Key
166         String primaryKey = attrib.getValue("primaryKey");
167         //Avoid NullPointerExceptions on string comparisons.
168         isPrimaryKey = ("true".equals(primaryKey));
169 
170         // If this column is a primary key then it can't be null.
171         if ("true".equals(primaryKey))
172         {
173             isNotNull = true;
174         }
175 
176         // HELP: Should primary key, index, and/or idMethod="native"
177         // affect isNotNull?  If not, please document why here.
178         String notNull = attrib.getValue("required");
179         isNotNull = (notNull != null && "true".equals(notNull));
180 
181         //AutoIncrement/Sequences
182         String autoIncrement = attrib.getValue("autoIncrement");
183         // autoincrement is false per default,
184         // except if the column is a primary key
185         // and the idMethod is native
186         // and the platform's default id Method is identity
187         // and autoIncrement is not excplicitly set to false
188         isAutoIncrement = ("true".equals(autoIncrement)
189                 || (isPrimaryKey()
190                     && IDMethod.NATIVE.equals(getTable().getIdMethod())
191                     && Platform.IDENTITY.equals(
192                             getPlatform().getNativeIdMethod())
193                     && (!"false".equals(autoIncrement))));
194         //Default column value.
195         domain.replaceDefaultValue(attrib.getValue("default"));
196 
197         domain.replaceSize(attrib.getValue("size"));
198         domain.replaceScale(attrib.getValue("scale"));
199 
200         inheritanceType = attrib.getValue("inheritance");
201         isInheritance = (inheritanceType != null
202                 && !inheritanceType.equals("false"));
203 
204         this.inputValidator = attrib.getValue("inputValidator");
205         description = attrib.getValue("description");
206 
207         isProtected = ("true".equals(attrib.getValue("protected")));
208     }
209 
210     /***
211      * Returns table.column
212      */
213     public String getFullyQualifiedName()
214     {
215         return (parentTable.getName() + '.' + name);
216     }
217 
218     /***
219      * Get the name of the column
220      */
221     public String getName()
222     {
223         return name;
224     }
225 
226     /***
227      * Set the name of the column
228      */
229     public void setName(String newName)
230     {
231         name = newName;
232     }
233 
234     /***
235      * Get the description for the Table
236      */
237     public String getDescription()
238     {
239         return description;
240     }
241 
242     /***
243      * Set the description for the Table
244      *
245      * @param newDescription description for the Table
246      */
247     public void setDescription(String newDescription)
248     {
249         description = newDescription;
250     }
251 
252     /***
253      * Get name to use in Java sources to build method names.
254      *
255      * @return the capitalised javaName
256      */
257     public String getJavaName()
258     {
259         if (javaName == null)
260         {
261             List inputs = new ArrayList(2);
262             inputs.add(name);
263             inputs.add(javaNamingMethod);
264             try
265             {
266                 javaName = NameFactory.generateName(NameFactory.JAVA_GENERATOR,
267                                                     inputs);
268             }
269             catch (EngineException e)
270             {
271                 log.error(e, e);
272             }
273         }
274         return StringUtils.capitalize(javaName);
275     }
276 
277     /***
278      * Returns the name for the getter method to retrieve the value of this
279      * column
280      *
281      * @return A getter method name for this column.
282      * @since 3.2
283      */
284     public String getGetterName()
285     {
286         if (("boolean".equalsIgnoreCase(getJavaNative()) && isCorrectGetters()))
287         {
288             return "is" + StringUtils.capitalize(getJavaName());
289         }
290         else
291         {
292             return "get" + StringUtils.capitalize(getJavaName());
293         }
294     }
295 
296     /***
297      * Returns the name for the setter method to set the value of this
298      * column
299      *
300      * @return A setter method name for this column.
301      * @since 3.2
302      */
303     public String getSetterName()
304     {
305         return "set" + StringUtils.capitalize(getJavaName());
306     }
307 
308     /***
309      * Get variable name to use in Java sources (= uncapitalised java name)
310      */
311     public String getUncapitalisedJavaName()
312     {
313         return StringUtils.uncapitalize(getJavaName());
314     }
315 
316     /***
317      * Returns the name of the constant that is used for the column in the Peer
318      * class, e.g., RecordPeer.COLVARNAME.
319      * Generally this will be a straight conversion to upper case.
320      * But if the column name is equals to TABLE_NAME or
321      * DATABASE_NAME (Torque predefined vars), the column name will have an _
322      * prefixed, e.g. _TABLE_NAME.
323      * <p>
324      * TODO: Handle delimited column names that have non-Java identifier
325      * characters in them.
326      *
327      * @return The name to use in defining the Peer class column variable.
328      */
329     public String getPeerJavaName()
330     {
331         String peerName = name.toUpperCase();
332         if ( peerName.equals("TABLE_NAME") ||
333              peerName.equals("DATABASE_NAME")) {
334             peerName = "_" + peerName;
335         }
336         return peerName;
337     }
338 
339     /***
340      * Set the name to use in Java sources.
341      */
342     public void setJavaName(String javaName)
343     {
344         this.javaName = javaName;
345     }
346 
347     /***
348      * Returns whether the type in the java object should be an object
349      * or primitive.
350      */
351     public String getJavaType()
352     {
353         return javaType;
354     }
355 
356     /***
357      * Get the location of this column within the table (one-based).
358      * @return value of position.
359      */
360     public int getPosition()
361     {
362         return position;
363     }
364 
365     /***
366      * Get the location of this column within the table (one-based).
367      * @param v  Value to assign to position.
368      */
369     public void setPosition(int  v)
370     {
371         this.position = v;
372     }
373 
374     /***
375      * Set the parent Table of the column
376      */
377     public void setTable(Table parent)
378     {
379         parentTable = parent;
380     }
381 
382     /***
383      * Get the parent Table of the column
384      */
385     public Table getTable()
386     {
387         return parentTable;
388     }
389 
390     /***
391      * Returns the Name of the table the column is in
392      */
393     public String getTableName()
394     {
395         return parentTable.getName();
396     }
397 
398     /***
399      * A utility function to create a new column
400      * from attrib and add it to this table.
401      */
402     public Inheritance addInheritance(Attributes attrib)
403     {
404         Inheritance inh = new Inheritance();
405         inh.loadFromXML (attrib);
406         addInheritance(inh);
407 
408         return inh;
409     }
410 
411     /***
412      * Adds a new inheritance definition to the inheritance list and set the
413      * parent column of the inheritance to the current column
414      */
415     public void addInheritance(Inheritance inh)
416     {
417         inh.setColumn(this);
418         if (inheritanceList == null)
419         {
420             inheritanceList = new ArrayList();
421             isEnumeratedClasses = true;
422         }
423         inheritanceList.add(inh);
424     }
425 
426     /***
427      * Get the inheritance definitions.
428      */
429     public List getChildren()
430     {
431         return inheritanceList;
432     }
433 
434     /***
435      * Determine if this column is a normal property or specifies a
436      * the classes that are represented in the table containing this column.
437      */
438     public boolean isInheritance()
439     {
440         return isInheritance;
441     }
442 
443     /***
444      * Determine if possible classes have been enumerated in the xml file.
445      */
446     public boolean isEnumeratedClasses()
447     {
448         return isEnumeratedClasses;
449     }
450 
451     /***
452      * Return the isNotNull property of the column
453      */
454     public boolean isNotNull()
455     {
456         return isNotNull;
457     }
458 
459     /***
460      * Set the isNotNull property of the column
461      */
462     public void setNotNull(boolean status)
463     {
464         isNotNull = status;
465     }
466 
467     /***
468      * Return NOT NULL String for this column
469      *
470      * @return "NOT NULL" if null values are not allowed or an empty String.
471      */
472     public String getNotNullString()
473     {
474         return getTable().getDatabase().getPlatform()
475                 .getNullString(this.isNotNull());
476     }
477 
478     /***
479      * Return the isProtected property of the column
480      */
481     public boolean isProtected()
482     {
483         return isProtected;
484     }
485 
486     /***
487      * Set the isProtected property of the Column
488      */
489     public void setProtected(boolean prot)
490     {
491         isProtected = prot;
492     }
493 
494     /***
495      * Set if the column is a primary key or not
496      */
497     public void setPrimaryKey(boolean pk)
498     {
499         isPrimaryKey = pk;
500     }
501 
502     /***
503      * Return true if the column is a primary key
504      */
505     public boolean isPrimaryKey()
506     {
507         return isPrimaryKey;
508     }
509 
510     /***
511      * Set true if the column is UNIQUE
512      */
513     public void setUnique (boolean u)
514     {
515         isUnique = u;
516     }
517 
518     /***
519      * Get the UNIQUE property
520      */
521     public boolean isUnique()
522     {
523         return isUnique;
524     }
525 
526     /***
527      * Return true if the column requires a transaction in Postgres
528      */
529     public boolean requiresTransactionInPostgres()
530     {
531         return needsTransactionInPostgres;
532     }
533 
534     /***
535      * Utility method to determine if this column is a foreign key.
536      */
537     public boolean isForeignKey()
538     {
539         return (getForeignKey() != null);
540     }
541 
542     /***
543      * Determine if this column is a foreign key that refers to the
544      * same table as another foreign key column in this table.
545      */
546     public boolean isMultipleFK()
547     {
548         ForeignKey fk = getForeignKey();
549         if (fk != null)
550         {
551             Iterator fks = parentTable.getForeignKeys().iterator();
552             while (fks.hasNext())
553             {
554                 ForeignKey key = (ForeignKey) fks.next();
555                 if (key.getForeignTableName().equals(fk.getForeignTableName())
556                         && !key.getLocalColumns().contains(this.name))
557                 {
558                     return true;
559                 }
560             }
561         }
562 
563         // No multiple foreign keys.
564         return false;
565     }
566 
567     /***
568      * get the foreign key object for this column
569      * if it is a foreign key or part of a foreign key
570      */
571     public ForeignKey getForeignKey()
572     {
573         return parentTable.getForeignKey(this.name);
574     }
575 
576     /***
577      * Utility method to get the related table of this column if it is a foreign
578      * key or part of a foreign key
579      */
580     public String getRelatedTableName()
581     {
582         ForeignKey fk = getForeignKey();
583         return (fk == null ? null : fk.getForeignTableName());
584     }
585 
586     /***
587      * Utility method to get the related column of this local column if this
588      * column is a foreign key or part of a foreign key.
589      */
590     public String getRelatedColumnName()
591     {
592         ForeignKey fk = getForeignKey();
593         if (fk == null)
594         {
595             return null;
596         }
597         else
598         {
599             return fk.getLocalForeignMapping().get(this.name).toString();
600         }
601     }
602 
603     /***
604      * Adds the foreign key from another table that refers to this column.
605      */
606     public void addReferrer(ForeignKey fk)
607     {
608         if (referrers == null)
609         {
610             referrers = new ArrayList(5);
611         }
612         referrers.add(fk);
613     }
614 
615     /***
616      * Get list of references to this column.
617      */
618     public List getReferrers()
619     {
620         if (referrers == null)
621         {
622             referrers = new ArrayList(5);
623         }
624         return referrers;
625     }
626 
627     /***
628      * Sets the colunm type
629      */
630     public void setType(String torqueType)
631     {
632         SchemaType type = SchemaType.getEnum(torqueType);
633         if (type == null)
634         {
635             log.warn("SchemaType " + torqueType + " does not exist");
636             type = Column.DEFAULT_TYPE;
637         }
638         setType(type);
639     }
640 
641     /***
642      * Sets the colunm type
643      */
644     public void setType(SchemaType torqueType)
645     {
646         domain = new Domain(getPlatform().getDomainForSchemaType(torqueType));
647         if (torqueType.equals(SchemaType.VARBINARY)
648                 || torqueType.equals(SchemaType.BLOB))
649         {
650             needsTransactionInPostgres = true;
651         }
652     }
653 
654     /***
655      * Returns the column jdbc type as an object
656      *
657      * @deprecated the type conversion is handled by the platform package
658      *             (since torque 3.2)
659      */
660     public Object getType()
661     {
662         return TypeMap.getJdbcType(domain.getType()).getName();
663     }
664 
665     /***
666      * Returns the column type as given in the schema as an object
667      */
668     public Object getTorqueType()
669     {
670         return domain.getType().getName();
671     }
672 
673     /***
674      * Utility method to see if the column is a string
675      *
676      * @deprecated will be removed after the 3.3 release
677      */
678     public boolean isString()
679     {
680         return (domain.getType().getName().indexOf ("CHAR") != -1);
681     }
682 
683     /***
684      * Utility method to return the value as an element to be usable
685      * in an SQL insert statement. This is used from the SQL loader task
686      */
687     public boolean needEscapedValue()
688     {
689         String torqueType = domain.getType().getName();
690         return (torqueType != null) && (torqueType.equals("VARCHAR")
691                         || torqueType.equals("LONGVARCHAR")
692                         || torqueType.equals("DATE")
693                         || torqueType.equals("DATETIME")
694                         || torqueType.equals("TIMESTAMP")
695                         || torqueType.equals("TIME")
696                         || torqueType.equals("CHAR")
697                         || torqueType.equals("CLOB"));
698     }
699 
700     /***
701      * String representation of the column. This is an xml representation.
702      *
703      * @return string representation in xml
704      */
705     public String toString()
706     {
707         StringBuffer result = new StringBuffer();
708         result.append("    <column name=\"").append(name).append('"');
709 
710         if (javaName != null)
711         {
712             result.append(" javaName=\"").append(javaName).append('"');
713         }
714 
715         if (isPrimaryKey)
716         {
717             result.append(" primaryKey=\"").append(isPrimaryKey).append('"');
718         }
719 
720         if (isNotNull)
721         {
722             result.append(" required=\"true\"");
723         }
724         else
725         {
726             result.append(" required=\"false\"");
727         }
728 
729         result.append(" type=\"").append(domain.getType().getName()).append('"');
730 
731         if (domain.getSize() != null)
732         {
733             result.append(" size=\"").append(domain.getSize()).append('"');
734         }
735 
736         if (domain.getScale() != null)
737         {
738             result.append(" scale=\"").append(domain.getScale()).append('"');
739         }
740 
741         if (domain.getDefaultValue() != null)
742         {
743             result.append(" default=\"").append(domain.getDefaultValue()).append('"');
744         }
745 
746         if (isInheritance())
747         {
748             result.append(" inheritance=\"").append(inheritanceType)
749                 .append('"');
750         }
751 
752         // Close the column.
753         result.append(" />\n");
754 
755         return result.toString();
756     }
757 
758     /***
759      * Returns the size of the column
760      */
761     public String getSize()
762     {
763         return domain.getSize();
764     }
765 
766     /***
767      * Set the size of the column
768      */
769     public void setSize(String newSize)
770     {
771         domain.setSize(newSize);
772     }
773 
774     /***
775      * Try to determine the precision of the field from the size attribute.
776      * If size attribute is an integer number, it will be returned.
777      * If size attribute is of the format "Precision,Scale", then Precision
778      * will be returned.
779      * If size is null or the size value is not an valid integer,
780      * null is returned.
781      * <p>
782      * Note: Unparseable values will be logged as a warning.
783      *
784      * @return The precision portion of the size attribute.
785      */
786     public String getPrecision()
787     {
788         String size = getSize();
789         if ( size == null )
790         {
791             return size;
792         }
793         int cLoc = size.indexOf(',');
794         if ( cLoc > 0 )
795         {
796             size = size.substring(0, cLoc);
797         }
798         try
799         {
800             Integer.parseInt(size);
801         }
802         catch ( NumberFormatException e  )
803         {
804             log.warn("getPrecision(): Size attribute found ("
805                     + getSize()
806                     + ") was not an integer number, using default of null!");
807             size = null;
808         }
809         return size;
810     }
811 
812     /***
813      * Try to determine the scale of the field from the scale and size
814      * attribute.
815      * If scale attribute is an integer number, it will be returned.
816      * If size attribute is of the format "Precision,Scale", then Scale
817      * will be returned.
818      * If scale and size attributes are null or the scale value found
819      * is not an valid integer, a null value is returned.
820      * <p>
821      * Note: Unparseable values will be logged as a warning.
822      *
823      * @return The precision portion of the size attribute.
824      */
825     public String getScale()
826     {
827         String scale = domain.getScale();
828         // Check for scale on size attribute if no scale attribute
829         if ( scale == null )
830         {
831             scale = getSize();
832             if ( scale == null )   // No scale or size attribute set.
833             {
834                 return scale;
835             }
836             int cLoc = scale.indexOf(',');
837             if ( cLoc < 0 )        // Size did not have "P,S" format
838             {
839                 return null;
840             }
841             scale = scale.substring(cLoc + 1 );
842         }
843 
844         // Validate that scale string found is integer.
845         try
846         {
847             Integer.parseInt(scale);
848         }
849         catch ( NumberFormatException e  )
850         {
851             log.warn("getScale(): Scale (or size=\"p,s\") attribute found ("
852                     + scale
853                     + ") was not an integer number, using default of null.");
854             scale = null;
855         }
856         return scale;
857     }
858 
859     /***
860      * Set the scale of the column
861      */
862     public void setScale(String newScale)
863     {
864         domain.setScale(newScale);
865     }
866 
867     /***
868      * Return the size and scale in brackets for use in an sql schema.
869      *
870      * @return size and scale or an empty String if there are no values
871      *         available.
872      */
873     public String printSize()
874     {
875         return domain.printSize();
876     }
877 
878     /***
879      * Return a string that will give this column a default value.
880      * @deprecated
881      */
882      public String getDefaultSetting()
883      {
884          return domain.getDefaultSetting();
885      }
886 
887     /***
888      * Set a string that will give this column a default value.
889      */
890     public void setDefaultValue(String def)
891     {
892         domain.setDefaultValue(def);
893     }
894 
895     /***
896      * Get a string that will give this column a default value.
897      */
898     public String getDefaultValue()
899     {
900         return domain.getDefaultValue();
901     }
902 
903     /***
904      * Returns the class name to do input validation
905      */
906     public String getInputValidator()
907     {
908        return this.inputValidator;
909     }
910 
911     /***
912      * Return auto increment/sequence string for the target database. We need to
913      * pass in the props for the target database!
914      */
915     public boolean isAutoIncrement()
916     {
917         return isAutoIncrement;
918     }
919 
920     /***
921      * Set the auto increment value.
922      * Use isAutoIncrement() to find out if it is set or not.
923      */
924     public void setAutoIncrement(boolean value)
925     {
926         isAutoIncrement = value;
927     }
928 
929     public String getAutoIncrementString()
930     {
931         if (isAutoIncrement()
932                 && IDMethod.NATIVE.equals(getTable().getIdMethod()))
933         {
934             return getPlatform().getAutoIncrement();
935         }
936         return "";
937     }
938 
939     /***
940      * Set the column type from a string property
941      * (normally a string from an sql input file)
942      */
943     public void setTypeFromString(String typeName, String size)
944     {
945         String tn = typeName.toUpperCase();
946         setType(tn);
947 
948         if (size != null)
949         {
950             domain.setSize(size);
951         }
952 
953         if (tn.indexOf("CHAR") != -1)
954         {
955             domain.setType(SchemaType.VARCHAR);
956         }
957         else if (tn.indexOf("INT") != -1)
958         {
959             domain.setType(SchemaType.INTEGER);
960         }
961         else if (tn.indexOf("FLOAT") != -1)
962         {
963             domain.setType(SchemaType.FLOAT);
964         }
965         else if (tn.indexOf("DATE") != -1)
966         {
967             domain.setType(SchemaType.DATE);
968         }
969         else if (tn.indexOf("TIME") != -1)
970         {
971             domain.setType(SchemaType.TIMESTAMP);
972         }
973         else if (tn.indexOf("BINARY") != -1)
974         {
975             domain.setType(SchemaType.LONGVARBINARY);
976         }
977         else
978         {
979             domain.setType(SchemaType.VARCHAR);
980         }
981     }
982 
983     /***
984      * Return a string representation of the
985      * Java object which corresponds to the JDBC
986      * type of this column. Use in the generation
987      * of MapBuilders.
988      */
989     public String getJavaObject()
990     {
991         return TypeMap.getJavaObject(domain.getType());
992     }
993 
994     /***
995      * Return a string representation of the primitive java type which
996      * corresponds to the JDBC type of this column.
997      *
998      * @return string representation of the primitive java type
999      */
1000     public String getJavaPrimitive()
1001     {
1002         return TypeMap.getJavaNative(domain.getType());
1003     }
1004 
1005     /***
1006      * Return a string representation of the native java type which corresponds
1007      * to the JDBC type of this column. Use in the generation of Base objects.
1008      * This method is used by torque, so it returns Key types for primaryKey and
1009      * foreignKey columns
1010      *
1011      * @return java datatype used by torque
1012      */
1013     public String getJavaNative()
1014     {
1015         String jtype = TypeMap.getJavaNativeObject(domain.getType());
1016         if (isUsePrimitive())
1017         {
1018             jtype = TypeMap.getJavaNative(domain.getType());
1019         }
1020 
1021         return jtype;
1022     }
1023 
1024     /***
1025      * Return Village asX() method which corresponds to the JDBC type
1026      * which represents this column.
1027      */
1028     public String getVillageMethod()
1029     {
1030         String vmethod = TypeMap.getVillageObjectMethod(domain.getType());
1031         if (isUsePrimitive())
1032         {
1033             vmethod = TypeMap.getVillageMethod(domain.getType());
1034         }
1035 
1036         return vmethod;
1037     }
1038 
1039     /***
1040      * Return ParameterParser getX() method which
1041      * corresponds to the JDBC type which represents this column.
1042      */
1043     public String getParameterParserMethod()
1044     {
1045         return TypeMap.getPPMethod(domain.getType());
1046     }
1047 
1048     /***
1049      * Returns true if the column type is boolean in the
1050      * java object and a numeric (1 or 0) in the db.
1051      */
1052     public boolean isBooleanInt()
1053     {
1054         return TypeMap.isBooleanInt(domain.getType());
1055     }
1056 
1057     /***
1058      * Returns true if the column type is boolean in the
1059      * java object and a String ("Y" or "N") in the db.
1060      */
1061     public boolean isBooleanChar()
1062     {
1063         return TypeMap.isBooleanChar(domain.getType());
1064     }
1065 
1066     /***
1067      * Returns true if the column type is boolean in the
1068      * java object and a Bit ("1" or "0") in the db.
1069      */
1070     public boolean isBit()
1071     {
1072         return TypeMap.isBit(domain.getType());
1073     }
1074 
1075     /***
1076      * returns true, if the columns java native type is an
1077      * boolean, byte, short, int, long, float, double, char
1078      */
1079     public boolean isPrimitive()
1080     {
1081         String t = getJavaNative();
1082         return "boolean".equals(t)
1083             || "byte".equals(t)
1084             || "short".equals(t)
1085             || "int".equals(t)
1086             || "long".equals(t)
1087             || "float".equals(t)
1088             || "double".equals(t)
1089             || "char".equals(t);
1090     }
1091 
1092     public boolean isUsePrimitive()
1093     {
1094         String s = getJavaType();
1095         return (s != null && s.equals("primitive"))
1096             || (s == null && !"object".equals(
1097                getTable().getDatabase().getDefaultJavaType()));
1098     }
1099 
1100     /***
1101      * @return Returns the domain.
1102      */
1103     public Domain getDomain()
1104     {
1105         return domain;
1106     }
1107 
1108     /***
1109      * @param domain The domain to set.
1110      */
1111     public void setDomain(Domain domain)
1112     {
1113         this.domain = domain;
1114     }
1115 
1116     private Platform getPlatform()
1117     {
1118         try
1119         {
1120             return getTable().getDatabase().getPlatform();
1121         }
1122         catch (Exception ex)
1123         {
1124             log.warn("could not load platform implementation");
1125         }
1126         return new PlatformDefaultImpl();
1127     }
1128 
1129     public String getSqlString()
1130     {
1131         List resultList = new ArrayList();
1132         resultList.add(getName());
1133 
1134         String type = getDomain().getSqlType();
1135 
1136         if (getPlatform().hasSize(getDomain().getSqlType()))
1137         {
1138             type += getDomain().printSize();
1139         }
1140 
1141         resultList.add(type);
1142 
1143         if (StringUtils.isNotEmpty(getDomain().getDefaultValue()))
1144         {
1145             resultList.add("default");
1146 
1147             if (TypeMap.isTextType(getDomain().getType()))
1148             {
1149                 // TODO: Properly SQL-escape the text.
1150                 resultList.add(
1151                         new StringBuffer()
1152                         .append('\'')
1153                         .append(getDefaultValue())
1154                         .append('\''));
1155             }
1156             else
1157             {
1158                 resultList.add(getDefaultValue());
1159             }
1160         }
1161         if (getPlatform().createNotNullBeforeAutoincrement())
1162         {
1163             if (StringUtils.isNotEmpty(getNotNullString()))
1164             {
1165                 resultList.add(getNotNullString());
1166             }
1167         }
1168         if (StringUtils.isNotEmpty(getAutoIncrementString()))
1169         {
1170             resultList.add(getAutoIncrementString());
1171         }
1172         if (!getPlatform().createNotNullBeforeAutoincrement())
1173         {
1174             if (StringUtils.isNotEmpty(getNotNullString()))
1175             {
1176                 resultList.add(getNotNullString());
1177             }
1178         }
1179         return StringUtils.join(resultList.iterator(), ' ');
1180     }
1181 
1182     /***
1183      * Return the correctGetters property of the column
1184      *
1185      * @return The currentValue of the correctGetters property.
1186      * @since 3.2
1187      */
1188     public boolean isCorrectGetters()
1189     {
1190         return correctGetters;
1191     }
1192 
1193     /***
1194      * Set the correctGetters property of the column. If set to true, the
1195      * column returns is&lt;xxx&gt; as the getter name which is correct for the
1196      * Bean Specs but incompatible to pre-3.2 releases.
1197      *
1198      * @param correctGetters The new value of the correctGetters property.
1199      * @since 3.2
1200      */
1201     public void setCorrectGetters(boolean correctGetters)
1202     {
1203         this.correctGetters = correctGetters;
1204     }
1205 
1206     /***
1207      * Get the value of the inheritance attribute defined in the schema XML.
1208      *
1209      * @return Returns the inheritanceType.
1210      */
1211     public String getInheritanceType()
1212     {
1213         return inheritanceType;
1214     }
1215 
1216     /***
1217      * Add an XML Specified option key/value pair to this element's option set.
1218      *
1219      * @param key the key of the option.
1220      * @param value the value of the option.
1221      */
1222     public void addOption(String key, String value)
1223     {
1224         options.put( key, value );
1225     }
1226 
1227     /***
1228      * Get the value that was associated with this key in an XML option
1229      * element.
1230      *
1231      * @param key the key of the option.
1232      * @return The value for the key or a null.
1233      */
1234     public String getOption(String key)
1235     {
1236         return (String) options.get(key);
1237     }
1238 
1239     /***
1240      * Gets the full ordered hashtable array of items specified by XML option
1241      * statements under this element.<p>
1242      *
1243      * Note, this is not thread save but since it's only used for
1244      * generation which is single threaded, there should be minimum
1245      * danger using this in Velocity.
1246      *
1247      * @return An Map of all options. Will not be null but may be empty.
1248      */
1249     public Map getOptions()
1250     {
1251         return options;
1252     }
1253 }