1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.sourceforge.schemaspy.model;
20
21 import static java.sql.DatabaseMetaData.importedKeyCascade;
22 import static java.sql.DatabaseMetaData.importedKeyNoAction;
23 import static java.sql.DatabaseMetaData.importedKeyRestrict;
24 import static java.sql.DatabaseMetaData.importedKeySetNull;
25
26 import java.util.ArrayList;
27 import java.util.Collections;
28 import java.util.List;
29 import java.util.logging.Level;
30 import java.util.logging.Logger;
31
32
33
34
35
36
37 public class ForeignKeyConstraint implements Comparable<ForeignKeyConstraint> {
38 private final String name;
39 private Table parentTable;
40 private final List<TableColumn> parentColumns = new ArrayList<TableColumn>();
41 private final Table childTable;
42 private final List<TableColumn> childColumns = new ArrayList<TableColumn>();
43 private final int deleteRule;
44 private final int updateRule;
45 private final static Logger logger = Logger.getLogger(ForeignKeyConstraint.class.getName());
46 private final static boolean finerEnabled = logger.isLoggable(Level.FINER);
47
48
49
50
51
52
53
54
55
56 ForeignKeyConstraint(Table child, String name, int updateRule, int deleteRule) {
57 this.name = name;
58 if (finerEnabled)
59 logger.finer("Adding foreign key constraint '" + getName() + "' to " + child);
60 childTable = child;
61 this.deleteRule = deleteRule;
62 this.updateRule = updateRule;
63 }
64
65
66
67
68
69
70
71
72
73 public ForeignKeyConstraint(TableColumn parentColumn, TableColumn childColumn,
74 int updateRule, int deleteRule) {
75 this(childColumn.getTable(), null, updateRule, deleteRule);
76
77 addChildColumn(childColumn);
78 addParentColumn(parentColumn);
79
80 childColumn.addParent(parentColumn, this);
81 parentColumn.addChild(childColumn, this);
82 }
83
84
85
86
87
88
89
90
91
92 public ForeignKeyConstraint(TableColumn parentColumn, TableColumn childColumn) {
93 this(parentColumn, childColumn, importedKeyNoAction, importedKeyNoAction);
94 }
95
96
97
98
99
100
101 void addParentColumn(TableColumn column) {
102 if (column != null) {
103 parentColumns.add(column);
104 parentTable = column.getTable();
105 }
106 }
107
108
109
110
111
112
113 void addChildColumn(TableColumn column) {
114 if (column != null) {
115 childColumns.add(column);
116 }
117 }
118
119
120
121
122
123
124 public String getName() {
125 return name;
126 }
127
128
129
130
131
132
133
134 public Table getParentTable() {
135 return parentTable;
136 }
137
138
139
140
141
142
143 public List<TableColumn> getParentColumns() {
144 return Collections.unmodifiableList(parentColumns);
145 }
146
147
148
149
150
151
152
153 public Table getChildTable() {
154 return childTable;
155 }
156
157
158
159
160
161
162 public List<TableColumn> getChildColumns() {
163 return Collections.unmodifiableList(childColumns);
164 }
165
166
167
168
169
170
171 public int getDeleteRule() {
172 return deleteRule;
173 }
174
175
176
177
178
179
180
181 public boolean isCascadeOnDelete() {
182 return getDeleteRule() == importedKeyCascade;
183 }
184
185
186
187
188
189
190
191 public boolean isRestrictDelete() {
192 return getDeleteRule() == importedKeyNoAction || getDeleteRule() == importedKeyRestrict;
193 }
194
195
196
197
198
199
200
201 public boolean isNullOnDelete() {
202 return getDeleteRule() == importedKeySetNull;
203 }
204
205 public String getDeleteRuleName() {
206 switch (getDeleteRule()) {
207 case importedKeyCascade:
208 return "Cascade on delete";
209
210 case importedKeyRestrict:
211 case importedKeyNoAction:
212 return "Restrict delete";
213
214 case importedKeySetNull:
215 return "Null on delete";
216
217 default:
218 return "";
219 }
220 }
221
222 public String getDeleteRuleDescription() {
223 switch (getDeleteRule()) {
224 case importedKeyCascade:
225 return "Cascade on delete:\n Deletion of parent deletes child";
226
227 case importedKeyRestrict:
228 case importedKeyNoAction:
229 return "Restrict delete:\n Parent cannot be deleted if children exist";
230
231 case importedKeySetNull:
232 return "Null on delete:\n Foreign key to parent set to NULL when parent deleted";
233
234 default:
235 return "";
236 }
237 }
238
239 public String getDeleteRuleAlias() {
240 switch (getDeleteRule()) {
241 case importedKeyCascade:
242 return "C";
243
244 case importedKeyRestrict:
245 case importedKeyNoAction:
246 return "R";
247
248 case importedKeySetNull:
249 return "N";
250
251 default:
252 return "";
253 }
254 }
255
256
257
258
259
260
261 public int getUpdateRule() {
262 return updateRule;
263 }
264
265
266
267
268
269
270
271
272
273 public boolean isImplied() {
274 return false;
275 }
276
277
278
279
280
281
282
283
284
285
286 public boolean isReal() {
287 return getClass() == ForeignKeyConstraint.class;
288 }
289
290
291
292
293
294
295
296
297
298 public int compareTo(ForeignKeyConstraint other) {
299 if (other == this)
300 return 0;
301
302 int rc = getName().compareToIgnoreCase(other.getName());
303 if (rc == 0) {
304
305 String ours = getChildColumns().get(0).getTable().getSchema();
306 String theirs = other.getChildColumns().get(0).getTable().getSchema();
307 if (ours != null && theirs != null)
308 rc = ours.compareToIgnoreCase(theirs);
309 else if (ours == null)
310 rc = -1;
311 else
312 rc = 1;
313 }
314
315 return rc;
316 }
317
318
319
320
321
322
323
324
325 public static String toString(List<TableColumn> columns) {
326 if (columns.size() == 1)
327 return columns.iterator().next().toString();
328 return columns.toString();
329 }
330
331
332
333
334
335
336 @Override
337 public String toString() {
338 StringBuilder buf = new StringBuilder();
339 buf.append(childTable.getName());
340 buf.append('.');
341 buf.append(toString(childColumns));
342 buf.append(" refs ");
343 buf.append(parentTable.getName());
344 buf.append('.');
345 buf.append(toString(parentColumns));
346 if (parentTable.isRemote()) {
347 buf.append(" in ");
348 buf.append(parentTable.getSchema());
349 }
350 if (name != null) {
351 buf.append(" via ");
352 buf.append(name);
353 }
354
355 return buf.toString();
356 }
357 }