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.Hashtable;
25  import java.util.Iterator;
26  import java.util.List;
27  import java.util.Map;
28  import org.apache.commons.collections.map.ListOrderedMap;
29  import org.apache.commons.lang.StringUtils;
30  
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  
34  import org.apache.torque.engine.EngineException;
35  
36  import org.xml.sax.Attributes;
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  public class Table implements IDMethod {
51  	
52  	private static Log log = LogFactory.getLog(Table.class);
53  
54  	
55  	private List columnList;
56  	private List foreignKeys;
57  	private List indices;
58  	private List unices;
59  	private List idMethodParameters;
60  	private String name;
61  	private String description;
62  	private String javaName;
63  	private String idMethod;
64  	private String javaNamingMethod;
65  	private Database tableParent;
66  	private List referrers;
67  	private List foreignTableNames;
68  	private boolean containsForeignPK;
69  	private Column inheritanceColumn;
70  	private boolean skipSql;
71  	private boolean abstractValue;
72  	private String alias;
73  	private String enterface;
74  	private String pkg;
75  	private String baseClass;
76  	private String basePeer;
77  	private Hashtable columnsByName;
78  	private Hashtable columnsByJavaName;
79  	private boolean needsTransactionInPostgres;
80  	private boolean heavyIndexing;
81  	private boolean forReferenceOnly;
82  	private Map options;
83  
84  	
85  
86  
87  	public Table() {
88  		this(null);
89  	}
90  
91  	
92  
93  
94  
95  
96  
97  	public Table(String name) {
98  		this.name = name;
99  		columnList = new ArrayList();
100 		foreignKeys = new ArrayList(5);
101 		indices = new ArrayList(5);
102 		unices = new ArrayList(5);
103 		columnsByName = new Hashtable();
104 		columnsByJavaName = new Hashtable();
105 		options = Collections.synchronizedMap(new ListOrderedMap());
106 	}
107 
108 	
109 
110 
111 
112 
113 
114 
115 
116 	public void loadFromXML(Attributes attrib, String defaultIdMethod) {
117 		name = attrib.getValue("name");
118 		javaName = attrib.getValue("javaName");
119 		idMethod = attrib.getValue("idMethod");
120 
121 		
122 		
123 		javaNamingMethod = attrib.getValue("javaNamingMethod");
124 		if (javaNamingMethod == null) {
125 			javaNamingMethod = getDatabase().getDefaultJavaNamingMethod();
126 		}
127 
128 		if ("null".equals(idMethod)) {
129 			idMethod = defaultIdMethod;
130 		}
131 		skipSql = "true".equals(attrib.getValue("skipSql"));
132 		
133 		abstractValue = "true".equals(attrib.getValue("abstract"));
134 		baseClass = attrib.getValue("baseClass");
135 		basePeer = attrib.getValue("basePeer");
136 		alias = attrib.getValue("alias");
137 		heavyIndexing = "true".equals(attrib.getValue("heavyIndexing")) || (!"false".equals(attrib.getValue("heavyIndexing")) && getDatabase().isHeavyIndexing());
138 		description = attrib.getValue("description");
139 		enterface = attrib.getValue("interface");
140 	}
141 
142 	
143 
144 
145 
146 
147 
148 
149 
150 
151 
152 	public void doFinalInitialization() {
153 		
154 		
155 		if (heavyIndexing) {
156 			doHeavyIndexing();
157 		}
158 
159 		
160 		
161 		doNaming();
162 	}
163 
164 	
165 
166 
167 
168 
169 
170 
171 
172 
173 
174 
175 
176 
177 
178 
179 
180 
181 
182 	private void doHeavyIndexing() {
183 		if (log.isDebugEnabled()) {
184 			log.debug("doHeavyIndex() called on table " + name);
185 		}
186 
187 		List pk = getPrimaryKey();
188 		int size = pk.size();
189 
190 		try {
191 			
192 			
193 			
194 			for (int i = 1; i < size; i++) {
195 				addIndex(new Index(this, pk.subList(i, size)));
196 			}
197 		} catch (EngineException e) {
198 			log.error(e, e);
199 		}
200 	}
201 
202 	
203 
204 
205 	private void doNaming() {
206 		int i;
207 		int size;
208 		String name;
209 
210 		
211 		try {
212 			for (i = 0, size = foreignKeys.size(); i < size; i++) {
213 				ForeignKey fk = (ForeignKey) foreignKeys.get(i);
214 				name = fk.getName();
215 				if (StringUtils.isEmpty(name)) {
216 					name = acquireConstraintName("FK", i + 1);
217 					fk.setName(name);
218 				}
219 			}
220 
221 			for (i = 0, size = indices.size(); i < size; i++) {
222 				Index index = (Index) indices.get(i);
223 				name = index.getName();
224 				if (StringUtils.isEmpty(name)) {
225 					name = acquireConstraintName("I", i + 1);
226 					index.setName(name);
227 				}
228 			}
229 
230 			for (i = 0, size = unices.size(); i < size; i++) {
231 				Unique unique = (Unique) unices.get(i);
232 				name = unique.getName();
233 				if (StringUtils.isEmpty(name)) {
234 					name = acquireConstraintName("U", i + 1);
235 					unique.setName(name);
236 				}
237 			}
238 		} catch (EngineException nameAlreadyInUse) {
239 			log.error(nameAlreadyInUse, nameAlreadyInUse);
240 		}
241 	}
242 
243 	
244 
245 
246 
247 
248 
249 
250 
251 
252 
253 	private final String acquireConstraintName(String nameType, int nbr) throws EngineException {
254 		List inputs = new ArrayList(4);
255 		inputs.add(getDatabase());
256 		inputs.add(getName());
257 		inputs.add(nameType);
258 		inputs.add(new Integer(nbr));
259 		return NameFactory.generateName(NameFactory.CONSTRAINT_GENERATOR, inputs);
260 	}
261 
262 	
263 
264 
265 
266 
267 	public String getBaseClass() {
268 		if (isAlias() && baseClass == null) {
269 			return alias;
270 		} else if (baseClass == null) {
271 			return getDatabase().getBaseClass();
272 		} else {
273 			return baseClass;
274 		}
275 	}
276 
277 	
278 
279 
280 
281 
282 
283 	public void setBaseClass(String v) {
284 		this.baseClass = v;
285 	}
286 
287 	
288 
289 
290 
291 
292 	public String getBasePeer() {
293 		if (isAlias() && basePeer == null) {
294 			return alias + "Peer";
295 		} else if (basePeer == null) {
296 			return getDatabase().getBasePeer();
297 		} else {
298 			return basePeer;
299 		}
300 	}
301 
302 	
303 
304 
305 
306 
307 
308 	public void setBasePeer(String v) {
309 		this.basePeer = v;
310 	}
311 
312 	
313 
314 
315 
316 
317 
318 
319 	public Column addColumn(Attributes attrib) {
320 		Column col = new Column();
321 		col.setTable(this);
322 		col.setCorrectGetters(false);
323 		col.loadFromXML(attrib);
324 		addColumn(col);
325 		return col;
326 	}
327 
328 	
329 
330 
331 
332 
333 
334 	public void addColumn(Column col) {
335 		col.setTable(this);
336 		if (col.isInheritance()) {
337 			inheritanceColumn = col;
338 		}
339 		columnList.add(col);
340 		columnsByName.put(col.getName(), col);
341 		columnsByJavaName.put(col.getJavaName(), col);
342 		col.setPosition(columnList.size());
343 		needsTransactionInPostgres |= col.requiresTransactionInPostgres();
344 	}
345 
346 	
347 
348 
349 
350 
351 
352 
353 	public ForeignKey addForeignKey(Attributes attrib) {
354 		ForeignKey fk = new ForeignKey();
355 		fk.loadFromXML(attrib);
356 		addForeignKey(fk);
357 		return fk;
358 	}
359 
360 	
361 
362 
363 	public Column getChildrenColumn() {
364 		return inheritanceColumn;
365 	}
366 
367 	
368 
369 
370 	public List getChildrenNames() {
371 		if (inheritanceColumn == null || !inheritanceColumn.isEnumeratedClasses()) {
372 			return null;
373 		}
374 		List children = inheritanceColumn.getChildren();
375 		List names = new ArrayList(children.size());
376 		for (int i = 0; i < children.size(); i++) {
377 			names.add(((Inheritance) children.get(i)).getClassName());
378 		}
379 		return names;
380 	}
381 
382 	
383 
384 
385 
386 
387 
388 	public void addReferrer(ForeignKey fk) {
389 		if (referrers == null) {
390 			referrers = new ArrayList(5);
391 		}
392 		referrers.add(fk);
393 	}
394 
395 	
396 
397 
398 
399 
400 	public List getReferrers() {
401 		return referrers;
402 	}
403 
404 	
405 
406 
407 
408 
409 	public void setContainsForeignPK(boolean b) {
410 		containsForeignPK = b;
411 	}
412 
413 	
414 
415 
416 	public boolean getContainsForeignPK() {
417 		return containsForeignPK;
418 	}
419 
420 	
421 
422 
423 
424 
425 	public List getForeignTableNames() {
426 		if (foreignTableNames == null) {
427 			foreignTableNames = new ArrayList(1);
428 		}
429 		return foreignTableNames;
430 	}
431 
432 	
433 
434 
435 
436 
437 
438 	public void addForeignKey(ForeignKey fk) {
439 		fk.setTable(this);
440 		foreignKeys.add(fk);
441 
442 		if (foreignTableNames == null) {
443 			foreignTableNames = new ArrayList(5);
444 		}
445 		if (!foreignTableNames.contains(fk.getForeignTableName())) {
446 			foreignTableNames.add(fk.getForeignTableName());
447 		}
448 	}
449 
450 	
451 
452 
453 	public boolean requiresTransactionInPostgres() {
454 		return needsTransactionInPostgres;
455 	}
456 
457 	
458 
459 
460 	public IdMethodParameter addIdMethodParameter(Attributes attrib) {
461 		IdMethodParameter imp = new IdMethodParameter();
462 		imp.loadFromXML(attrib);
463 		addIdMethodParameter(imp);
464 		return imp;
465 	}
466 
467 	
468 
469 
470 
471 
472 
473 
474 	public void addIdMethodParameter(IdMethodParameter imp) {
475 		imp.setTable(this);
476 		if (idMethodParameters == null) {
477 			idMethodParameters = new ArrayList(2);
478 		}
479 		idMethodParameters.add(imp);
480 	}
481 
482 	
483 
484 
485 	public void addIndex(Index index) {
486 		index.setTable(this);
487 		indices.add(index);
488 	}
489 
490 	
491 
492 
493 	public Index addIndex(Attributes attrib) {
494 		Index index = new Index();
495 		index.loadFromXML(attrib);
496 		addIndex(index);
497 		return index;
498 	}
499 
500 	
501 
502 
503 	public void addUnique(Unique unique) {
504 		unique.setTable(this);
505 		unices.add(unique);
506 	}
507 
508 	
509 
510 
511 
512 
513 
514 	public Unique addUnique(Attributes attrib) {
515 		Unique unique = new Unique();
516 		unique.loadFromXML(attrib);
517 		addUnique(unique);
518 		return unique;
519 	}
520 
521 	
522 
523 
524 	public String getName() {
525 		return name;
526 	}
527 
528 	
529 
530 
531 	public void setName(String newName) {
532 		name = newName;
533 	}
534 
535 	
536 
537 
538 	public String getDescription() {
539 		return description;
540 	}
541 
542 	
543 
544 
545 
546 
547 
548 	public void setDescription(String newDescription) {
549 		description = newDescription;
550 	}
551 
552 	
553 
554 
555 	public String getJavaName() {
556 		if (javaName == null) {
557 			List inputs = new ArrayList(2);
558 			inputs.add(name);
559 			inputs.add(javaNamingMethod);
560 			try {
561 				javaName = NameFactory.generateName(NameFactory.JAVA_GENERATOR, inputs);
562 			} catch (EngineException e) {
563 				log.error(e, e);
564 			}
565 		}
566 		return javaName;
567 	}
568 
569 	
570 
571 
572 	public void setJavaName(String javaName) {
573 		this.javaName = javaName;
574 	}
575 
576 	
577 
578 
579 	public String getIdMethod() {
580 		if (idMethod == null) {
581 			return IDMethod.NO_ID_METHOD;
582 		} else {
583 			return idMethod;
584 		}
585 	}
586 
587 	
588 
589 
590 	public void setIdMethod(String idMethod) {
591 		this.idMethod = idMethod;
592 	}
593 
594 	
595 
596 
597 
598 
599 	public boolean isSkipSql() {
600 		return (skipSql || isAlias() || isForReferenceOnly());
601 	}
602 
603 	
604 
605 
606 
607 
608 
609 	public void setSkipSql(boolean v) {
610 		this.skipSql = v;
611 	}
612 
613 	
614 
615 
616 
617 
618 	public String getAlias() {
619 		return alias;
620 	}
621 
622 	
623 
624 
625 
626 
627 	public boolean isAlias() {
628 		return (alias != null);
629 	}
630 
631 	
632 
633 
634 
635 
636 
637 	public void setAlias(String v) {
638 		this.alias = v;
639 	}
640 
641 	
642 
643 
644 
645 
646 	public String getInterface() {
647 		return enterface;
648 	}
649 
650 	
651 
652 
653 
654 
655 
656 	public void setInterface(String v) {
657 		this.enterface = v;
658 	}
659 
660 	
661 
662 
663 
664 
665 
666 
667 	public boolean isAbstract() {
668 		return abstractValue;
669 	}
670 
671 	
672 
673 
674 
675 
676 
677 
678 
679 	public void setAbstract(boolean v) {
680 		this.abstractValue = v;
681 	}
682 
683 	
684 
685 
686 
687 
688 	public String getPackage() {
689 		if (pkg != null) {
690 			return pkg;
691 		} else {
692 			return this.getDatabase().getPackage();
693 		}
694 	}
695 
696 	
697 
698 
699 
700 
701 
702 	public void setPackage(String v) {
703 		this.pkg = v;
704 	}
705 
706 	
707 
708 
709 
710 
711 	public List getColumns() {
712 		return columnList;
713 	}
714 
715 	
716 
717 
718 	public int getNumColumns() {
719 		return columnList.size();
720 	}
721 
722 	
723 
724 
725 
726 
727 	public List getForeignKeys() {
728 		return foreignKeys;
729 	}
730 
731 	
732 
733 
734 	public List getIdMethodParameters() {
735 		return idMethodParameters;
736 	}
737 
738 	
739 
740 
741 
742 
743 	public String getSequenceName() {
744 		String result = null;
745 		if (getIdMethod().equals(NATIVE)) {
746 			List idMethodParams = getIdMethodParameters();
747 			if (idMethodParams == null) {
748 				result = getName() + "_SEQ";
749 			} else {
750 				result = ((IdMethodParameter) idMethodParams.get(0)).getValue();
751 			}
752 		}
753 		return result;
754 	}
755 
756 	
757 
758 
759 
760 
761 	public List getIndices() {
762 		return indices;
763 	}
764 
765 	
766 
767 
768 
769 
770 	public List getUnices() {
771 		return unices;
772 	}
773 
774 	
775 
776 
777 
778 
779 
780 
781 	public Column getColumn(String name) {
782 		return (Column) columnsByName.get(name);
783 	}
784 
785 	
786 
787 
788 
789 
790 
791 
792 	public Column getColumnByJavaName(String javaName) {
793 		return (Column) columnsByJavaName.get(javaName);
794 	}
795 
796 	
797 
798 
799 
800 
801 
802 
803 
804 	public ForeignKey getForeignKey(String col) {
805 		ForeignKey firstFK = null;
806 		for (Iterator iter = foreignKeys.iterator(); iter.hasNext();) {
807 			ForeignKey key = (ForeignKey) iter.next();
808 			if (key.getLocalColumns().contains(col)) {
809 				if (firstFK == null) {
810 					firstFK = key;
811 				} else {
812 					
813 					
814 					
815 					
816 				}
817 			}
818 		}
819 		return firstFK;
820 	}
821 
822 	
823 
824 
825 
826 
827 
828 
829 	public boolean containsColumn(Column col) {
830 		return columnList.contains(col);
831 	}
832 
833 	
834 
835 
836 
837 
838 
839 
840 	public boolean containsColumn(String name) {
841 		return (getColumn(name) != null);
842 	}
843 
844 	
845 
846 
847 
848 
849 
850 	public void setDatabase(Database parent) {
851 		tableParent = parent;
852 	}
853 
854 	
855 
856 
857 
858 
859 	public Database getDatabase() {
860 		return tableParent;
861 	}
862 
863 	
864 
865 
866 
867 
868 	public boolean isForReferenceOnly() {
869 		return forReferenceOnly;
870 	}
871 
872 	
873 
874 
875 
876 
877 
878 	public void setForReferenceOnly(boolean v) {
879 		this.forReferenceOnly = v;
880 	}
881 
882 	
883 
884 
885 
886 
887 	public String toString() {
888 		StringBuffer result = new StringBuffer();
889 
890 		result.append("<table name=\"").append(name).append('\"');
891 
892 		if (javaName != null) {
893 			result.append(" javaName=\"").append(javaName).append('\"');
894 		}
895 
896 		if (idMethod != null) {
897 			result.append(" idMethod=\"").append(idMethod).append('\"');
898 		}
899 
900 		if (skipSql) {
901 			result.append(" skipSql=\"").append(new Boolean(skipSql)).append('\"');
902 		}
903 
904 		if (abstractValue) {
905 			result.append(" abstract=\"").append(new Boolean(abstractValue)).append('\"');
906 		}
907 
908 		if (baseClass != null) {
909 			result.append(" baseClass=\"").append(baseClass).append('\"');
910 		}
911 
912 		if (basePeer != null) {
913 			result.append(" basePeer=\"").append(basePeer).append('\"');
914 		}
915 
916 		result.append(">\n");
917 
918 		if (columnList != null) {
919 			for (Iterator iter = columnList.iterator(); iter.hasNext();) {
920 				result.append(iter.next());
921 			}
922 		}
923 
924 		if (foreignKeys != null) {
925 			for (Iterator iter = foreignKeys.iterator(); iter.hasNext();) {
926 				result.append(iter.next());
927 			}
928 		}
929 
930 		if (idMethodParameters != null) {
931 			Iterator iter = idMethodParameters.iterator();
932 			while (iter.hasNext()) {
933 				result.append(iter.next());
934 			}
935 		}
936 
937 		result.append("</table>\n");
938 
939 		return result.toString();
940 	}
941 
942 	
943 
944 
945 
946 
947 	public List getPrimaryKey() {
948 		List pk = new ArrayList(columnList.size());
949 
950 		Iterator iter = columnList.iterator();
951 		while (iter.hasNext()) {
952 			Column col = (Column) iter.next();
953 			if (col.isPrimaryKey()) {
954 				pk.add(col);
955 			}
956 		}
957 		return pk;
958 	}
959 
960 	
961 
962 
963 
964 
965 	public boolean hasPrimaryKey() {
966 		return (getPrimaryKey().size() > 0);
967 	}
968 
969 	
970 
971 
972 
973 
974 	public String printPrimaryKey() {
975 		return printList(columnList);
976 	}
977 
978 	
979 
980 
981 
982 
983 
984 
985 	private String printList(List list) {
986 		StringBuffer result = new StringBuffer();
987 		boolean comma = false;
988 		for (Iterator iter = list.iterator(); iter.hasNext();) {
989 			Column col = (Column) iter.next();
990 			if (col.isPrimaryKey()) {
991 				if (comma) {
992 					result.append(',');
993 				} else {
994 					comma = true;
995 				}
996 				result.append(col.getName());
997 			}
998 		}
999 		return result.toString();
1000 	}
1001 
1002 	
1003 
1004 
1005 
1006 
1007 
1008 
1009 	public void setCorrectGetters(Boolean value) {
1010 		boolean correctGetters = value != null && value.booleanValue();
1011 		for (Iterator it = columnList.iterator(); it.hasNext();) {
1012 			Column col = (Column) it.next();
1013 			col.setCorrectGetters(correctGetters);
1014 		}
1015 	}
1016 
1017 	
1018 
1019 
1020 
1021 
1022 
1023 
1024 
1025 	public void addOption(String key, String value) {
1026 		options.put(key, value);
1027 	}
1028 
1029 	
1030 
1031 
1032 
1033 
1034 
1035 
1036 	public String getOption(String key) {
1037 		return (String) options.get(key);
1038 	}
1039 
1040 	
1041 
1042 
1043 
1044 
1045 
1046 
1047 
1048 
1049 	public Map getOptions() {
1050 		return options;
1051 	}
1052 }