package com.metservice.kanban.model; import static java.util.Collections.unmodifiableCollection; import static org.apache.commons.lang.SystemUtils.LINE_SEPARATOR; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; //TODO This class needs more unit tests. public class KanbanBoard implements Iterable<KanbanBoardRow> { private final KanbanBoardColumnList columns; private final List<KanbanBoardRow> rows = new ArrayList<KanbanBoardRow>(); public KanbanBoard(KanbanBoardColumnList columns) { this.columns = columns; } public void merge(KanbanBoard otherBoard) { extendLength(otherBoard.rows.size()); mergeRows(otherBoard); } private void extendLength(int newLength) { for (int i = rows.size(); i < newLength; i++) { KanbanBoardRow blankRow = new KanbanBoardRow(columns); rows.add(blankRow); } } private void mergeRows(KanbanBoard otherBoard) { for (int i = 0; i < otherBoard.rows.size(); i++) { KanbanBoardRow destination = rows.get(i); KanbanBoardRow source = otherBoard.rows.get(i); destination.merge(source); } } public void stack(KanbanBoard otherBoard) { for (KanbanBoardRow row : otherBoard) { rows.add(row.clone()); } } public void insert(WorkItem workItem, WorkItem workItemAbove, WorkItem workItemBelow, WorkItem workItemTop) { KanbanBoardRow targetRow = null; for (KanbanBoardRow row : this) { if (row.canAdd(workItem)) { targetRow = row; break; } } if (targetRow == null) { // no space: add a new row targetRow = new KanbanBoardRow(columns); rows.add(targetRow); } targetRow.insert(workItem, workItemAbove, workItemBelow, workItemTop); } @Override public Iterator<KanbanBoardRow> iterator() { return unmodifiableCollection(rows).iterator(); } public KanbanCell getCell(int rowIndex, int columnIndex) { return rows.get(rowIndex).getCell(columnIndex); } @Override public String toString() { StringBuilder builder = new StringBuilder(); for (KanbanBoardRow row : this) { builder.append(row); builder.append(LINE_SEPARATOR); } return builder.toString(); } private Map<String, Integer> itemsInColumn; public synchronized Map<String, Integer> getItemsInColumn() { if (itemsInColumn == null) { itemsInColumn = computeItemsInColumn(); } return itemsInColumn; } private Map<String, Integer> computeItemsInColumn() { Map<String, Integer> result = new HashMap<String, Integer>(); for (KanbanBoardRow row : rows) { int column = 0; for (KanbanCell cell : row) { if (!cell.isEmptyCell()) { String columnName = row.getColumns().get(column).getPhase(); int previous = 0; if (result.containsKey(columnName)) { previous = result.get(columnName); } result.put(columnName, previous + 1); } column++; } } return result; } // required by JSP as c:forEach cannot iterate using Iterable public Iterator<KanbanBoardRow> getIterator() { return iterator(); } }