1   package org.apache.torque.engine.database.model;
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
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  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  public class Column {
49  	private static final SchemaType DEFAULT_TYPE = SchemaType.VARCHAR;
50  	
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  	
67  	
68  	
69  	
70  	private String inheritanceType;
71  	private boolean isInheritance;
72  	private boolean isEnumeratedClasses;
73  	private List inheritanceList;
74  	private boolean needsTransactionInPostgres;
75  	
76  
77  
78  	private int jdbcType;
79  
80  	
81  	private boolean correctGetters = false;
82  
83  	
84  	private String inputValidator = null;
85  	private Map options;
86  
87  	
88  
89  
90  	public Column() {
91  		this(null);
92  	}
93  
94  	
95  
96  
97  
98  
99  
100 	public Column(String name) {
101 		this.name = name;
102 		options = Collections.synchronizedMap(new ListOrderedMap());
103 	}
104 
105 	
106 
107 
108 
109 
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 
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 		
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 		
149 		
150 		javaNamingMethod = attrib.getValue("javaNamingMethod");
151 		if (javaNamingMethod == null) {
152 			javaNamingMethod = parentTable.getDatabase().getDefaultJavaNamingMethod();
153 		}
154 
155 		
156 		String primaryKey = attrib.getValue("primaryKey");
157 		
158 		isPrimaryKey = ("true".equals(primaryKey));
159 
160 		
161 		if ("true".equals(primaryKey)) {
162 			isNotNull = true;
163 		}
164 
165 		
166 		
167 		String notNull = attrib.getValue("required");
168 		isNotNull = (notNull != null && "true".equals(notNull));
169 
170 		
171 		String autoIncrement = attrib.getValue("autoIncrement");
172 		
173 		
174 		
175 		
176 		
177 		isAutoIncrement = ("true".equals(autoIncrement) || (isPrimaryKey() && IDMethod.NATIVE.equals(getTable().getIdMethod())
178 		        && Platform.IDENTITY.equals(getPlatform().getNativeIdMethod()) && (!"false".equals(autoIncrement))));
179 		
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 
196 
197 	public String getFullyQualifiedName() {
198 		return (parentTable.getName() + '.' + name);
199 	}
200 
201 	
202 
203 
204 	public String getName() {
205 		return name;
206 	}
207 
208 	
209 
210 
211 	public void setName(String newName) {
212 		name = newName;
213 	}
214 
215 	
216 
217 
218 	public String getDescription() {
219 		return description;
220 	}
221 
222 	
223 
224 
225 
226 
227 
228 	public void setDescription(String newDescription) {
229 		description = newDescription;
230 	}
231 
232 	
233 
234 
235 
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 
253 
254 
255 
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 
267 
268 
269 
270 
271 	public String getSetterName() {
272 		return "set" + StringUtils.capitalize(getJavaName());
273 	}
274 
275 	
276 
277 
278 	public String getUncapitalisedJavaName() {
279 		return StringUtils.uncapitalize(getJavaName());
280 	}
281 
282 	
283 
284 
285 
286 
287 
288 
289 
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 
301 
302 	public void setJavaName(String javaName) {
303 		this.javaName = javaName;
304 	}
305 
306 	
307 
308 
309 	public String getJavaType() {
310 		return javaType;
311 	}
312 
313 	
314 
315 
316 
317 
318 	public int getPosition() {
319 		return position;
320 	}
321 
322 	
323 
324 
325 
326 
327 
328 	public void setPosition(int v) {
329 		this.position = v;
330 	}
331 
332 	
333 
334 
335 	public void setTable(Table parent) {
336 		parentTable = parent;
337 	}
338 
339 	
340 
341 
342 	public Table getTable() {
343 		return parentTable;
344 	}
345 
346 	
347 
348 
349 	public String getTableName() {
350 		return parentTable.getName();
351 	}
352 
353 	
354 
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 
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 
378 
379 	public List getChildren() {
380 		return inheritanceList;
381 	}
382 
383 	
384 
385 
386 	public boolean isInheritance() {
387 		return isInheritance;
388 	}
389 
390 	
391 
392 
393 	public boolean isEnumeratedClasses() {
394 		return isEnumeratedClasses;
395 	}
396 
397 	
398 
399 
400 	public boolean isNotNull() {
401 		return isNotNull;
402 	}
403 
404 	
405 
406 
407 	public void setNotNull(boolean status) {
408 		isNotNull = status;
409 	}
410 
411 	
412 
413 
414 
415 
416 	public String getNotNullString() {
417 		return getTable().getDatabase().getPlatform().getNullString(this.isNotNull());
418 	}
419 
420 	
421 
422 
423 	public boolean isProtected() {
424 		return isProtected;
425 	}
426 
427 	
428 
429 
430 	public void setProtected(boolean prot) {
431 		isProtected = prot;
432 	}
433 
434 	
435 
436 
437 	public void setPrimaryKey(boolean pk) {
438 		isPrimaryKey = pk;
439 	}
440 
441 	
442 
443 
444 	public boolean isPrimaryKey() {
445 		return isPrimaryKey;
446 	}
447 
448 	
449 
450 
451 	public void setUnique(boolean u) {
452 		isUnique = u;
453 	}
454 
455 	
456 
457 
458 	public boolean isUnique() {
459 		return isUnique;
460 	}
461 
462 	
463 
464 
465 	public boolean requiresTransactionInPostgres() {
466 		return needsTransactionInPostgres;
467 	}
468 
469 	
470 
471 
472 	public boolean isForeignKey() {
473 		return (getForeignKey() != null);
474 	}
475 
476 	
477 
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 		
492 		return false;
493 	}
494 
495 	
496 
497 
498 	public ForeignKey getForeignKey() {
499 		return parentTable.getForeignKey(this.name);
500 	}
501 
502 	
503 
504 
505 	public String getRelatedTableName() {
506 		ForeignKey fk = getForeignKey();
507 		return (fk == null ? null : fk.getForeignTableName());
508 	}
509 
510 	
511 
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 
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 
534 
535 	public List getReferrers() {
536 		if (referrers == null) {
537 			referrers = new ArrayList(5);
538 		}
539 		return referrers;
540 	}
541 
542 	
543 
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 
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 
566 
567 
568 
569 	@Deprecated
570     public Object getType() {
571 		return TypeMap.getJdbcType(domain.getType()).getName();
572 	}
573 
574 	
575 
576 
577 	public Object getTorqueType() {
578 		return domain.getType().getName();
579 	}
580 
581 	
582 
583 
584 
585 
586 	@Deprecated
587     public boolean isString() {
588 		return (domain.getType().getName().indexOf("CHAR") != -1);
589 	}
590 
591 	
592 
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 
603 
604 
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 		
644 		result.append(" />\n");
645 
646 		return result.toString();
647 	}
648 
649 	
650 
651 
652 	public String getSize() {
653 		return domain.getSize();
654 	}
655 
656 	
657 
658 
659 	public void setSize(String newSize) {
660 		domain.setSize(newSize);
661 	}
662 
663 	
664 
665 
666 
667 
668 
669 
670 
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 
692 
693 
694 
695 
696 
697 
698 
699 	public String getScale() {
700 		String scale = domain.getScale();
701 		
702 		if (scale == null) {
703 			scale = getSize();
704 			if (scale == null) 
705 			{
706 				return scale;
707 			}
708 			int cLoc = scale.indexOf(',');
709 			if (cLoc < 0) 
710 			{
711 				return null;
712 			}
713 			scale = scale.substring(cLoc + 1);
714 		}
715 
716 		
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 
728 
729 	public void setScale(String newScale) {
730 		domain.setScale(newScale);
731 	}
732 
733 	
734 
735 
736 
737 
738 	public String printSize() {
739 		return domain.printSize();
740 	}
741 
742 	
743 
744 
745 
746 
747 	@Deprecated
748     public String getDefaultSetting() {
749 		return domain.getDefaultSetting();
750 	}
751 
752 	
753 
754 
755 	public void setDefaultValue(String def) {
756 		domain.setDefaultValue(def);
757 	}
758 
759 	
760 
761 
762 	public String getDefaultValue() {
763 		return domain.getDefaultValue();
764 	}
765 
766 	
767 
768 
769 	public String getInputValidator() {
770 		return this.inputValidator;
771 	}
772 
773 	
774 
775 
776 	public boolean isAutoIncrement() {
777 		return isAutoIncrement;
778 	}
779 
780 	
781 
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 
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 
824 
825 
826 	public String getJavaObject() {
827 		return TypeMap.getJavaObject(domain.getType());
828 	}
829 
830 	
831 
832 
833 
834 
835 	public String getJavaPrimitive() {
836 		return TypeMap.getJavaNative(domain.getType());
837 	}
838 
839 	
840 
841 
842 
843 
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 
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 
868 
869 	public String getParameterParserMethod() {
870 		return TypeMap.getPPMethod(domain.getType());
871 	}
872 
873 	
874 
875 
876 	public boolean isBooleanInt() {
877 		return TypeMap.isBooleanInt(domain.getType());
878 	}
879 
880 	
881 
882 
883 	public boolean isBooleanChar() {
884 		return TypeMap.isBooleanChar(domain.getType());
885 	}
886 
887 	
888 
889 
890 	public boolean isBit() {
891 		return TypeMap.isBit(domain.getType());
892 	}
893 
894 	
895 
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 
909 
910 	public Domain getDomain() {
911 		return domain;
912 	}
913 
914 	
915 
916 
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 				
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 
972 
973 
974 
975 
976 	public boolean isCorrectGetters() {
977 		return correctGetters;
978 	}
979 
980 	
981 
982 
983 
984 
985 
986 
987 
988 	public void setCorrectGetters(boolean correctGetters) {
989 		this.correctGetters = correctGetters;
990 	}
991 
992 	
993 
994 
995 
996 
997 	public String getInheritanceType() {
998 		return inheritanceType;
999 	}
1000 
1001 	
1002 
1003 
1004 
1005 
1006 
1007 
1008 
1009 	public void addOption(String key, String value) {
1010 		options.put(key, value);
1011 	}
1012 
1013 	
1014 
1015 
1016 
1017 
1018 
1019 
1020 	public String getOption(String key) {
1021 		return (String) options.get(key);
1022 	}
1023 
1024 	
1025 
1026 
1027 
1028 
1029 
1030 
1031 
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 }