/*
* Copyright (c) 2002 Cunningham & Cunningham, Inc.
* Copyright (c) 2009-2015 by Jochen Wierum & Cologne Intelligence
*
* This file is part of FitGoodies.
*
* FitGoodies is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FitGoodies is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FitGoodies. If not, see <http://www.gnu.org/licenses/>.
*/
package de.cologneintelligence.fitgoodies.runners;
import de.cologneintelligence.fitgoodies.Counts;
import de.cologneintelligence.fitgoodies.file.FileSystemDirectoryHelper;
import de.cologneintelligence.fitgoodies.util.FitUtils;
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
* Implementation of FitResult which generates a indented HTML table.
*/
public final class FitResultTable implements FitResult {
private final List<FileCount> results = new LinkedList<>();
private final FileSystemDirectoryHelper dirHelper;
/**
* Generates a new Object.
*
* @param helper helper object to convert pathnames
*/
public FitResultTable(final FileSystemDirectoryHelper helper) {
dirHelper = helper;
}
/**
* Saves the result <code>result</code> of the file {@code file}.
*
* @param file filename to identify the result
* @param result results
*/
@Override
public void put(final File file, final Counts result) {
FileCount fileCount = new FileCount(file, result);
if (results.contains(fileCount)) {
results.remove(fileCount);
}
results.add(fileCount);
}
/**
* Returns the {@code Counts} of a filename.
*
* @param file filename to look up
* @return {@code Counts} object which represents the file result
*/
public Counts get(final File file) {
int index = results.indexOf(new FileCount(file, null));
if (index == -1) {
return null;
} else {
return results.get(index).getCounts();
}
}
/**
* Returns all saved filenames.
*
* @return filenames of all results.
*/
public File[] getFiles() {
List<File> result = new ArrayList<>();
for (FileCount fileCount : results) {
result.add(fileCount.getFile());
}
Collections.sort(result, new FitFileComparator());
return result.toArray(new File[result.size()]);
}
/**
* Returns the sum of all results.
*
* @return sum of all results
*/
public Counts getSummary() {
Counts result = new Counts();
for (FileCount fileCount : results) {
if (fileCount.getCounts() != null) {
result.tally(fileCount.getCounts());
}
}
return result;
}
private static String color(final Counts counts) {
if (counts == null) {
return FitUtils.HTML_GREY;
} else if (counts.exceptions > 0 || counts.wrong > 0) {
return FitUtils.HTML_RED;
} else {
return FitUtils.HTML_GREEN;
}
}
/**
* Returns a single HTML Table row representing the results of the file
* {@code file}.
*
* @param file filename to look up
* @return HTML String with a a single Table row
*/
public String getRow(final File file) {
StringBuilder builder = new StringBuilder();
Counts counts = get(file);
builder.append("<tr bgcolor=\"");
builder.append(color(counts));
builder.append("\"><td>");
int depth = dirHelper.dirDepth(file);
indent(depth, builder);
builder.append("<a href=\"");
builder.append(FitUtils.htmlSafeFile(file));
builder.append("\">");
builder.append(file.getName());
builder.append("</a>");
builder.append("</td><td>");
if (counts == null) {
builder.append("(none)");
} else {
builder.append(counts.toString());
}
builder.append("</td></tr>");
return builder.toString();
}
/**
* Returns a summary row for a whole test run.
*
* @param directory headline of the table
* @return a single HTML row
*/
public String getSummaryRow(final File directory) {
StringBuilder builder = new StringBuilder();
Counts counts = getSummary();
builder.append("<tr bgcolor=\"");
builder.append(color(counts));
builder.append("\"><th style=\"text-align: left\">");
builder.append(directory.getName());
builder.append("</th><th style=\"text-align: left\">");
builder.append(counts.toString());
builder.append("</th></tr>");
return builder.toString();
}
/**
* Prints out a table to {@code stream} which contains all saved
* results including all summary rows.
*
* @param directory headline of the table
* @param stream stream to write results to
* @throws IOException thrown by {@code stream} in case of problems
*/
@Override
public void print(final File directory, final OutputStream stream) throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(stream);
BufferedWriter bw = new BufferedWriter(osw);
bw.write("<table>");
bw.write(getSummaryRow(directory));
bw.write("<tr><td colspan=\"2\"></td></tr>");
File[] files = getFiles();
if (files.length == 0) {
bw.write("<tr><td colspan=\"2\">no files found</td></tr>");
} else {
File currentDir = directory;
for (File file : files) {
File newDir = file.getAbsoluteFile().getParentFile();
if (!newDir.equals(currentDir) && !dirHelper.isSubDir(currentDir, newDir)) {
for (File tmpDir : dirHelper.getParentDirs(dirHelper.getCommonDir(currentDir, file), newDir)) {
bw.write(getSubSummaryRow(tmpDir));
}
}
currentDir = newDir;
bw.write(getRow(file));
}
}
bw.write("</table>");
bw.flush();
osw.flush();
}
/**
* Generates a HTML summary row for a subdirectory.
*
* @param path subdirectory to process
* @return a single HTML row
* @throws IOException if path cannot be resolved correctly
*/
public String getSubSummaryRow(final File path) throws IOException {
Counts sum = subDirSum(path);
return String.format("<tr bgcolor=\"%s\"><th style=\"text-align: left\">%s</th><td>%s</td></tr>",
color(sum), FitUtils.htmlSafeFile(dirHelper.abs2rel(new File("").getAbsolutePath(), path.getAbsolutePath())), sum.toString());
}
private Counts subDirSum(final File fullPath) throws IOException {
Counts sum = new Counts();
for (FileCount fileCount : results) {
String filePath = fileCount.getFile().getCanonicalFile().getParentFile().getCanonicalFile().getAbsolutePath();
if (filePath.startsWith(fullPath.getCanonicalFile().getAbsolutePath()) && fileCount.getCounts() != null) {
sum.tally(fileCount.getCounts());
}
}
return sum;
}
private void indent(final int depth, final StringBuilder builder) {
for (int i = 0; i < depth; ++i) {
builder.append(" ");
}
}
}