package reportgen.formatter.simple;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import reportgen.utils.ReportException;
import reportgen.prototype.queryresults.ResultsRow;
import reportgen.math.agregate.agregate.AggregateFunction;
/**
* Все строки результата можно распределить по рекурсивным группам,
* соответственно колонкам группировки
*/
public class ResultGroup {
private final static int NOT_FILTERED = -1;
private final int filterColIndex;
private Object filterValue;
private final MetaData data;
private final ArrayList<ResultGroup> included = new ArrayList<ResultGroup>();
private final ArrayList<ResultsRow> rows = new ArrayList<ResultsRow>();
private ResultGroup(MetaData data, int filterColIndex) {
super();
this.data = data;
this.filterColIndex = filterColIndex;
}
public ResultGroup(MetaData data) {
this(data, ResultGroup.NOT_FILTERED);
}
/**
* Распределяет строку по рекурсивным группам, соответственно
* @param row
* @return
*/
public boolean merge(ResultsRow row) {
boolean match = false;
if (filterColIndex == NOT_FILTERED) {
//подходят все строки
match = true;
} else if (rows.size() == 0) {
//пустая группа - подходят все строки
match = true;
filterValue = row.getValue(data.getGroupColumnIndex(filterColIndex));
} else {
//не пустая группа - есть данные, сравниваем, подходит или нет
Object rowValue = row.getValue(data.getGroupColumnIndex(filterColIndex));
if (filterValue == rowValue
|| (rowValue != null && rowValue != null && rowValue.equals(filterValue))) {
match = true;
}
}
if (!match) {
return false;
}
//if can have included tables
if (data.isLastGroupCol(filterColIndex)) {
rows.add(row);
} else {
//check already exist tables
if (included.size() > 0) {
for (ResultGroup group : included) {
if (group.merge(row)) {
return true;
}
}
}
//if not found match, create new table
ResultGroup group = new ResultGroup(data, filterColIndex + 1);
included.add(group);
group.merge(row);
}
return true;
}
/**
* Выводит в отформатированном виде группу и ее содержимое рекурсивно
* @param txt
* @param level
* @throws reportgen.ren.exception.ReportException
*/
public void format(PrintStream stream, int level, String prefix, boolean makeSumRows) throws ReportException {
if (rows.size() == 0) {
return;
}
//if filtered by column - show title
if (filterColIndex != NOT_FILTERED) {
stream.print("<h" + level + ">" + prefix + " ");
stream.print(data.getColumnTitle(data.getGroupColumnIndex(filterColIndex)));
if(filterValue == null) {
stream.print(": -");
} else {
stream.print(": " + filterValue.toString());
}
stream.print("</h" + level + ">");
}
//has included tables
if (included.size() > 0) {
int subPrefixIndex = 1;
for (ResultGroup internalGroup : included) {
internalGroup.format(stream, level + 1, prefix + subPrefixIndex + ".", makeSumRows);
subPrefixIndex++;
}
} else {
makeTable(stream, rows, true, false);
}
//Summ row
if (makeSumRows) {
stream.print("<h" + level + ">");
if (filterValue == null) {
stream.print("Итого");
} else {
stream.print("Итого по \"" + filterValue.toString() + "\"");
}
stream.print("</h" + (level-1) + ">");
//summ row values
makeTable(stream, getSummRows(), true, true);
}
}
/**
*
* @return
* @throws reportgen.ren.exception.ReportException
*/
private List<ResultsRow> getSummRows() throws ReportException {
List<ResultsRow> resultRows = new ArrayList<ResultsRow>();
ResultsRow row = rows.get(0).clone();
resultRows.add(row);
row.initSummRow(data.getModes());
for (int i = 1; i < rows.size(); i++) {
row.merge(rows.get(i), null, data.getModes());
}
row.normalize(data.getModes());
return resultRows;
}
/**
* Creates table from specified visible columns
* @param rows
* @param showHeader - show table header or not
* @param includeFunc - show in header column view mode function
* @return
*/
private void makeTable(PrintStream stream, List<ResultsRow> rows,
boolean showHeader, boolean includeFunc) {
Set<Integer> visible = data.getRealVisibleColumns();
stream.print("<table width='100%' border='1'>");
//header
if (showHeader) {
String head = "<tr>";
for (int columnIndex : visible) {
String colTitle = data.getColumnTitle(columnIndex);
AggregateFunction mode = data.getModes().get(columnIndex);
if (includeFunc && !mode.equals(AggregateFunction.ASIS)) {
colTitle = mode.toString() + "(" + colTitle + ")";
}
head += "<th>" + colTitle + "</th>";
}
stream.print(head + "</tr>");
}
//body
for (ResultsRow row : rows) {
String rowtxt = "<tr>";
for (int columnIndex : visible) {
rowtxt += "<td>" + row.getValue(columnIndex) + "</td>";
}
stream.print(rowtxt + "</tr>");
}
stream.print("</table>");
}
}