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