package org.agnitas.util; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.GregorianCalendar; import java.util.List; import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.StringUtils; public class TextTable { private static final String METADATA_HEADER = "HEADER"; private static final String METADATA_FARBE = "FARBE"; private static final String METADATA_RIGHTALIGNMENT = "RIGHTALIGN"; private List<List<String>> columnNames; private List<List<String>> content; private List<String> columnColors; private List<String> lineColors; private List<Boolean> columnRightAligned; private int currentLineIndex = -1; private int currentColumnIndex = -1; public TextTable() { columnNames = new ArrayList<List<String>>(); columnColors = new ArrayList<String>(); content = new ArrayList<List<String>>(); columnRightAligned = new ArrayList<Boolean>(); lineColors = new ArrayList<String>(); // first row contains headers columnNames.add(new ArrayList<String>()); } public TextTable(String... columnNames) { this(); for (String columnName : columnNames) addColumn(columnName); } public boolean hasData() { return currentLineIndex >= 0; } public void addColumn(String columnName) { addColumn(columnName, null, false); } public void addColumn(String columnName, String columnNameLine2, boolean alignRight) { addColumn(columnName, columnNameLine2, alignRight, null); } public void addColumn(String columnName, String columnNameLine2, boolean alignRight, String farbe) { columnNames.get(0).add(columnName); columnColors.add(farbe); // add second row if (columnNameLine2 != null && columnNames.size() == 1) columnNames.add(new ArrayList<String>()); if (columnNames.size() > 1) { while (columnNames.get(1).size() < columnNames.get(0).size() - 1) columnNames.get(1).add(""); } if (columnNameLine2 != null) columnNames.get(1).add(columnNameLine2); else if (columnNames.size() > 1) columnNames.get(1).add(""); columnRightAligned.add(alignRight); // bring all rows to length of headers for (List<String> line : content) { while (line.size() < columnNames.get(0).size()) line.add(""); } } public void dropColumn(int index) { columnNames.get(0).remove(index); columnColors.remove(index); if (columnNames.size() > 1) columnNames.get(1).remove(index); columnRightAligned.remove(index); // bring all rows to length of headers for (List<String> line : content) line.remove(index); } public void setAlignmentForColumn(int columnIndex, boolean alignRight) throws Exception { if (columnIndex < 0 || columnIndex >= columnNames.get(0).size()) throw new Exception("Ungültige Spalten-Indexangabe: " + columnIndex); columnRightAligned.set(columnIndex, alignRight); } public void startNewLine() { startNewLine(null); } public void startNewLine(String farbe) { content.add(new ArrayList<String>()); lineColors.add(farbe); currentLineIndex++; currentColumnIndex = 0; // bring new row to length of headers while (content.get(currentLineIndex).size() < columnNames.get(0).size()) content.get(currentLineIndex).add(""); } public void addValueToCurrentLine(int value) throws Exception { addValueToCurrentLine(Integer.toString(value)); } public void addValueToCurrentLine(String value) throws Exception { if (currentLineIndex == -1) throw new Exception("Keine Zeile zum Erweitern angelegt"); else if (content.get(currentLineIndex).size() <= currentColumnIndex) throw new Exception("Versuch in eine Spalte zu Schreiben die noch nicht angelegt wurde"); if (value == null) value = ""; content.get(currentLineIndex).set(currentColumnIndex, value); currentColumnIndex++; } public void setNumericColumnsRightALigned() { for (int columnIndex = 0; columnIndex < columnRightAligned.size(); columnIndex++) { boolean isNumeric = true; for (List<String> line : content) { if (StringUtils.isNotBlank(line.get(columnIndex)) && !AgnUtils.isNumber(line.get(columnIndex))) { isNumeric = false; break; } } columnRightAligned.set(columnIndex, isNumeric); } } @Override public String toString() { List<StringBuilder> columnNamesLines = new ArrayList<StringBuilder>(); for (int lineIndex = 0; lineIndex < columnNames.size(); lineIndex++) { columnNamesLines.add(new StringBuilder()); } List<StringBuilder> contentLines = new ArrayList<StringBuilder>(); for (int lineIndex = 0; lineIndex < content.size(); lineIndex++) { contentLines.add(new StringBuilder()); } // iterate over columns for (int columnIndex = 0 ; columnIndex < columnNames.get(0).size(); columnIndex++) { int size = getMaxSizeOfColumn(columnIndex); for (int lineIndex = 0; lineIndex < columnNames.size(); lineIndex++) { if (columnIndex > 0) columnNamesLines.get(lineIndex).append(" "); columnNamesLines.get(lineIndex).append(trimStringToLengthAlignedLeft(columnNames.get(lineIndex).get(columnIndex), size)); } // iterate over rows for (int lineIndex = 0; lineIndex < content.size(); lineIndex++) { if (columnIndex > 0) contentLines.get(lineIndex).append(" "); if (columnRightAligned.get(columnIndex)) contentLines.get(lineIndex).append(trimStringToLengthAlignedRight(content.get(lineIndex).get(columnIndex), size)); else contentLines.get(lineIndex).append(trimStringToLengthAlignedLeft(content.get(lineIndex).get(columnIndex), size)); } } StringBuilder text = new StringBuilder(); for (int lineIndex = 0 ; lineIndex < columnNamesLines.size(); lineIndex++) { text.append(columnNamesLines.get(lineIndex) + "\n"); } // separate headers text.append(AgnUtils.repeatString("-", columnNamesLines.get(0).length()) + "\n"); for (int lineIndex = 0 ; lineIndex < contentLines.size(); lineIndex++) { text.append(contentLines.get(lineIndex) + "\n"); } return text.toString(); } public String toCsvString() { StringBuilder csvText = new StringBuilder(); // write headers first // iterate over header lines for (int lineIndex = 0; lineIndex < columnNames.size(); lineIndex++) { // iterate over columns for (int columnIndex = 0 ; columnIndex < columnNames.get(0).size(); columnIndex++) { csvText.append("\"" + columnNames.get(lineIndex).get(columnIndex) + "\";"); } csvText.append("\n"); } // write data rows // itearate over rows for (int lineIndex = 0; lineIndex < content.size(); lineIndex++) { // itearate over columns for (int columnIndex = 0 ; columnIndex < content.get(0).size(); columnIndex++) { csvText.append("\"" + content.get(lineIndex).get(columnIndex) + "\";"); } csvText.append("\n"); } return csvText.toString(); } public String toCsvStringWithMetaData() { StringBuilder csvText = new StringBuilder(); // write headers // itearate over header rows for (int lineIndex = 0; lineIndex < columnNames.size(); lineIndex++) { csvText.append("\"" + METADATA_HEADER + "\";"); // itearate over columns for (int columnIndex = 0 ; columnIndex < columnNames.get(0).size(); columnIndex++) { csvText.append("\"" + columnNames.get(lineIndex).get(columnIndex) + "\";"); } csvText.append("\n"); } csvText.append("\"" + METADATA_FARBE + "\";"); for (int columnIndex = 0 ; columnIndex < columnNames.get(0).size(); columnIndex++) { csvText.append("\"" + columnColors.get(columnIndex) + "\";"); } csvText.append("\n"); csvText.append("\"" + METADATA_RIGHTALIGNMENT + "\";"); for (int columnIndex = 0 ; columnIndex < columnNames.get(0).size(); columnIndex++) { csvText.append("\"" + columnRightAligned.get(columnIndex) + "\";"); } csvText.append("\n"); // write data rows // itearate over rows for (int lineIndex = 0; lineIndex < content.size(); lineIndex++) { csvText.append("\"" + lineColors.get(lineIndex) + "\";"); // itearate over columns for (int columnIndex = 0 ; columnIndex < content.get(0).size(); columnIndex++) { // remova leading apostroph String cellContentString = content.get(lineIndex).get(columnIndex); if (cellContentString != null && cellContentString.startsWith("'") && !cellContentString.endsWith("'")) cellContentString = cellContentString.substring(1); csvText.append("\"" + cellContentString + "\";"); } csvText.append("\n"); } return csvText.toString(); } public static String getHtmlHeader(String title) { return getHtmlHeader(title, true, null); } public static String getHtmlHeader(String title, boolean mitZeit) { return getHtmlHeader(title, mitZeit, null); } public static String getHtmlHeader(String title, boolean mitZeit, String inlineCssStyleSheet) { return "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n" + "<html>\n" + "<head>\n<title>" + title + "</title>\n" + (StringUtils.isEmpty(inlineCssStyleSheet) ? "" : inlineCssStyleSheet) + "</head>\n" + "<body>\n" + "<h2>" + title + "</h2>\n" + (mitZeit ? "<h4>Stand: " + new SimpleDateFormat("dd.MM.yyyy HH:mm:ss").format(new GregorianCalendar().getTime()) + "</h4>\n" : ""); } public static String getHtmlFooter() { return "<body>\n" + "<html>\n"; } public String toHtmlString(String tableTitle) { return toHtmlString(tableTitle, 0); } public String toHtmlString(String tableTitle, int fontsizeInPt) { StringBuilder htmlTableStringBuffer = new StringBuilder(); htmlTableStringBuffer.append(StringEscapeUtils.escapeHtml(tableTitle) + "<br>\n"); if (fontsizeInPt > 0) htmlTableStringBuffer.append("<STYLE TYPE=\"text/css\"><!--TD{font-family: Arial; font-size: " + fontsizeInPt + "pt;}---></STYLE>"); htmlTableStringBuffer.append("<table border='1' cellspacing='1' cellpadding='1'>\n"); // Alternative for full width: "<table border='1' width='100%' cellspacing='1' cellpadding='1'>\n"); int rowcount = 0; htmlTableStringBuffer.append("<tr align='center'>"); // itearate over columns for (int columnIndex = 0 ; columnIndex < columnNames.get(0).size(); columnIndex++) { if (columnColors.get(columnIndex) == null) htmlTableStringBuffer.append("<td>"); else htmlTableStringBuffer.append("<td bgcolor='" + convertXlsColor2HtmlColor(columnColors.get(columnIndex)) + "'>"); htmlTableStringBuffer.append(StringEscapeUtils.escapeHtml(columnNames.get(0).get(columnIndex)).replace(" ", " ").replace("-", "‑")); if (columnNames.size() > 1) htmlTableStringBuffer.append("<br/>" + StringEscapeUtils.escapeHtml(columnNames.get(1).get(columnIndex)).replace(" ", " ").replace("-", "‑")); htmlTableStringBuffer.append("</td>"); } htmlTableStringBuffer.append("</tr>\n"); // itearate over rows for (int lineIndex = 0; lineIndex < content.size(); lineIndex++) { if (lineColors.get(lineIndex) != null) htmlTableStringBuffer.append("<tr align='right' bgcolor='" + lineColors.get(lineIndex) + "'>"); else if (rowcount % 2 == 0) htmlTableStringBuffer.append("<tr align='right' bgcolor='cornflowerblue'>"); else htmlTableStringBuffer.append("<tr align='right' bgcolor='lightblue'>"); // itearate over columns for (int columnIndex = 0 ; columnIndex < columnNames.get(0).size(); columnIndex++) { // remove leading apostroph String cellContentString = content.get(lineIndex).get(columnIndex); if (cellContentString != null && cellContentString.startsWith("'") && !cellContentString.endsWith("'")) cellContentString = cellContentString.substring(1); htmlTableStringBuffer.append("<td align='" + (columnRightAligned.get(columnIndex) ? "right" : "left") + "'>" + StringEscapeUtils.escapeHtml(cellContentString).replace(" ", " ").replace("-", "‑") + "</td>"); } htmlTableStringBuffer.append("</tr>\n"); rowcount++; } htmlTableStringBuffer.append("</table>\n"); htmlTableStringBuffer.append("<br>\n"); htmlTableStringBuffer.append("<br>\n"); return htmlTableStringBuffer.toString(); } private int getMaxSizeOfColumn(int index) { int maxSize = 0; for (List<String> line : columnNames) { maxSize = Math.max(line.get(index).length(), maxSize); } for (List<String> line : content) { maxSize = Math.max(line.get(index).length(), maxSize); } return maxSize; } public static String convertXlsColor2HtmlColor(String xlsColor) { if ("VERY_LIGHT_YELLOW".equalsIgnoreCase(xlsColor)) return "yellow"; else if ("LIGHT_GREEN".equalsIgnoreCase(xlsColor)) return "lime"; else if ("LAVENDER".equalsIgnoreCase(xlsColor)) return "fuchsia"; else if ("TAN".equalsIgnoreCase(xlsColor)) return "fuchsia"; else if ("TURQUOISE".equalsIgnoreCase(xlsColor)) return "aqua"; else if ("YELLOW".equalsIgnoreCase(xlsColor)) return "yellow"; else if ("LIGHT_TURQUOISE".equalsIgnoreCase(xlsColor)) return "aqua"; else if ("LIGHT_ORANGE".equalsIgnoreCase(xlsColor)) return "red"; else if ("ROSE".equalsIgnoreCase(xlsColor)) return "fuchsia"; else if ("WOCHENENDE".equalsIgnoreCase(xlsColor)) // special color return "coral"; else return "white"; } public void loadCsvWithMetadataFile(byte[] csvWithMetadata) throws IOException { columnNames.clear(); content.clear(); columnColors.clear(); lineColors.clear(); columnRightAligned.clear(); currentLineIndex = -1; currentColumnIndex = 0; BufferedReader fileReader = null; try { fileReader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(csvWithMetadata), "UTF-8")); String fileLine = null; while ((fileLine = fileReader.readLine()) != null) { String[] lineParts = fileLine.split(";"); for (int i = 0; i < lineParts.length; i++) { if (lineParts[i].startsWith("\"")) lineParts[i] = lineParts[i].substring(1); if (lineParts[i].endsWith("\"")) lineParts[i] = lineParts[i].substring(0, lineParts[i].length() - 1); } if (METADATA_HEADER.equals(lineParts[0])) { List<String> headerLine = new ArrayList<String>(); columnNames.add(headerLine); for (int i = 1; i < lineParts.length; i++) { headerLine.add(lineParts[i]); } } else if (METADATA_FARBE.equals(lineParts[0])) { for (int i = 1; i < lineParts.length; i++) { if (lineParts[i].equalsIgnoreCase("null")) columnColors.add(null); else columnColors.add(lineParts[i]); } } else if (METADATA_RIGHTALIGNMENT.equals(lineParts[0])) { for (int i = 1; i < lineParts.length; i++) { if (lineParts[i].equalsIgnoreCase("true")) columnRightAligned.add(true); else columnRightAligned.add(false); } } else { if (lineParts[0].equalsIgnoreCase("null")) lineColors.add(null); else lineColors.add(lineParts[0]); List<String> contentLine = new ArrayList<String>(); content.add(contentLine); for (int i = 1; i < lineParts.length; i++) { contentLine.add(lineParts[i]); } } } } finally { if (fileReader != null) { try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } fileReader = null; } } public void keepOnlyLastRows(int numberOfLastRows) { while(content.size() > numberOfLastRows) { content.remove(0); } } public void keepOnlyFirstRows(int numberOfFirstRows) { while(content.size() > numberOfFirstRows) { content.remove(content.size() - 1); } } public int getHeaderLineCount() { return columnNames.size(); } public int getColumnCount() { return columnNames.get(0).size(); } public int getDataLineCount() { return content.size(); } public String getHeader(int headerLineIndex, int columnIndex) throws Exception { if (columnNames.size() <= headerLineIndex || columnNames.get(headerLineIndex).size() <= columnIndex) throw new Exception("Ungültige Datenabfrage an Spaltenüberschriften Zeilenindex " + headerLineIndex + " Spaltenindex " + columnIndex); return columnNames.get(headerLineIndex).get(columnIndex); } public String getHeaderColor(int columnIndex) { return columnColors.get(columnIndex); } public String getLineColor(int lineIndex) { return lineColors.get(lineIndex); } public String getData(int lineIndex, int columnIndex) throws Exception { if (content.size() <= lineIndex || content.get(lineIndex).size() <= columnIndex) throw new Exception("Ungültige Datenabfrage an Zeilenindex " + lineIndex + " Spaltenindex " + columnIndex); return content.get(lineIndex).get(columnIndex); } public static String trimStringToLengthAlignedRight(String inputString, int length) { return String.format("%" + length + "s", inputString); } public static String trimStringToLengthAlignedLeft(String inputString, int length) { return String.format("%-" + length + "s", inputString); } }