package fit.decorator.util; import java.text.ParseException; import fit.Parse; import fit.decorator.exceptions.InvalidInputException; public class Table { private final Parse table; public Table(Parse table) { this.table = table; } public Table(String html) throws ParseException { this.table = new Parse(html); } public Parse incrementColumnValues(int numberOfTimes, String columnName, Delta delta) throws InvalidInputException { int headerRowIndex = rowNumberContainingText(columnName); copyAndAppendLastRow(numberOfTimes - 1); incrementColumnValues(columnName, delta, headerRowIndex); return table; } public void insertAsFirstRow(Parse firstRow) { firstRow.more = table.parts; table.parts = firstRow; } public Parse stripFirstRow() { Parse firstRow = table.parts; table.parts = table.parts.more; return firstRow; } @Override public String toString() { return toSimpleText(table, new StringBuffer()); } int columnNumberContainingText(String columnName, int headerRowIndex) throws InvalidInputException { int columnNumber = -1; Parse columns = table.at(0, headerRowIndex, 0); while (columns != null) { columnNumber++; if (columnName.equals(columns.text())) { return columnNumber; } columns = columns.more; } throw new InvalidInputException(errorMsg(columnName)); } String columnValue(int rowIndex, int columnIndex) { return table.at(0, rowIndex, columnIndex).text(); } public void copyAndAppendLastRow(int numberOfTimes) { if (numberOfTimes > 0 && tableHasMoreThanTwoRows()) { Parse lastRow = lastRow(); Parse secondLastRow = secondLastRow(lastRow); copyAndAppend(lastRow, numberOfTimes); secondLastRow.more = lastRow; } } void incrementColumnValues(String columnName, Delta delta, int headerRowIndex) throws InvalidInputException { int columnNumber = columnNumberContainingText(columnName, headerRowIndex); int totalNumberOfRows = numberOfRows(); for (int i = headerRowIndex + 2; i < totalNumberOfRows; ++i) { Parse columnToBeUpdated = table.at(0, i, columnNumber); String value = columnToBeUpdated.text(); value = delta.addTo(value, i - headerRowIndex - 1); columnToBeUpdated.body = value; } } Parse lastRow() { return table.parts.last(); } int numberOfRows() { return table.parts.size(); } int rowNumberContainingText(String searchText) throws InvalidInputException { Parse rows = table.at(0, 0); int numberOfRows = rows.size(); for (int i = 0; i < numberOfRows; i++) { Parse columns = table.at(0, i, 0); int numberOfColumns = columns.size(); for (int j = 0; j < numberOfColumns; ++j) { if (searchText.equals(table.at(0, i, j).text())) { return i; } } } throw new InvalidInputException(errorMsg(searchText)); } Parse secondLastRow(Parse lastRow) { Parse nextRow = table.parts; Parse currentRow = null; while (nextRow != lastRow) { currentRow = nextRow; nextRow = nextRow.more; } if (currentRow != null) { currentRow.more = null; } return currentRow; } private void copyAndAppend(Parse lastRow, int numberOfTimes) { for (int i = 0; i < numberOfTimes; i++) { Parse columns = lastRow.parts; Parse nextColumn = columns.more; Parse newNextColumn = newParse(nextColumn, nextColumn.more); Parse newColumn = newParse(columns, newNextColumn); Parse newRow = new Parse(stripAngularBrackets(lastRow.tag), lastRow.body, newColumn, null); lastRow.last().more = newRow; } } private Parse newParse(Parse columns, Parse nextColumn) { return new Parse(stripAngularBrackets(columns.tag), columns.body, columns.parts, nextColumn); } private String errorMsg(String searchText) { return "'" + searchText + "' was not found in the table " + toString(); } private void simpleTextOfLeave(Parse table, StringBuffer returnText) { returnText.append(table.tag).append(table.text()).append(table.end); } private void simpleTextOfMore(Parse table, StringBuffer returnText) { if ((table.more != null)) { toSimpleText(table.more, returnText); } } private void simpleTextOfParts(Parse table, StringBuffer returnText) { returnText.append(table.tag); toSimpleText(table.parts, returnText); returnText.append(table.end); } private String stripAngularBrackets(String tag) { return tag.substring(1, tag.length() - 1); } private String toSimpleText(Parse table, StringBuffer returnText) { if (table.parts == null) { simpleTextOfLeave(table, returnText); simpleTextOfMore(table, returnText); return returnText.toString(); } simpleTextOfParts(table, returnText); simpleTextOfMore(table, returnText); return returnText.toString(); } public Parse table() { return table; } public Parse incrementColumnValuesByDelta(String columnName, Delta delta) throws InvalidInputException { int headerRowIndex = rowNumberContainingText(columnName); incrementColumnValues(columnName, delta, headerRowIndex); return table; } private boolean tableHasMoreThanTwoRows() { return (table.parts.size() > 2); } }