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