1 | |
package liquibase.dbdoc; |
2 | |
|
3 | |
import liquibase.change.Change; |
4 | |
import liquibase.changelog.ChangeSet; |
5 | |
import liquibase.database.Database; |
6 | |
import liquibase.exception.DatabaseException; |
7 | |
import liquibase.exception.DatabaseHistoryException; |
8 | |
import liquibase.util.LiquibaseUtil; |
9 | |
import liquibase.util.StringUtils; |
10 | |
|
11 | |
import java.io.File; |
12 | |
import java.io.FileWriter; |
13 | |
import java.io.IOException; |
14 | |
import java.text.DateFormat; |
15 | |
import java.util.Date; |
16 | |
import java.util.List; |
17 | |
|
18 | |
public abstract class HTMLWriter { |
19 | |
protected File outputDir; |
20 | |
protected Database database; |
21 | |
|
22 | 0 | public HTMLWriter(File outputDir, Database database) { |
23 | 0 | this.outputDir = outputDir; |
24 | 0 | this.database = database; |
25 | 0 | if (!outputDir.exists()) { |
26 | 0 | outputDir.mkdirs(); |
27 | |
} |
28 | 0 | } |
29 | |
|
30 | |
protected abstract void writeCustomHTML(FileWriter fileWriter, Object object, List<Change> changes, |
31 | |
Database database) throws IOException; |
32 | |
|
33 | |
private FileWriter createFileWriter(Object object) throws IOException { |
34 | 0 | return new FileWriter(new File(outputDir, object.toString().toLowerCase() + ".html")); |
35 | |
} |
36 | |
|
37 | |
public void writeHTML(Object object, List<Change> ranChanges, List<Change> changesToRun, String changeLog) |
38 | |
throws IOException, DatabaseHistoryException, DatabaseException { |
39 | 0 | FileWriter fileWriter = createFileWriter(object); |
40 | |
|
41 | |
try { |
42 | 0 | fileWriter.append("<html>"); |
43 | 0 | writeHeader(object, fileWriter); |
44 | 0 | fileWriter.append("<body BGCOLOR=\"white\" onload=\"windowTitle();\">"); |
45 | |
|
46 | 0 | fileWriter.append("<H2>").append(createTitle(object)).append("</H2>\n"); |
47 | |
|
48 | 0 | writeBody(fileWriter, object, ranChanges, changesToRun); |
49 | |
|
50 | 0 | writeFooter(fileWriter, changeLog); |
51 | |
|
52 | 0 | fileWriter.append("</body>"); |
53 | 0 | fileWriter.append("</html>"); |
54 | |
} finally { |
55 | 0 | fileWriter.close(); |
56 | 0 | } |
57 | |
|
58 | 0 | } |
59 | |
|
60 | |
private void writeFooter(FileWriter fileWriter, String changeLog) throws IOException { |
61 | 0 | fileWriter.append("<hr>Generated: "); |
62 | 0 | fileWriter.append(DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).format(new Date())); |
63 | 0 | fileWriter.append("<BR>Against: "); |
64 | 0 | fileWriter.append(database.toString()); |
65 | 0 | fileWriter.append("<BR>Change Log: "); |
66 | 0 | fileWriter.append(changeLog); |
67 | 0 | fileWriter.append("<BR><BR>Generated By: "); |
68 | 0 | fileWriter.append("<a href='http://www.liquibase.org' target='_TOP'>Liquibase ") |
69 | |
.append(LiquibaseUtil.getBuildVersion()).append("</a>"); |
70 | 0 | } |
71 | |
|
72 | |
protected void writeBody(FileWriter fileWriter, Object object, List<Change> ranChanges, List<Change> changesToRun) |
73 | |
throws IOException, DatabaseHistoryException, DatabaseException { |
74 | 0 | writeCustomHTML(fileWriter, object, ranChanges, database); |
75 | 0 | writeChanges("Pending Changes", fileWriter, changesToRun); |
76 | 0 | writeChanges("Past Changes", fileWriter, ranChanges); |
77 | 0 | } |
78 | |
|
79 | |
protected void writeTable(String title, List<List<String>> cells, FileWriter fileWriter) throws IOException { |
80 | 0 | fileWriter.append("<P>"); |
81 | 0 | int colspan = 0; |
82 | 0 | if (cells.size() == 0) { |
83 | 0 | colspan = 0; |
84 | |
} else { |
85 | 0 | colspan = cells.get(0).size(); |
86 | |
} |
87 | 0 | fileWriter.append("<TABLE BORDER=\"1\" WIDTH=\"100%\" CELLPADDING=\"3\" CELLSPACING=\"0\" SUMMARY=\"\">\n") |
88 | |
.append("<TR BGCOLOR=\"#CCCCFF\" CLASS=\"TableHeadingColor\">\n").append("<TD COLSPAN=") |
89 | |
.append(String.valueOf(colspan)).append("><FONT SIZE=\"+2\">\n").append("<B>").append(title) |
90 | |
.append("</B></FONT></TD>\n").append("</TR>\n"); |
91 | |
|
92 | 0 | for (List<String> row : cells) { |
93 | 0 | fileWriter.append("<TR BGCOLOR=\"white\" CLASS=\"TableRowColor\">\n"); |
94 | 0 | for (String cell : row) { |
95 | 0 | writeTD(fileWriter, cell); |
96 | |
} |
97 | 0 | fileWriter.append("</TR>\n"); |
98 | |
} |
99 | 0 | fileWriter.append("</TABLE>\n"); |
100 | 0 | } |
101 | |
|
102 | |
private void writeTD(FileWriter fileWriter, String filePath) throws IOException { |
103 | 0 | fileWriter.append("<TD VALIGN=\"top\">\n"); |
104 | 0 | fileWriter.append(filePath); |
105 | 0 | fileWriter.append("</TD>\n"); |
106 | 0 | } |
107 | |
|
108 | |
private void writeHeader(Object object, FileWriter fileWriter) throws IOException { |
109 | 0 | String title = createTitle(object); |
110 | 0 | fileWriter.append("<head>").append("<title>").append(title).append("</title>") |
111 | |
.append("<LINK REL =\"stylesheet\" TYPE=\"text/css\" HREF=\"../../stylesheet.css\" TITLE=\"Style\">") |
112 | |
.append("<SCRIPT type=\"text/javascript\">").append("function windowTitle()").append("{") |
113 | |
.append(" parent.document.title=\"").append(title.replaceAll("\"", "'")).append("\";").append("}") |
114 | |
.append("</SCRIPT>").append("</head>"); |
115 | 0 | } |
116 | |
|
117 | |
protected abstract String createTitle(Object object); |
118 | |
|
119 | |
protected void writeChanges(String title, FileWriter fileWriter, List<Change> changes) throws IOException, |
120 | |
DatabaseHistoryException, DatabaseException { |
121 | 0 | fileWriter.append("<p><TABLE BORDER=\"1\" WIDTH=\"100%\" CELLPADDING=\"3\" CELLSPACING=\"0\" SUMMARY=\"\">\n"); |
122 | 0 | fileWriter.append("<TR BGCOLOR=\"#CCCCFF\" CLASS=\"TableHeadingColor\">\n"); |
123 | 0 | fileWriter.append("<TD COLSPAN='4'><FONT SIZE=\"+2\">\n"); |
124 | 0 | fileWriter.append("<B>"); |
125 | 0 | fileWriter.append(title); |
126 | 0 | fileWriter.append("</B></FONT></TD>\n"); |
127 | 0 | fileWriter.append("</TR>\n"); |
128 | |
|
129 | 0 | ChangeSet lastChangeSet = null; |
130 | 0 | if (changes == null || changes.size() == 0) { |
131 | 0 | fileWriter.append("<tr><td>None Found</td></tr>"); |
132 | |
} else { |
133 | 0 | for (Change change : changes) { |
134 | 0 | if (!change.getChangeSet().equals(lastChangeSet)) { |
135 | 0 | lastChangeSet = change.getChangeSet(); |
136 | 0 | fileWriter.append("<TR BGCOLOR=\"#EEEEFF\" CLASS=\"TableSubHeadingColor\">\n"); |
137 | 0 | writeTD(fileWriter, "<a href='../changelogs/" + change.getChangeSet().getFilePath() + ".xml'>" |
138 | |
+ change.getChangeSet().getFilePath() + "</a>"); |
139 | 0 | writeTD(fileWriter, change.getChangeSet().getId()); |
140 | 0 | writeTD(fileWriter, "<a href='../authors/" + change.getChangeSet().getAuthor().toLowerCase() |
141 | |
+ ".html'>" + change.getChangeSet().getAuthor().toLowerCase() + "</a>"); |
142 | |
|
143 | 0 | ChangeSet.RunStatus runStatus = database.getRunStatus(change.getChangeSet()); |
144 | 0 | if (runStatus.equals(ChangeSet.RunStatus.NOT_RAN)) { |
145 | 0 | String anchor = change.getChangeSet().toString(false).replaceAll("\\W", "_"); |
146 | 0 | writeTD(fileWriter, "NOT YET RAN [<a href='../pending/sql.html#" + anchor + "'>SQL</a>]"); |
147 | 0 | } else if (runStatus.equals(ChangeSet.RunStatus.INVALID_MD5SUM)) { |
148 | 0 | writeTD(fileWriter, "INVALID MD5SUM"); |
149 | 0 | } else if (runStatus.equals(ChangeSet.RunStatus.ALREADY_RAN)) { |
150 | 0 | writeTD(fileWriter, |
151 | |
"Executed " |
152 | |
+ DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).format( |
153 | |
database.getRanDate(change.getChangeSet()))); |
154 | 0 | } else if (runStatus.equals(ChangeSet.RunStatus.RUN_AGAIN)) { |
155 | 0 | writeTD(fileWriter, "Executed, WILL RUN AGAIN"); |
156 | |
} else { |
157 | 0 | throw new RuntimeException("Unknown run status: " + runStatus); |
158 | |
} |
159 | |
|
160 | 0 | fileWriter.append("</TR>"); |
161 | |
|
162 | 0 | if (StringUtils.trimToNull(change.getChangeSet().getComments()) != null) { |
163 | 0 | fileWriter.append("<TR><TD BGCOLOR='#EEEEFF' CLASS='TableSubHeadingColor' colspan='4'>") |
164 | |
.append(change.getChangeSet().getComments()).append("</TD></TR>"); |
165 | |
} |
166 | |
|
167 | |
} |
168 | |
|
169 | 0 | fileWriter.append("<TR BGCOLOR=\"white\" CLASS=\"TableRowColor\">\n"); |
170 | 0 | fileWriter.append("<td colspan='4'> ") |
171 | |
.append(change.getConfirmationMessage()).append("</td></TR>"); |
172 | |
} |
173 | |
} |
174 | |
|
175 | 0 | fileWriter.append("</TABLE>"); |
176 | 0 | fileWriter.append(" </P>"); |
177 | |
|
178 | 0 | } |
179 | |
} |