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.apache.torque.engine.platform.PlatformDefaultImpl;
35  import org.xml.sax.Attributes;
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  public class Column {
50  	private static final SchemaType DEFAULT_TYPE = SchemaType.VARCHAR;
51  	
52  	private static Log log = LogFactory.getLog(Column.class);
53  	private String name;
54  	private String description;
55  	private Domain domain = new Domain();
56  	private String javaName = null;
57  	private String javaNamingMethod;
58  	private boolean isNotNull = false;
59  	private boolean isProtected = false;
60  	private String javaType;
61  	private Table parentTable;
62  	private int position;
63  	private boolean isPrimaryKey = false;
64  	private boolean isUnique = false;
65  	private boolean isAutoIncrement = false;
66  	private List referrers;
67  	
68  	
69  	
70  	
71  	private String inheritanceType;
72  	private boolean isInheritance;
73  	private boolean isEnumeratedClasses;
74  	private List inheritanceList;
75  	private boolean needsTransactionInPostgres;
76  	
77  
78  
79  	private int jdbcType;
80  
81  	
82  	private boolean correctGetters = false;
83  
84  	
85  	private String inputValidator = null;
86  	private Map options;
87  
88  	
89  
90  
91  	public Column() {
92  		this(null);
93  	}
94  
95  	
96  
97  
98  
99  
100 
101 	public Column(String name) {
102 		this.name = name;
103 		options = Collections.synchronizedMap(new ListOrderedMap());
104 	}
105 
106 	
107 
108 
109 
110 
111 
112 
113 	public static String makeList(List columns) {
114 		Object obj = columns.get(0);
115 		boolean isColumnList = (obj instanceof Column);
116 		if (isColumnList) {
117 			obj = ((Column) obj).getName();
118 		}
119 		StringBuffer buf = new StringBuffer((String) obj);
120 		for (int i = 1; i < columns.size(); i++) {
121 			obj = columns.get(i);
122 			if (isColumnList) {
123 				obj = ((Column) obj).getName();
124 			}
125 			buf.append(", ").append(obj);
126 		}
127 		return buf.toString();
128 	}
129 
130 	
131 
132 
133 	public void loadFromXML(Attributes attrib) {
134 		String dom = attrib.getValue("domain");
135 		if (StringUtils.isNotEmpty(dom)) {
136 			domain = new Domain(getTable().getDatabase().getDomain(dom));
137 		} else {
138 			domain = new Domain(getPlatform().getDomainForSchemaType(DEFAULT_TYPE));
139 			setType(attrib.getValue("type"));
140 		}
141 		
142 		name = attrib.getValue("name");
143 
144 		javaName = attrib.getValue("javaName");
145 		javaType = attrib.getValue("javaType");
146 		if (javaType != null && javaType.length() == 0) {
147 			javaType = null;
148 		}
149 
150 		
151 		
152 		javaNamingMethod = attrib.getValue("javaNamingMethod");
153 		if (javaNamingMethod == null) {
154 			javaNamingMethod = parentTable.getDatabase().getDefaultJavaNamingMethod();
155 		}
156 
157 		
158 		String primaryKey = attrib.getValue("primaryKey");
159 		
160 		isPrimaryKey = ("true".equals(primaryKey));
161 
162 		
163 		if ("true".equals(primaryKey)) {
164 			isNotNull = true;
165 		}
166 
167 		
168 		
169 		String notNull = attrib.getValue("required");
170 		isNotNull = (notNull != null && "true".equals(notNull));
171 
172 		
173 		String autoIncrement = attrib.getValue("autoIncrement");
174 		
175 		
176 		
177 		
178 		
179 		isAutoIncrement = ("true".equals(autoIncrement) || (isPrimaryKey() && IDMethod.NATIVE.equals(getTable().getIdMethod()) && Platform.IDENTITY.equals(getPlatform().getNativeIdMethod()) && (!"false".equals(autoIncrement))));
180 		
181 		domain.replaceDefaultValue(attrib.getValue("default"));
182 
183 		domain.replaceSize(attrib.getValue("size"));
184 		domain.replaceScale(attrib.getValue("scale"));
185 
186 		inheritanceType = attrib.getValue("inheritance");
187 		isInheritance = (inheritanceType != null && !inheritanceType.equals("false"));
188 
189 		this.inputValidator = attrib.getValue("inputValidator");
190 		description = attrib.getValue("description");
191 
192 		isProtected = ("true".equals(attrib.getValue("protected")));
193 	}
194 
195 	
196 
197 
198 	public String getFullyQualifiedName() {
199 		return (parentTable.getName() + '.' + name);
200 	}
201 
202 	
203 
204 
205 	public String getName() {
206 		return name;
207 	}
208 
209 	
210 
211 
212 	public void setName(String newName) {
213 		name = newName;
214 	}
215 
216 	
217 
218 
219 	public String getDescription() {
220 		return description;
221 	}
222 
223 	
224 
225 
226 
227 
228 
229 	public void setDescription(String newDescription) {
230 		description = newDescription;
231 	}
232 
233 	
234 
235 
236 
237 
238 	public String getJavaName() {
239 		if (javaName == null) {
240 			List inputs = new ArrayList(2);
241 			inputs.add(name);
242 			inputs.add(javaNamingMethod);
243 			try {
244 				javaName = NameFactory.generateName(NameFactory.JAVA_GENERATOR, inputs);
245 			} catch (EngineException e) {
246 				log.error(e, e);
247 			}
248 		}
249 		return StringUtils.capitalize(javaName);
250 	}
251 
252 	
253 
254 
255 
256 
257 
258 	public String getGetterName() {
259 		if (("boolean".equalsIgnoreCase(getJavaNative()) && isCorrectGetters())) {
260 			return "is" + StringUtils.capitalize(getJavaName());
261 		} else {
262 			return "get" + StringUtils.capitalize(getJavaName());
263 		}
264 	}
265 
266 	
267 
268 
269 
270 
271 
272 	public String getSetterName() {
273 		return "set" + StringUtils.capitalize(getJavaName());
274 	}
275 
276 	
277 
278 
279 	public String getUncapitalisedJavaName() {
280 		return StringUtils.uncapitalize(getJavaName());
281 	}
282 
283 	
284 
285 
286 
287 
288 
289 
290 
291 
292 	public String getPeerJavaName() {
293 		String peerName = name.toUpperCase();
294 		if (peerName.equals("TABLE_NAME") || peerName.equals("DATABASE_NAME")) {
295 			peerName = "_" + peerName;
296 		}
297 		return peerName;
298 	}
299 
300 	
301 
302 
303 	public void setJavaName(String javaName) {
304 		this.javaName = javaName;
305 	}
306 
307 	
308 
309 
310 	public String getJavaType() {
311 		return javaType;
312 	}
313 
314 	
315 
316 
317 
318 
319 	public int getPosition() {
320 		return position;
321 	}
322 
323 	
324 
325 
326 
327 
328 
329 	public void setPosition(int v) {
330 		this.position = v;
331 	}
332 
333 	
334 
335 
336 	public void setTable(Table parent) {
337 		parentTable = parent;
338 	}
339 
340 	
341 
342 
343 	public Table getTable() {
344 		return parentTable;
345 	}
346 
347 	
348 
349 
350 	public String getTableName() {
351 		return parentTable.getName();
352 	}
353 
354 	
355 
356 
357 	public Inheritance addInheritance(Attributes attrib) {
358 		Inheritance inh = new Inheritance();
359 		inh.loadFromXML(attrib);
360 		addInheritance(inh);
361 
362 		return inh;
363 	}
364 
365 	
366 
367 
368 
369 	public void addInheritance(Inheritance inh) {
370 		inh.setColumn(this);
371 		if (inheritanceList == null) {
372 			inheritanceList = new ArrayList();
373 			isEnumeratedClasses = true;
374 		}
375 		inheritanceList.add(inh);
376 	}
377 
378 	
379 
380 
381 	public List getChildren() {
382 		return inheritanceList;
383 	}
384 
385 	
386 
387 
388 
389 	public boolean isInheritance() {
390 		return isInheritance;
391 	}
392 
393 	
394 
395 
396 	public boolean isEnumeratedClasses() {
397 		return isEnumeratedClasses;
398 	}
399 
400 	
401 
402 
403 	public boolean isNotNull() {
404 		return isNotNull;
405 	}
406 
407 	
408 
409 
410 	public void setNotNull(boolean status) {
411 		isNotNull = status;
412 	}
413 
414 	
415 
416 
417 
418 
419 	public String getNotNullString() {
420 		return getTable().getDatabase().getPlatform().getNullString(this.isNotNull());
421 	}
422 
423 	
424 
425 
426 	public boolean isProtected() {
427 		return isProtected;
428 	}
429 
430 	
431 
432 
433 	public void setProtected(boolean prot) {
434 		isProtected = prot;
435 	}
436 
437 	
438 
439 
440 	public void setPrimaryKey(boolean pk) {
441 		isPrimaryKey = pk;
442 	}
443 
444 	
445 
446 
447 	public boolean isPrimaryKey() {
448 		return isPrimaryKey;
449 	}
450 
451 	
452 
453 
454 	public void setUnique(boolean u) {
455 		isUnique = u;
456 	}
457 
458 	
459 
460 
461 	public boolean isUnique() {
462 		return isUnique;
463 	}
464 
465 	
466 
467 
468 	public boolean requiresTransactionInPostgres() {
469 		return needsTransactionInPostgres;
470 	}
471 
472 	
473 
474 
475 	public boolean isForeignKey() {
476 		return (getForeignKey() != null);
477 	}
478 
479 	
480 
481 
482 
483 	public boolean isMultipleFK() {
484 		ForeignKey fk = getForeignKey();
485 		if (fk != null) {
486 			Iterator fks = parentTable.getForeignKeys().iterator();
487 			while (fks.hasNext()) {
488 				ForeignKey key = (ForeignKey) fks.next();
489 				if (key.getForeignTableName().equals(fk.getForeignTableName()) && !key.getLocalColumns().contains(this.name)) {
490 					return true;
491 				}
492 			}
493 		}
494 
495 		
496 		return false;
497 	}
498 
499 	
500 
501 
502 	public ForeignKey getForeignKey() {
503 		return parentTable.getForeignKey(this.name);
504 	}
505 
506 	
507 
508 
509 	public String getRelatedTableName() {
510 		ForeignKey fk = getForeignKey();
511 		return (fk == null ? null : fk.getForeignTableName());
512 	}
513 
514 	
515 
516 
517 
518 	public String getRelatedColumnName() {
519 		ForeignKey fk = getForeignKey();
520 		if (fk == null) {
521 			return null;
522 		} else {
523 			return fk.getLocalForeignMapping().get(this.name).toString();
524 		}
525 	}
526 
527 	
528 
529 
530 	public void addReferrer(ForeignKey fk) {
531 		if (referrers == null) {
532 			referrers = new ArrayList(5);
533 		}
534 		referrers.add(fk);
535 	}
536 
537 	
538 
539 
540 	public List getReferrers() {
541 		if (referrers == null) {
542 			referrers = new ArrayList(5);
543 		}
544 		return referrers;
545 	}
546 
547 	
548 
549 
550 	public void setType(String torqueType) {
551 		SchemaType type = SchemaType.getEnum(torqueType);
552 		if (type == null) {
553 			log.warn("SchemaType " + torqueType + " does not exist");
554 			type = Column.DEFAULT_TYPE;
555 		}
556 		setType(type);
557 	}
558 
559 	
560 
561 
562 	public void setType(SchemaType torqueType) {
563 		domain = new Domain(getPlatform().getDomainForSchemaType(torqueType));
564 		if (torqueType.equals(SchemaType.VARBINARY) || torqueType.equals(SchemaType.BLOB)) {
565 			needsTransactionInPostgres = true;
566 		}
567 	}
568 
569 	
570 
571 
572 
573 
574 	public Object getType() {
575 		return TypeMap.getJdbcType(domain.getType()).getName();
576 	}
577 
578 	
579 
580 
581 	public Object getTorqueType() {
582 		return domain.getType().getName();
583 	}
584 
585 	
586 
587 
588 
589 
590 	public boolean isString() {
591 		return (domain.getType().getName().indexOf("CHAR") != -1);
592 	}
593 
594 	
595 
596 
597 
598 	public boolean needEscapedValue() {
599 		String torqueType = domain.getType().getName();
600 		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 
605 
606 
607 
608 	public String toString() {
609 		StringBuffer result = new StringBuffer();
610 		result.append("    <column name=\"").append(name).append('"');
611 
612 		if (javaName != null) {
613 			result.append(" javaName=\"").append(javaName).append('"');
614 		}
615 
616 		if (isPrimaryKey) {
617 			result.append(" primaryKey=\"").append(isPrimaryKey).append('"');
618 		}
619 
620 		if (isNotNull) {
621 			result.append(" required=\"true\"");
622 		} else {
623 			result.append(" required=\"false\"");
624 		}
625 
626 		result.append(" type=\"").append(domain.getType().getName()).append('"');
627 
628 		if (domain.getSize() != null) {
629 			result.append(" size=\"").append(domain.getSize()).append('"');
630 		}
631 
632 		if (domain.getScale() != null) {
633 			result.append(" scale=\"").append(domain.getScale()).append('"');
634 		}
635 
636 		if (domain.getDefaultValue() != null) {
637 			result.append(" default=\"").append(domain.getDefaultValue()).append('"');
638 		}
639 
640 		if (isInheritance()) {
641 			result.append(" inheritance=\"").append(inheritanceType).append('"');
642 		}
643 
644 		
645 		result.append(" />\n");
646 
647 		return result.toString();
648 	}
649 
650 	
651 
652 
653 	public String getSize() {
654 		return domain.getSize();
655 	}
656 
657 	
658 
659 
660 	public void setSize(String newSize) {
661 		domain.setSize(newSize);
662 	}
663 
664 	
665 
666 
667 
668 
669 
670 
671 
672 
673 	public String getPrecision() {
674 		String size = getSize();
675 		if (size == null) {
676 			return size;
677 		}
678 		int cLoc = size.indexOf(',');
679 		if (cLoc > 0) {
680 			size = size.substring(0, cLoc);
681 		}
682 		try {
683 			Integer.parseInt(size);
684 		} catch (NumberFormatException e) {
685 			log.warn("getPrecision(): Size attribute found (" + getSize() + ") was not an integer number, using default of null!");
686 			size = null;
687 		}
688 		return size;
689 	}
690 
691 	
692 
693 
694 
695 
696 
697 
698 
699 
700 	public String getScale() {
701 		String scale = domain.getScale();
702 		
703 		if (scale == null) {
704 			scale = getSize();
705 			if (scale == null) 
706 			{
707 				return scale;
708 			}
709 			int cLoc = scale.indexOf(',');
710 			if (cLoc < 0) 
711 			{
712 				return null;
713 			}
714 			scale = scale.substring(cLoc + 1);
715 		}
716 
717 		
718 		try {
719 			Integer.parseInt(scale);
720 		} catch (NumberFormatException e) {
721 			log.warn("getScale(): Scale (or size=\"p,s\") attribute found (" + scale + ") was not an integer number, using default of null.");
722 			scale = null;
723 		}
724 		return scale;
725 	}
726 
727 	
728 
729 
730 	public void setScale(String newScale) {
731 		domain.setScale(newScale);
732 	}
733 
734 	
735 
736 
737 
738 
739 	public String printSize() {
740 		return domain.printSize();
741 	}
742 
743 	
744 
745 
746 
747 
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 
777 	public boolean isAutoIncrement() {
778 		return isAutoIncrement;
779 	}
780 
781 	
782 
783 
784 	public void setAutoIncrement(boolean value) {
785 		isAutoIncrement = value;
786 	}
787 
788 	public String getAutoIncrementString() {
789 		if (isAutoIncrement() && IDMethod.NATIVE.equals(getTable().getIdMethod())) {
790 			return getPlatform().getAutoIncrement();
791 		}
792 		return "";
793 	}
794 
795 	
796 
797 
798 	public void setTypeFromString(String typeName, String size) {
799 		String tn = typeName.toUpperCase();
800 		setType(tn);
801 
802 		if (size != null) {
803 			domain.setSize(size);
804 		}
805 
806 		if (tn.indexOf("CHAR") != -1) {
807 			domain.setType(SchemaType.VARCHAR);
808 		} else if (tn.indexOf("INT") != -1) {
809 			domain.setType(SchemaType.INTEGER);
810 		} else if (tn.indexOf("FLOAT") != -1) {
811 			domain.setType(SchemaType.FLOAT);
812 		} else if (tn.indexOf("DATE") != -1) {
813 			domain.setType(SchemaType.DATE);
814 		} else if (tn.indexOf("TIME") != -1) {
815 			domain.setType(SchemaType.TIMESTAMP);
816 		} else if (tn.indexOf("BINARY") != -1) {
817 			domain.setType(SchemaType.LONGVARBINARY);
818 		} else {
819 			domain.setType(SchemaType.VARCHAR);
820 		}
821 	}
822 
823 	
824 
825 
826 
827 	public String getJavaObject() {
828 		return TypeMap.getJavaObject(domain.getType());
829 	}
830 
831 	
832 
833 
834 
835 
836 	public String getJavaPrimitive() {
837 		return TypeMap.getJavaNative(domain.getType());
838 	}
839 
840 	
841 
842 
843 
844 
845 
846 
847 	public String getJavaNative() {
848 		String jtype = TypeMap.getJavaNativeObject(domain.getType());
849 		if (isUsePrimitive()) {
850 			jtype = TypeMap.getJavaNative(domain.getType());
851 		}
852 
853 		return jtype;
854 	}
855 
856 	
857 
858 
859 	public String getVillageMethod() {
860 		String vmethod = TypeMap.getVillageObjectMethod(domain.getType());
861 		if (isUsePrimitive()) {
862 			vmethod = TypeMap.getVillageMethod(domain.getType());
863 		}
864 
865 		return vmethod;
866 	}
867 
868 	
869 
870 
871 	public String getParameterParserMethod() {
872 		return TypeMap.getPPMethod(domain.getType());
873 	}
874 
875 	
876 
877 
878 	public boolean isBooleanInt() {
879 		return TypeMap.isBooleanInt(domain.getType());
880 	}
881 
882 	
883 
884 
885 	public boolean isBooleanChar() {
886 		return TypeMap.isBooleanChar(domain.getType());
887 	}
888 
889 	
890 
891 
892 	public boolean isBit() {
893 		return TypeMap.isBit(domain.getType());
894 	}
895 
896 	
897 
898 
899 	public boolean isPrimitive() {
900 		String t = getJavaNative();
901 		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 		String s = getJavaType();
906 		return (s != null && s.equals("primitive")) || (s == null && !"object".equals(getTable().getDatabase().getDefaultJavaType()));
907 	}
908 
909 	
910 
911 
912 	public Domain getDomain() {
913 		return domain;
914 	}
915 
916 	
917 
918 
919 
920 	public void setDomain(Domain domain) {
921 		this.domain = domain;
922 	}
923 
924 	private Platform getPlatform() {
925 		try {
926 			return getTable().getDatabase().getPlatform();
927 		} catch (Exception ex) {
928 			log.warn("could not load platform implementation");
929 		}
930 		return new PlatformDefaultImpl();
931 	}
932 
933 	public String getSqlString() {
934 		List resultList = new ArrayList();
935 		resultList.add(getName());
936 
937 		String type = getDomain().getSqlType();
938 
939 		if (getPlatform().hasSize(getDomain().getSqlType())) {
940 			type += getDomain().printSize();
941 		}
942 
943 		resultList.add(type);
944 
945 		String defaultStr = getPlatform().filterInvalidDefaultValues(getDomain().getDefaultValue());
946 		if (StringUtils.isNotEmpty(defaultStr)) {
947 
948 			resultList.add("default");
949 
950 			if (TypeMap.isTextType(getDomain().getType()) && !getPlatform().isSpecialDefault(defaultStr)) {
951 				
952 				resultList.add(new StringBuffer().append('\'').append(getDefaultValue()).append('\''));
953 			} else {
954 				resultList.add(getDefaultValue());
955 			}
956 		}
957 		if (getPlatform().createNotNullBeforeAutoincrement()) {
958 			if (StringUtils.isNotEmpty(getNotNullString())) {
959 				resultList.add(getNotNullString());
960 			}
961 		}
962 		if (StringUtils.isNotEmpty(getAutoIncrementString())) {
963 			resultList.add(getAutoIncrementString());
964 		}
965 		if (!getPlatform().createNotNullBeforeAutoincrement()) {
966 			if (StringUtils.isNotEmpty(getNotNullString())) {
967 				resultList.add(getNotNullString());
968 			}
969 		}
970 		return StringUtils.join(resultList.iterator(), ' ');
971 	}
972 
973 	
974 
975 
976 
977 
978 
979 	public boolean isCorrectGetters() {
980 		return correctGetters;
981 	}
982 
983 	
984 
985 
986 
987 
988 
989 
990 
991 	public void setCorrectGetters(boolean correctGetters) {
992 		this.correctGetters = correctGetters;
993 	}
994 
995 	
996 
997 
998 
999 
1000 	public String getInheritanceType() {
1001 		return inheritanceType;
1002 	}
1003 
1004 	
1005 
1006 
1007 
1008 
1009 
1010 
1011 
1012 	public void addOption(String key, String value) {
1013 		options.put(key, value);
1014 	}
1015 
1016 	
1017 
1018 
1019 
1020 
1021 
1022 
1023 	public String getOption(String key) {
1024 		return (String) options.get(key);
1025 	}
1026 
1027 	
1028 
1029 
1030 
1031 
1032 
1033 
1034 
1035 
1036 	public Map getOptions() {
1037 		return options;
1038 	}
1039 
1040 	public int getJdbcType() {
1041 		return jdbcType;
1042 	}
1043 
1044 	public void setJdbcType(int jdbcType) {
1045 		this.jdbcType = jdbcType;
1046 	}
1047 }