package liquibase.dbdoc;
import liquibase.change.Change;
import liquibase.changelog.ChangeSet;
import liquibase.database.Database;
import liquibase.exception.DatabaseException;
import liquibase.exception.DatabaseHistoryException;
import liquibase.util.LiquibaseUtil;
import liquibase.util.StringUtils;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DateFormat;
import java.util.Date;
import java.util.List;
public abstract class HTMLWriter {
protected File outputDir;
protected Database database;
public HTMLWriter(File outputDir, Database database) {
this.outputDir = outputDir;
this.database = database;
if (!outputDir.exists()) {
outputDir.mkdirs();
}
}
protected abstract void writeCustomHTML(FileWriter fileWriter, Object object, List<Change> changes, Database database) throws IOException;
private FileWriter createFileWriter(Object object) throws IOException {
return new FileWriter(new File(outputDir, object.toString().toLowerCase() + ".html"));
}
public void writeHTML(Object object, List<Change> ranChanges, List<Change> changesToRun, String changeLog) throws IOException, DatabaseHistoryException, DatabaseException {
FileWriter fileWriter = createFileWriter(object);
try {
fileWriter.append("<html>");
writeHeader(object, fileWriter);
fileWriter.append("<body BGCOLOR=\"white\" onload=\"windowTitle();\">");
fileWriter.append("<H2>").append(createTitle(object)).append("</H2>\n");
writeBody(fileWriter, object, ranChanges, changesToRun);
writeFooter(fileWriter, changeLog);
fileWriter.append("</body>");
fileWriter.append("</html>");
} finally {
fileWriter.close();
}
}
private void writeFooter(FileWriter fileWriter, String changeLog) throws IOException {
fileWriter.append("<hr>Generated: ");
fileWriter.append(DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).format(new Date()));
fileWriter.append("<BR>Against: ");
fileWriter.append(database.toString());
fileWriter.append("<BR>Change Log: ");
fileWriter.append(changeLog);
fileWriter.append("<BR><BR>Generated By: ");
fileWriter.append("<a href='http://www.liquibase.org' target='_TOP'>Liquibase ").append(LiquibaseUtil.getBuildVersion()).append("</a>");
}
protected void writeBody(FileWriter fileWriter, Object object, List<Change> ranChanges, List<Change> changesToRun) throws IOException, DatabaseHistoryException, DatabaseException {
writeCustomHTML(fileWriter, object, ranChanges, database);
writeChanges("Pending Changes", fileWriter, changesToRun);
writeChanges("Past Changes", fileWriter, ranChanges);
}
protected void writeTable(String title, List<List<String>> cells, FileWriter fileWriter) throws IOException {
fileWriter.append("<P>");
int colspan = 0;
if (cells.size() == 0) {
colspan = 0;
} else {
colspan = cells.get(0).size();
}
fileWriter.append("<TABLE BORDER=\"1\" WIDTH=\"100%\" CELLPADDING=\"3\" CELLSPACING=\"0\" SUMMARY=\"\">\n")
.append("<TR BGCOLOR=\"#CCCCFF\" CLASS=\"TableHeadingColor\">\n").append("<TD COLSPAN=").append(String.valueOf(colspan)).append("><FONT SIZE=\"+2\">\n").append("<B>").append(title).append("</B></FONT></TD>\n")
.append("</TR>\n");
for (List<String> row : cells) {
fileWriter.append("<TR BGCOLOR=\"white\" CLASS=\"TableRowColor\">\n");
for (String cell : row) {
writeTD(fileWriter, cell);
}
fileWriter.append("</TR>\n");
}
fileWriter.append("</TABLE>\n");
}
private void writeTD(FileWriter fileWriter, String filePath) throws IOException {
fileWriter.append("<TD VALIGN=\"top\">\n");
fileWriter.append(filePath);
fileWriter.append("</TD>\n");
}
private void writeHeader(Object object, FileWriter fileWriter) throws IOException {
String title = createTitle(object);
fileWriter.append("<head>")
.append("<title>").append(title).append("</title>")
.append("<LINK REL =\"stylesheet\" TYPE=\"text/css\" HREF=\"../../stylesheet.css\" TITLE=\"Style\">")
.append("<SCRIPT type=\"text/javascript\">")
.append("function windowTitle()")
.append("{").append(" parent.document.title=\"").append(title.replaceAll("\"", "'")).append("\";")
.append("}")
.append("</SCRIPT>")
.append("</head>");
}
protected abstract String createTitle(Object object);
protected void writeChanges(String title, FileWriter fileWriter, List<Change> changes) throws IOException, DatabaseHistoryException, DatabaseException {
fileWriter.append("<p><TABLE BORDER=\"1\" WIDTH=\"100%\" CELLPADDING=\"3\" CELLSPACING=\"0\" SUMMARY=\"\">\n");
fileWriter.append("<TR BGCOLOR=\"#CCCCFF\" CLASS=\"TableHeadingColor\">\n");
fileWriter.append("<TD COLSPAN='4'><FONT SIZE=\"+2\">\n");
fileWriter.append("<B>");
fileWriter.append(title);
fileWriter.append("</B></FONT></TD>\n");
fileWriter.append("</TR>\n");
ChangeSet lastChangeSet = null;
if (changes == null || changes.size() == 0) {
fileWriter.append("<tr><td>None Found</td></tr>");
} else {
for (Change change : changes) {
if (!change.getChangeSet().equals(lastChangeSet)) {
lastChangeSet = change.getChangeSet();
fileWriter.append("<TR BGCOLOR=\"#EEEEFF\" CLASS=\"TableSubHeadingColor\">\n");
writeTD(fileWriter, "<a href='../changelogs/"+change.getChangeSet().getFilePath()+".xml'>"+change.getChangeSet().getFilePath()+"</a>");
writeTD(fileWriter, change.getChangeSet().getId());
writeTD(fileWriter, "<a href='../authors/"+change.getChangeSet().getAuthor().toLowerCase()+".html'>"+change.getChangeSet().getAuthor().toLowerCase()+"</a>");
ChangeSet.RunStatus runStatus = database.getRunStatus(change.getChangeSet());
if (runStatus.equals(ChangeSet.RunStatus.NOT_RAN)) {
String anchor = change.getChangeSet().toString(false).replaceAll("\\W","_");
writeTD(fileWriter, "NOT YET RAN [<a href='../pending/sql.html#"+ anchor +"'>SQL</a>]");
} else if (runStatus.equals(ChangeSet.RunStatus.INVALID_MD5SUM)) {
writeTD(fileWriter, "INVALID MD5SUM");
} else if (runStatus.equals(ChangeSet.RunStatus.ALREADY_RAN)) {
writeTD(fileWriter, "Executed "+ DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).format(database.getRanDate(change.getChangeSet())));
} else if (runStatus.equals(ChangeSet.RunStatus.RUN_AGAIN)) {
writeTD(fileWriter, "Executed, WILL RUN AGAIN");
} else {
throw new RuntimeException("Unknown run status: "+runStatus);
}
fileWriter.append("</TR>");
if (StringUtils.trimToNull(change.getChangeSet().getComments()) != null) {
fileWriter.append("<TR><TD BGCOLOR='#EEEEFF' CLASS='TableSubHeadingColor' colspan='4'>").append(change.getChangeSet().getComments()).append("</TD></TR>");
}
}
fileWriter.append("<TR BGCOLOR=\"white\" CLASS=\"TableRowColor\">\n");
fileWriter.append("<td colspan='4'> ").append(change.getConfirmationMessage()).append("</td></TR>");
}
}
fileWriter.append("</TABLE>");
fileWriter.append(" </P>");
}
}