private void writeReport(String taskListName, EVTaskList evModel,
Date effDate, EVReportSettings settings, EVTaskFilter taskFilter,
int purpose) throws IOException {
EVSchedule schedule = evModel.getSchedule();
double totalPlanTime = schedule.getMetrics().totalPlan();
boolean hideNames = settings.getBool(EVReport.CUSTOMIZE_HIDE_NAMES);
boolean showAssignedTo = (evModel instanceof EVTaskListRollup)
&& !hideNames;
boolean showTimingIcons = (evModel instanceof EVTaskListData
&& !isExporting() && purpose == PLAIN_REPORT);
boolean showMilestones = evModel.showMilestoneColumn();
boolean showLabels = evModel.showLabelsColumn();
int numOptionalCols = (showAssignedTo ? 1 : 0) //
+ (showMilestones ? 1 : 0) + (showLabels ? 1 : 0);
// Calculate the dates one week before and after the effective date.
Date lastWeek = adjustDate(effDate, -EVSchedule.WEEK_MILLIS);
Date nextWeek = adjustDate(effDate, EVSchedule.WEEK_MILLIS);
Date startDate = schedule.getStartDate();
if (lastWeek.before(startDate)) lastWeek = startDate;
Date effDateDisplay = new Date(effDate.getTime() - 1000);
Date nextWeekDisplay = new Date(nextWeek.getTime() - 1000);
// calculate flags describing whether the actual current date falls
// within our reporting period
long now = System.currentTimeMillis();
boolean reportingPeriodIncludesToday = (lastWeek.getTime() < now
&& now <= effDate.getTime());
boolean reportingPeriodPrecedesToday = (effDate.getTime() < now
&& now <= nextWeek.getTime());
// Calculate future cutoff dates for task dependency display
Date dependDate = getFutureCutoffDate(effDate,
Settings.getInt("ev.numDependencyWeeks", 3));
Date revDependDate = getFutureCutoffDate(effDate,
Settings.getInt("ev.numReverseDependencyWeeks", 6));
// Get a slice of the schedule representing the previous week.
EVSchedule filteredSchedule = getEvSchedule(evModel, taskFilter);
EVSchedule.Period weekSlice = EVScheduleRollup.getSlice(
filteredSchedule, lastWeek, effDate);
// Now scan the task list looking for information we need.
TableModel tasks = evModel.getSimpleTableModel(taskFilter);
int taskListLen = tasks.getRowCount();
// keep track of tasks that should be displayed in the three lists.
boolean[] completedLastWeek = new boolean[taskListLen];
boolean[] inProgressThisWeek = new boolean[taskListLen];
boolean[] dueThroughNextWeek = new boolean[taskListLen];
byte[] progress = new byte[taskListLen];
Map<String, DependencyForCoord> upcomingDependencies =
new HashMap<String, DependencyForCoord>();
List<RevDependencyForCoord> reverseDependencies =
new ArrayList<RevDependencyForCoord>();
Arrays.fill(completedLastWeek, false);
Arrays.fill(inProgressThisWeek, false);
Arrays.fill(dueThroughNextWeek, false);
boolean oneCompletedLastWeek = false;
boolean oneInProgressThisWeek = false;
boolean oneDueNextWeek = false;
// keep track of the people assigned to the current schedule
Set allIndividuals = new HashSet();
String ignoreIndividual = null;
if (evModel instanceof EVTaskListData && purpose == PLAIN_REPORT)
allIndividuals.add(ignoreIndividual = getOwner());
// retrieve information about the actual time that was logged to tasks
// during the effective time period
double[] actualTimeThisWeek = getActualTimeSpent(tasks, lastWeek,
effDate);
double completedTasksTimeThisWeek = 0;
double inProgressTasksTimeThisWeek = 0;
// keep track of the two total plan/actual time to date for
// completed tasks.
double completedTasksTotalPlanTime = 0;
double completedTasksTotalActualTime = 0;
for (int i = 0; i < taskListLen; i++) {
Date completed =
(Date) tasks.getValueAt(i, EVTaskList.DATE_COMPLETE_COLUMN);
if (completed != null && completed.before(effDate)) {
completedTasksTotalPlanTime += parseTime
(tasks.getValueAt(i, -EVTaskList.PLAN_DTIME_COLUMN));
completedTasksTotalActualTime += parseTime
(tasks.getValueAt(i, -EVTaskList.ACT_DTIME_COLUMN));
if (!completed.before(lastWeek) &&
completed.before(nextWeek)) {
completedLastWeek[i] = oneCompletedLastWeek = true;
completedTasksTimeThisWeek += actualTimeThisWeek[i];
} else if (actualTimeThisWeek[i] > 0) {
// if the task was marked complete in the past, but
// someone logged time against it this week, display
// it in the "in progress" table.
inProgressThisWeek[i] = oneInProgressThisWeek = true;
inProgressTasksTimeThisWeek += actualTimeThisWeek[i];
}
} else {
Date due =
(Date) tasks.getValueAt(i, EVTaskList.PLAN_DATE_COLUMN);
Date replannedDue =
(Date) tasks.getValueAt(i, EVTaskList.REPLAN_DATE_COLUMN);
Date taskStarted =
(Date) tasks.getValueAt(i, EVTaskList.ACT_START_DATE_COLUMN);
// Check to see if the task was in progress this week
if (taskStarted != null && taskStarted.before(effDate)
&& (completed == null || completed.after(effDate))) {
inProgressThisWeek[i] = oneInProgressThisWeek = true;
inProgressTasksTimeThisWeek += actualTimeThisWeek[i];
}
// Check to see if the task is due next week
if ((due != null && due.after(startDate) && due.before(nextWeek))
|| (replannedDue != null && replannedDue.after(startDate)
&& replannedDue.before(nextWeek))) {
dueThroughNextWeek[i] = oneDueNextWeek = true;
}
if ((inProgressThisWeek[i] || dueThroughNextWeek[i])
&& (due != null)) {
if (!due.after(effDate))
progress[i] = BEHIND_SCHEDULE;
else if (due.after(nextWeek))
progress[i] = AHEAD_OF_SCHEDULE;
}
Date projectedDate = (Date) tasks.getValueAt(i,
EVTaskList.PROJ_DATE_COLUMN);
findUpcomingDependencies(tasks, upcomingDependencies,
i, projectedDate, dependDate, ignoreIndividual);
// don't search for reverse dependencies when we're hiding the
// names of individuals. After all, the only thing we display
// about a reverse dependency is the names of the waiting
// people. If we can't display their names, then we won't
// have any identifying data to show, so there would be no
// point in collecting reverse dependencies.
if (!hideNames)
findReverseDependencies(tasks, reverseDependencies,
revDependDate, i);
}
List assignedTo = (List) tasks.getValueAt(i,
-EVTaskList.ASSIGNED_TO_COLUMN);
if (assignedTo != null)
allIndividuals.addAll(assignedTo);
}
double cpi = completedTasksTotalPlanTime/completedTasksTotalActualTime;
boolean showTimeThisWeek = (completedTasksTimeThisWeek > 0
|| inProgressTasksTimeThisWeek > 0);
/*
* Okay, we have all the data we need. Lets generate the HTML.
*/
if (isTopLevel(purpose)) {
String taskListDisplayName = EVTaskList.cleanupName(taskListName);
String titleHTML = resources.format("Title_FMT", taskListDisplayName);
titleHTML = HTMLUtils.escapeEntities(titleHTML);
StringBuffer header = new StringBuffer(HEADER_HTML);
StringUtils.findAndReplace(header, TITLE_VAR, titleHTML);
if (taskFilter != null)
header.insert(header.indexOf("</head>"), FILTER_HEADER_HTML);
if (isExportingToExcel())
StringUtils.findAndReplace(header, "hideIfCollapsed", "ignore");
out.print(header);
out.print("<h2>");
String endDateStr = encodeHTML(effDateDisplay);
out.print(resources.format("Header_HTML_FMT", endDateStr));
if (!isExporting() || getParameter(EFF_DATE_PARAM) == null) {
if (lastWeek.compareTo(startDate) > 0)
printNavLink(lastWeek, "Previous", settings, purpose);
printNavLink(nextWeek, "Next", settings, purpose);
if (!isExporting())
printGoToDateLink(effDate, schedule, settings, purpose);
}
out.print("</h2>\n");
EVReport.printFilterInfo(out, taskFilter, isExportingToExcel());
EVReport.printScheduleErrors(out, filteredSchedule.getMetrics().getErrors());
} else {
out.print("<div class='");
out.print(purpose == LEAF_REPORT ? "collapsed" : "expanded");
out.print("'><h2>");