org.databene.dbsanity.report.DefectsPageModule Maven / Gradle / Ivy
The newest version!
/*
* (c) Copyright 2010-2011 by Volker Bergmann. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, is permitted under the terms of the
* GNU General Public License (GPL).
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* WITHOUT A WARRANTY OF ANY KIND. ALL EXPRESS OR IMPLIED CONDITIONS,
* REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE
* HEREBY EXCLUDED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package org.databene.dbsanity.report;
import java.io.File;
import org.databene.commons.FileUtil;
import org.databene.commons.converter.ToStringConverter;
import org.databene.dbsanity.ExecutionMode;
import org.databene.dbsanity.html.HtmlPrintWriter;
import org.databene.dbsanity.model.DefectRow;
import org.databene.dbsanity.model.SanityCheck;
import org.databene.html.HTMLUtil;
/**
* {@link ReportModule} implementation which creates an HTML page for each failed check.
* The page lists the faulty data in a table.
* Created: 13.10.2010 18:50:32
* @since 1.0
* @author Volker Bergmann
*/
public class DefectsPageModule extends AbstractReportModule {
private String latestFailedCheck;
private int latestDefectCount;
private HtmlPrintWriter out;
private char c = '/';
@Override
public void failure(SanityCheck check, DefectRow defectRow, String[] infoHeaders) {
if (!check.getName().equals(latestFailedCheck)) {
if (latestFailedCheck != null)
closeCurrentFile();
startNewFile(check, defectRow, infoHeaders);
this.latestDefectCount = 0;
}
if (context.getDefectRowLimit() <= 0 || latestDefectCount < context.getDefectRowLimit())
printDefectRow(defectRow);
this.latestFailedCheck = check.getName();
this.latestDefectCount++;
}
public void startNewFile(SanityCheck check, DefectRow defectRow,
String[] infoHeaders) {
try {
String title = "Defect List of check '" + check.getName() + "'";
File file = check.getDefectsOrErrorPage();
FileUtil.ensureDirectoryExists(file.getParentFile());
out = openNewFile(file, title);
context.printNavBar(file, out, ReportUtil.docRef(check, context));
renderCheckInfo(check, out);
startDefectList(infoHeaders, defectRow);
} catch (Exception e) {
throw new RuntimeException("Unexpected error", e);
}
}
public void startDefectList(String[] infoHeaders, DefectRow defectRow) {
out.startModule("Defects");
out.startTable();
printFailureInfoHeader(infoHeaders);
}
@Override
public void close() {
closeCurrentFile();
}
private char next(char c) {
switch (c) {
case '/' : return '-';
case '-' : return '\\';
case '\\' : return '|';
default : return '/';
}
}
protected void closeCurrentFile() {
if (out != null) {
if (latestFailedCheck != null) {
out.endTable();
out.endModule();
}
super.closeFile(out);
out = null;
}
}
private void printFailureInfoHeader(String[] errorInfo) {
out.startTableRow();
for (String header : errorInfo)
out.render(headerCell(header).withClass("td_defect"));
out.endTableRow();
}
private void printDefectRow(DefectRow defectRow) {
out.startTableRow();
for (int i = 0; i < defectRow.length(); i++) {
String cellClass = (defectRow.isMarked(i) ? "td_defect_em" : "td_defect");
out.render(cell(renderCellValue(defectRow.get(i), i)).withClass(cellClass));
}
out.endTableRow();
// print activity indicator or defect data to console
switch ((ExecutionMode) context.get("executionMode")) {
case VERBOSE : printDefectDataToConsole(defectRow); break;
case DEFAULT : System.out.print((c = next(c)) + "\r"); break;
}
}
private String renderCellValue(Object value, int index) {
if (value == null)
return "[null]";
if (value instanceof CharSequence) {
String rawString = HTMLUtil.escape((String) value);
int firstWordChar = firstNonWhitespaceIndex(rawString);
int lastWordChar = lastNonWhitespaceIndex(rawString);
StringBuilder builder = new StringBuilder();
for (int i = 0; i < firstWordChar; i++)
builder.append("♦");
builder.append(HTMLUtil.escape(rawString.substring(firstWordChar, lastWordChar + 1)));
for (int i = lastWordChar; i < rawString.length() - 1; i++)
builder.append("♦");
return builder.toString();
} else {
return ToStringConverter.convert(value, "[null]");
}
}
private int firstNonWhitespaceIndex(String text) {
int i = 0;
while (i < text.length() && Character.isWhitespace(text.charAt(i)))
i++;
return i;
}
private int lastNonWhitespaceIndex(String text) {
int i = text.length() - 1;
while (i > 0 && Character.isWhitespace(text.charAt(i)))
i--;
return i;
}
private void printDefectDataToConsole(DefectRow defectRow) {
System.out.print("Defective record: " + defectRow.get(0));
for (int i = 1; i < defectRow.length(); i++)
System.out.print(" " + renderCellValue(defectRow.get(i), i));
System.out.println();
}
}