package com.metservice.kanban.charts.cumulativeflow; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.joda.time.LocalDate; import com.metservice.kanban.model.WorkItem; import com.metservice.kanban.utils.WorkingDayUtils; public class CumulativeFlowChartMatrix { private Map<LocalDate, Map<String, Integer>> map; private List<String> phases; private LocalDate startDate; private LocalDate endDate; // add start date and end date instead of "reference date" here public CumulativeFlowChartMatrix(List<String> phases, LocalDate startDate, LocalDate endDate) { this.phases = phases; this.startDate = startDate; this.endDate = endDate; map = new HashMap<LocalDate, Map<String, Integer>>(); } public void registerWorkItem(WorkItem workItem) { if (workItem.isExcluded()) { return; } String phase = phases.get(0); LocalDate localDate = workItem.getDate(phase); while (!localDate.isAfter(endDate)) { if (phases.contains(phase) && WorkingDayUtils.isWorkingDay(localDate)) { register(localDate, phase); } localDate = nextWorkingDay(localDate); phase = workItem.getPhaseOnDate(localDate); } } public double[][] getData() { List<LocalDate> dates = getOrderedListOfDates(); double[][] data = new double[phases.size()][dates.size()]; int phaseIndex = phases.size() - 1; for (String phase : phases) { int dateIndex = 0; for (LocalDate date : dates) { data[phaseIndex][dateIndex] = getQuantityOfItemsOnDateAndPhase(date, phase); dateIndex++; } phaseIndex--; } return data; } private LocalDate nextWorkingDay(LocalDate date) { LocalDate nextDay = date.plusDays(1); while (!WorkingDayUtils.isWorkingDay(nextDay)) { nextDay = nextDay.plusDays(1); } return nextDay; } public Integer getQuantityOfItemsOnDateAndPhase(LocalDate date, String phase) { Map<String, Integer> phaseIntegerMap = map.get(date); if (phaseIntegerMap == null) { return 0; } Integer result = phaseIntegerMap.get(phase); return result == null ? 0 : result; } private void register(LocalDate date, String phase) { Map<String, Integer> phaseIntegerMap = map.get(date); if (phaseIntegerMap == null) { phaseIntegerMap = new HashMap<String, Integer>(); } Integer count = phaseIntegerMap.get(phase); if (count == null) { count = 0; } phaseIntegerMap.put(phase, count + 1); map.put(date, phaseIntegerMap); } // limit dates to between start and end dates only @SuppressWarnings("unchecked") public List<LocalDate> getOrderedListOfDates() { List<LocalDate> dates = new ArrayList<LocalDate>(map.keySet()); Collections.sort(dates); // make sure there are index values for the sublist LocalDate startDateCorrected = WorkingDayUtils.nextWorkingDay(startDate); LocalDate endDateCorrected = WorkingDayUtils.nextWorkingDay(endDate); int startIndex = dates.indexOf(startDateCorrected) == -1 ? 0 : dates.indexOf(startDateCorrected); int endIndex = dates.indexOf(endDateCorrected) == -1 ? dates.size() : dates.indexOf(endDateCorrected) + 1; if (endIndex > dates.size()) { endIndex = dates.size(); } dates = dates.subList(startIndex, endIndex); return dates; } }