/*
* This file is part of LibrePlan
*
* Copyright (C) 2013 St. Antoniusziekenhuis
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.libreplan.importers;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.joda.time.LocalDate;
import org.libreplan.business.resources.entities.Worker;
import org.libreplan.business.workingday.EffortDuration;
import org.libreplan.business.workingday.IntraDayDate.PartialDay;
import org.libreplan.importers.tim.RosterDTO;
/**
* Class to convert the Roster response DTO to the <code>RosterException<code>
*
* @author Miciele Ghiorghis <m.ghiorghis@antoniusziekenhuis.nl>
*/
public class RosterException {
private Worker worker;
private int productivityFactor;
List<RosterExceptionItem> rosterExceptionItems = new ArrayList<RosterExceptionItem>();
public RosterException(Worker worker, int productivityFactor) {
this.worker = worker;
this.productivityFactor = productivityFactor;
}
/**
* Reads the rosters and add the exceptions to
* <code>rosterExceptionItems</code>
*
* @param rosterDTOs
* list of rosterDTO
*/
public void addRosterExceptions(List<RosterDTO> rosterDTOs) {
Map<LocalDate, List<RosterDTO>> mapDateRosterDTO = new TreeMap<LocalDate, List<RosterDTO>>();
for (RosterDTO rosterDTO : rosterDTOs) {
if (!mapDateRosterDTO.containsKey(rosterDTO.getDate())) {
mapDateRosterDTO.put(rosterDTO.getDate(), new ArrayList<RosterDTO>());
}
mapDateRosterDTO.get(rosterDTO.getDate()).add(rosterDTO);
}
for (Map.Entry<LocalDate, List<RosterDTO>> entry : mapDateRosterDTO
.entrySet()) {
RosterExceptionItem item = new RosterExceptionItem(entry.getKey());
updateExceptionTypeAndEffort(item, entry.getValue());
rosterExceptionItems.add(item);
}
}
/**
* updates the <code>exceptionType</code> and <code>effortDuration</code>
*
* In Tim you can divide your exception day in different
* <code>exceptionType</code>, for example on Monday:
* <ul>
* <li>4 hours RESOURCE_HOLIDAY</li>
* <li>2 hours STRIKE</li>
* <li>2 hours BANK_HOLIDAY</li>
* </ul>
*
* But Libreplan allows only one <code>exceptionType</code> per day.
*
* In order to store different <code>exceptionTypes</code> per day as one
* <code>exceptionType</code>, this method gets the
* <code>exceptionType</code> from the <code>rosterDTO</code> with the
* highest duration, in this example RESOURCE_HOLIDAY as a valid exception
* type, but the total duration is the sum of all these exception types
*
* Again in Tim this total duration means that the worker is on holiday for
* that total duration, but Libreplan does the opposite. In Libreplan, the
* total duration in this case means that the worker is not on holiday. If
* he is then the total duration should be Zero. And this method does this
* translation
*
* @param rosterExceptionItem
* the rosterException item
* @param rosterDTOs
* list of rosterDTO
*/
private void updateExceptionTypeAndEffort(
RosterExceptionItem rosterExceptionItem, List<RosterDTO> rosterDTOs) {
EffortDuration max = EffortDuration.zero();
EffortDuration sum = EffortDuration.zero();
String rosterCatName = rosterDTOs.get(0).getRosterCategories().get(0)
.getName();
for (RosterDTO rosterDTO : rosterDTOs) {
EffortDuration duration = EffortDuration
.parseFromFormattedString(rosterDTO.getDuration());
if (duration.compareTo(max) > 0) {
rosterCatName = rosterDTO.getRosterCategories().get(0)
.getName();
}
max = EffortDuration.max(max, duration);
sum = EffortDuration.sum(sum, duration);
}
EffortDuration exceptionTime = EffortDuration.zero();
EffortDuration workableTime = worker.getCalendar().getCapacityOn(
PartialDay.wholeDay(rosterExceptionItem.getDate()));
// Convert the total duration from Tim to the productivity time as is
// configured in resource calendar
EffortDuration productivityTime = sum.multiplyBy(productivityFactor)
.divideBy(100);
// Calculate the exception time
if (workableTime.compareTo(productivityTime) >= 0) {
exceptionTime = workableTime.minus(productivityTime);
}
rosterExceptionItem.setExceptionType(rosterCatName);
rosterExceptionItem.setEffortDuration(exceptionTime);
}
/**
* returns {@link Worker}
*/
public Worker getWorker() {
return worker;
}
/**
* returns list of {@link RosterExceptionItem}
*/
public List<RosterExceptionItem> getRosterExceptionItems() {
return rosterExceptionItems;
}
/**
* class representing RosterExceptionItem
*/
public class RosterExceptionItem {
private LocalDate date;
private String exceptionType;
private EffortDuration effortDuration;
public RosterExceptionItem(LocalDate date) {
this.date = date;
}
public LocalDate getDate() {
return date;
}
public String getExceptionType() {
return exceptionType;
}
public void setExceptionType(String exceptionType) {
this.exceptionType = exceptionType;
}
public EffortDuration getEffortDuration() {
return effortDuration;
}
public void setEffortDuration(EffortDuration effortDuration) {
this.effortDuration = effortDuration;
}
}
}