001: package liquibase.dbdoc;
002:
003: import liquibase.ChangeSet;
004: import liquibase.change.Change;
005: import liquibase.database.Database;
006: import liquibase.exception.DatabaseHistoryException;
007: import liquibase.exception.JDBCException;
008: import liquibase.util.LiquibaseUtil;
009: import liquibase.util.StringUtils;
010:
011: import java.io.File;
012: import java.io.FileWriter;
013: import java.io.IOException;
014: import java.text.DateFormat;
015: import java.util.Date;
016: import java.util.List;
017:
018: public abstract class HTMLWriter {
019: protected File outputDir;
020: protected Database database;
021:
022: public HTMLWriter(File outputDir, Database database) {
023: this .outputDir = outputDir;
024: this .database = database;
025: if (!outputDir.exists()) {
026: outputDir.mkdirs();
027: }
028: }
029:
030: protected abstract void writeCustomHTML(FileWriter fileWriter,
031: Object object, List<Change> changes, Database database)
032: throws IOException;
033:
034: private FileWriter createFileWriter(Object object)
035: throws IOException {
036: return new FileWriter(new File(outputDir, object.toString()
037: .toLowerCase()
038: + ".html"));
039: }
040:
041: public void writeHTML(Object object, List<Change> ranChanges,
042: List<Change> changesToRun, String changeLog)
043: throws IOException, DatabaseHistoryException, JDBCException {
044: FileWriter fileWriter = createFileWriter(object);
045:
046: try {
047: fileWriter.append("<html>");
048: writeHeader(object, fileWriter);
049: fileWriter
050: .append("<body BGCOLOR=\"white\" onload=\"windowTitle();\">");
051:
052: fileWriter.append("<H2>").append(createTitle(object))
053: .append("</H2>\n");
054:
055: writeBody(fileWriter, object, ranChanges, changesToRun);
056:
057: writeFooter(fileWriter, changeLog);
058:
059: fileWriter.append("</body>");
060: fileWriter.append("</html>");
061: } finally {
062: fileWriter.close();
063: }
064:
065: }
066:
067: private void writeFooter(FileWriter fileWriter, String changeLog)
068: throws IOException {
069: fileWriter.append("<hr>Generated: ");
070: fileWriter.append(DateFormat.getDateTimeInstance(
071: DateFormat.SHORT, DateFormat.SHORT).format(new Date()));
072: fileWriter.append("<BR>Against: ");
073: fileWriter.append(database.toString());
074: fileWriter.append("<BR>Change Log: ");
075: fileWriter.append(changeLog);
076: fileWriter.append("<BR><BR>Generated By: ");
077: fileWriter
078: .append(
079: "<a href='http://www.liquibase.org' target='_TOP'>LiquiBase ")
080: .append(LiquibaseUtil.getBuildVersion()).append("</a>");
081: }
082:
083: protected void writeBody(FileWriter fileWriter, Object object,
084: List<Change> ranChanges, List<Change> changesToRun)
085: throws IOException, DatabaseHistoryException, JDBCException {
086: writeCustomHTML(fileWriter, object, ranChanges, database);
087: writeChanges("Pending Changes", fileWriter, changesToRun);
088: writeChanges("Past Changes", fileWriter, ranChanges);
089: }
090:
091: protected void writeTable(String title, List<List<String>> cells,
092: FileWriter fileWriter) throws IOException {
093: fileWriter.append("<P>");
094: fileWriter
095: .append(
096: "<TABLE BORDER=\"1\" WIDTH=\"100%\" CELLPADDING=\"3\" CELLSPACING=\"0\" SUMMARY=\"\">\n")
097: .append(
098: "<TR BGCOLOR=\"#CCCCFF\" CLASS=\"TableHeadingColor\">\n")
099: .append("<TD COLSPAN=").append(
100: String.valueOf(cells.get(0).size())).append(
101: "><FONT SIZE=\"+2\">\n").append("<B>").append(
102: title).append("</B></FONT></TD>\n").append(
103: "</TR>\n");
104:
105: for (List<String> row : cells) {
106: fileWriter
107: .append("<TR BGCOLOR=\"white\" CLASS=\"TableRowColor\">\n");
108: for (String cell : row) {
109: writeTD(fileWriter, cell);
110: }
111: fileWriter.append("</TR>\n");
112: }
113: fileWriter.append("</TABLE>\n");
114: }
115:
116: private void writeTD(FileWriter fileWriter, String filePath)
117: throws IOException {
118: fileWriter.append("<TD VALIGN=\"top\">\n");
119: fileWriter.append(filePath);
120: fileWriter.append("</TD>\n");
121: }
122:
123: private void writeHeader(Object object, FileWriter fileWriter)
124: throws IOException {
125: String title = createTitle(object);
126: fileWriter
127: .append("<head>")
128: .append("<title>")
129: .append(title)
130: .append("</title>")
131: .append(
132: "<LINK REL =\"stylesheet\" TYPE=\"text/css\" HREF=\"../../stylesheet.css\" TITLE=\"Style\">")
133: .append("<SCRIPT type=\"text/javascript\">").append(
134: "function windowTitle()").append("{").append(
135: " parent.document.title=\"").append(title)
136: .append("\";").append("}").append("</SCRIPT>").append(
137: "</head>");
138: }
139:
140: protected abstract String createTitle(Object object);
141:
142: protected void writeChanges(String title, FileWriter fileWriter,
143: List<Change> changes) throws IOException,
144: DatabaseHistoryException, JDBCException {
145: fileWriter
146: .append("<p><TABLE BORDER=\"1\" WIDTH=\"100%\" CELLPADDING=\"3\" CELLSPACING=\"0\" SUMMARY=\"\">\n");
147: fileWriter
148: .append("<TR BGCOLOR=\"#CCCCFF\" CLASS=\"TableHeadingColor\">\n");
149: fileWriter.append("<TD COLSPAN='4'><FONT SIZE=\"+2\">\n");
150: fileWriter.append("<B>");
151: fileWriter.append(title);
152: fileWriter.append("</B></FONT></TD>\n");
153: fileWriter.append("</TR>\n");
154:
155: ChangeSet lastChangeSet = null;
156: if (changes == null || changes.size() == 0) {
157: fileWriter.append("<tr><td>None Found</td></tr>");
158: } else {
159: for (Change change : changes) {
160: if (!change.getChangeSet().equals(lastChangeSet)) {
161: lastChangeSet = change.getChangeSet();
162: fileWriter
163: .append("<TR BGCOLOR=\"#EEEEFF\" CLASS=\"TableSubHeadingColor\">\n");
164: writeTD(fileWriter, "<a href='../changelogs/"
165: + change.getChangeSet().getFilePath()
166: + ".xml'>"
167: + change.getChangeSet().getFilePath()
168: + "</a>");
169: writeTD(fileWriter, change.getChangeSet().getId());
170: writeTD(fileWriter, "<a href='../authors/"
171: + change.getChangeSet().getAuthor()
172: .toLowerCase()
173: + ".html'>"
174: + change.getChangeSet().getAuthor()
175: .toLowerCase() + "</a>");
176:
177: ChangeSet.RunStatus runStatus = database
178: .getRunStatus(change.getChangeSet());
179: if (runStatus.equals(ChangeSet.RunStatus.NOT_RAN)) {
180: String anchor = change.getChangeSet().toString(
181: false).replaceAll("\\W", "_");
182: writeTD(fileWriter,
183: "NOT YET RAN [<a href='../pending/sql.html#"
184: + anchor + "'>SQL</a>]");
185: } else if (runStatus
186: .equals(ChangeSet.RunStatus.INVALID_MD5SUM)) {
187: writeTD(fileWriter, "INVALID MD5SUM");
188: } else if (runStatus
189: .equals(ChangeSet.RunStatus.ALREADY_RAN)) {
190: writeTD(fileWriter, "Executed "
191: + DateFormat.getDateTimeInstance(
192: DateFormat.SHORT,
193: DateFormat.SHORT).format(
194: database.getRanDate(change
195: .getChangeSet())));
196: } else if (runStatus
197: .equals(ChangeSet.RunStatus.RUN_AGAIN)) {
198: writeTD(fileWriter, "Executed, WILL RUN AGAIN");
199: } else {
200: throw new RuntimeException(
201: "Unknown run status: " + runStatus);
202: }
203:
204: fileWriter.append("</TR>");
205:
206: if (StringUtils.trimToNull(change.getChangeSet()
207: .getComments()) != null) {
208: fileWriter
209: .append(
210: "<TR><TD BGCOLOR='#EEEEFF' CLASS='TableSubHeadingColor' colspan='4'>")
211: .append(
212: change.getChangeSet()
213: .getComments()).append(
214: "</TD></TR>");
215: }
216:
217: }
218:
219: fileWriter
220: .append("<TR BGCOLOR=\"white\" CLASS=\"TableRowColor\">\n");
221: fileWriter
222: .append(
223: "<td colspan='4'> ")
224: .append(change.getConfirmationMessage())
225: .append("</td></TR>");
226: }
227: }
228:
229: fileWriter.append("</TABLE>");
230: fileWriter.append(" </P>");
231:
232: }
233: }
|