1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.sourceforge.schemaspy.view;
20
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Comparator;
25 import java.util.HashSet;
26 import java.util.List;
27 import java.util.Set;
28 import java.util.TreeSet;
29 import net.sourceforge.schemaspy.model.Database;
30 import net.sourceforge.schemaspy.model.Table;
31 import net.sourceforge.schemaspy.model.TableColumn;
32 import net.sourceforge.schemaspy.model.TableIndex;
33 import net.sourceforge.schemaspy.util.LineWriter;
34
35
36
37
38
39
40
41 public class HtmlColumnsPage extends HtmlFormatter {
42 private static HtmlColumnsPage instance = new HtmlColumnsPage();
43
44
45
46
47 private HtmlColumnsPage() {
48 }
49
50
51
52
53
54
55 public static HtmlColumnsPage getInstance() {
56 return instance;
57 }
58
59
60
61
62
63
64 public List<ColumnInfo> getColumnInfos()
65 {
66 List<ColumnInfo> columns = new ArrayList<ColumnInfo>();
67
68 columns.add(new ColumnInfo("Table", new ByTableComparator()));
69 columns.add(new ColumnInfo("Column", new ByColumnComparator()));
70 columns.add(new ColumnInfo("Type", new ByTypeComparator()));
71 columns.add(new ColumnInfo("Size", new BySizeComparator()));
72 columns.add(new ColumnInfo("Nulls", new ByNullableComparator()));
73 columns.add(new ColumnInfo("Auto", new ByAutoUpdateComparator()));
74 columns.add(new ColumnInfo("Default", new ByDefaultValueComparator()));
75
76 return columns;
77 }
78
79 public class ColumnInfo
80 {
81 private final String columnName;
82 private final Comparator<TableColumn> comparator;
83
84 private ColumnInfo(String columnName, Comparator<TableColumn> comparator)
85 {
86 this.columnName = columnName;
87 this.comparator = comparator;
88 }
89
90 public String getColumnName() {
91 return columnName;
92 }
93
94 public String getLocation() {
95 return getLocation(columnName);
96 }
97
98 public String getLocation(String colName) {
99 return "columns.by" + colName + ".html";
100 }
101
102 private Comparator<TableColumn> getComparator() {
103 return comparator;
104 }
105
106 @Override
107 public String toString() {
108 return getLocation();
109 }
110 }
111
112 public void write(Database database, Collection<Table> tables, ColumnInfo columnInfo, boolean showOrphansDiagram, LineWriter html) throws IOException {
113 Set<TableColumn> columns = new TreeSet<TableColumn>(columnInfo.getComparator());
114 Set<TableColumn> primaryColumns = new HashSet<TableColumn>();
115 Set<TableColumn> indexedColumns = new HashSet<TableColumn>();
116
117 for (Table table : tables) {
118 columns.addAll(table.getColumns());
119
120 primaryColumns.addAll(table.getPrimaryColumns());
121 for (TableIndex index : table.getIndexes()) {
122 indexedColumns.addAll(index.getColumns());
123 }
124 }
125
126 writeHeader(database, columns.size(), showOrphansDiagram, columnInfo, html);
127
128 HtmlTablePage formatter = HtmlTablePage.getInstance();
129
130 for (TableColumn column : columns) {
131 formatter.writeColumn(column, column.getTable().getName(), primaryColumns, indexedColumns, true, false, html);
132 }
133
134 writeFooter(html);
135 }
136
137 private void writeHeader(Database db, int numberOfColumns, boolean hasOrphans, ColumnInfo selectedColumn, LineWriter html) throws IOException {
138 writeHeader(db, null, "Columns", hasOrphans, html);
139
140 html.writeln("<table width='100%' border='0'>");
141 html.writeln("<tr><td class='container'>");
142 writeGeneratedBy(db.getConnectTime(), html);
143 html.writeln("</td><td class='container' rowspan='2' align='right' valign='top'>");
144 writeLegend(false, false, html);
145 html.writeln("</td></tr>");
146 html.writeln("<tr valign='top'><td class='container' align='left' valign='top'>");
147 html.writeln("<p>");
148 html.writeln("<form name='options' action=''>");
149 html.writeln(" <label for='showComments'><input type=checkbox id='showComments'>Comments</label>");
150 html.writeln(" <label for='showLegend'><input type=checkbox checked id='showLegend'>Legend</label>");
151 html.writeln("</form>");
152 html.writeln("</table>");
153
154 html.writeln("<div class='indent'>");
155 html.write("<b>");
156 html.write(db.getName());
157 if (db.getSchema() != null) {
158 html.write('.');
159 html.write(db.getSchema());
160 }
161 html.write(" contains ");
162 html.write(String.valueOf(numberOfColumns));
163 html.write(" columns</b> - click on heading to sort:");
164 Collection<Table> tables = db.getTables();
165 boolean hasTableIds = tables.size() > 0 && tables.iterator().next().getId() != null;
166 writeMainTableHeader(hasTableIds, selectedColumn, html);
167 html.writeln("<tbody valign='top'>");
168 }
169
170 public void writeMainTableHeader(boolean hasTableIds, ColumnInfo selectedColumn, LineWriter out) throws IOException {
171 boolean onColumnsPage = selectedColumn != null;
172 out.writeln("<a name='columns'></a>");
173 out.writeln("<table id='columns' class='dataTable' border='1' rules='groups'>");
174 int numCols = 6;
175 if (hasTableIds && !onColumnsPage)
176 ++numCols;
177 if (onColumnsPage)
178 ++numCols;
179 else
180 numCols += 2;
181 for (int i = 0; i < numCols; ++i)
182 out.writeln("<colgroup>");
183 out.writeln("<colgroup class='comment'>");
184
185 out.writeln("<thead align='left'>");
186 out.writeln("<tr>");
187 if (hasTableIds && !onColumnsPage)
188 out.writeln(getTH(selectedColumn, "ID", null, "right"));
189 if (onColumnsPage)
190 out.writeln(getTH(selectedColumn, "Table", null, null));
191 out.writeln(getTH(selectedColumn, "Column", null, null));
192 out.writeln(getTH(selectedColumn, "Type", null, null));
193 out.writeln(getTH(selectedColumn, "Size", null, null));
194 out.writeln(getTH(selectedColumn, "Nulls", "Are nulls allowed?", null));
195 out.writeln(getTH(selectedColumn, "Auto", "Is column automatically updated?", null));
196 out.writeln(getTH(selectedColumn, "Default", "Default value", null));
197 if (!onColumnsPage) {
198 out.write(" <th title='Columns in tables that reference this column'>");
199 out.writeln("<span class='notSortedByColumn'>Children</span></th>");
200 out.write(" <th title='Columns in tables that are referenced by this column'>");
201 out.writeln("<span class='notSortedByColumn'>Parents</span></th>");
202 }
203 out.writeln(" <th title='Comments' class='comment'><span class='notSortedByColumn'>Comments</span></th>");
204 out.writeln("</tr>");
205 out.writeln("</thead>");
206 }
207
208 private String getTH(ColumnInfo selectedColumn, String columnName, String title, String align) {
209 StringBuilder buf = new StringBuilder(" <th");
210
211 if (align != null) {
212 buf.append(" align='");
213 buf.append(align);
214 buf.append("'");
215 }
216
217 if (title != null) {
218 buf.append(" title='");
219 buf.append(title);
220 buf.append("'");
221 }
222
223 if (selectedColumn != null) {
224 if (selectedColumn.getColumnName().equals(columnName)) {
225 buf.append(" class='sortedByColumn'>");
226 buf.append(columnName);
227 } else {
228 buf.append(" class='notSortedByColumn'>");
229 buf.append("<a href='");
230 buf.append(encodeHref(selectedColumn.getLocation(columnName)));
231 buf.append("#columns'><span class='notSortedByColumn'>");
232 buf.append(columnName);
233 buf.append("</span></a>");
234 }
235 } else {
236 buf.append('>');
237 buf.append(columnName);
238 }
239 buf.append("</th>");
240
241 return buf.toString();
242 }
243
244 @Override
245 protected void writeFooter(LineWriter html) throws IOException {
246 html.writeln("</table>");
247 html.writeln("</div>");
248 super.writeFooter(html);
249 }
250
251 @Override
252 protected boolean isColumnsPage() {
253 return true;
254 }
255
256 private class ByColumnComparator implements Comparator<TableColumn> {
257 public int compare(TableColumn column1, TableColumn column2) {
258 int rc = column1.getName().compareToIgnoreCase(column2.getName());
259 if (rc == 0)
260 rc = column1.getTable().compareTo(column2.getTable());
261 return rc;
262 }
263 }
264
265 private class ByTableComparator implements Comparator<TableColumn> {
266 public int compare(TableColumn column1, TableColumn column2) {
267 int rc = column1.getTable().compareTo(column2.getTable());
268 if (rc == 0)
269 rc = column1.getName().compareToIgnoreCase(column2.getName());
270 return rc;
271 }
272 }
273
274 private class ByTypeComparator implements Comparator<TableColumn> {
275 private final Comparator<TableColumn> bySize = new BySizeComparator();
276
277 public int compare(TableColumn column1, TableColumn column2) {
278 int rc = column1.getType().compareToIgnoreCase(column2.getType());
279 if (rc == 0) {
280 rc = bySize.compare(column1, column2);
281 }
282 return rc;
283 }
284 }
285
286 private class BySizeComparator implements Comparator<TableColumn> {
287 private final Comparator<TableColumn> byColumn = new ByColumnComparator();
288
289 public int compare(TableColumn column1, TableColumn column2) {
290 int rc = column1.getLength() - column2.getLength();
291 if (rc == 0) {
292 rc = column1.getDecimalDigits() - column2.getDecimalDigits();
293 if (rc == 0)
294 rc = byColumn.compare(column1, column2);
295 }
296 return rc;
297 }
298 }
299
300 private class ByNullableComparator implements Comparator<TableColumn> {
301 private final Comparator<TableColumn> byColumn = new ByColumnComparator();
302
303 public int compare(TableColumn column1, TableColumn column2) {
304 int rc = column1.isNullable() == column2.isNullable() ? 0 : column1.isNullable() ? -1 : 1;
305 if (rc == 0)
306 rc = byColumn.compare(column1, column2);
307 return rc;
308 }
309 }
310
311 private class ByAutoUpdateComparator implements Comparator<TableColumn> {
312 private final Comparator<TableColumn> byColumn = new ByColumnComparator();
313
314 public int compare(TableColumn column1, TableColumn column2) {
315 int rc = column1.isAutoUpdated() == column2.isAutoUpdated() ? 0 : column1.isAutoUpdated() ? -1 : 1;
316 if (rc == 0)
317 rc = byColumn.compare(column1, column2);
318 return rc;
319 }
320 }
321
322 private class ByDefaultValueComparator implements Comparator<TableColumn> {
323 private final Comparator<TableColumn> byColumn = new ByColumnComparator();
324
325 public int compare(TableColumn column1, TableColumn column2) {
326 int rc = String.valueOf(column1.getDefaultValue()).compareToIgnoreCase(String.valueOf(column2.getDefaultValue()));
327 if (rc == 0)
328 rc = byColumn.compare(column1, column2);
329 return rc;
330 }
331 }
332 }