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 }