/*
* This file is part of LibrePlan
*
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L.
*
* 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.ws.resources.impl;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.libreplan.business.calendars.entities.CalendarAvailability;
import org.libreplan.business.calendars.entities.ResourceCalendar;
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
import org.libreplan.business.common.exceptions.MultipleInstancesException;
import org.libreplan.business.common.exceptions.ValidationException;
import org.libreplan.business.costcategories.entities.ResourcesCostCategoryAssignment;
import org.libreplan.business.resources.entities.CriterionSatisfaction;
import org.libreplan.business.resources.entities.CriterionType;
import org.libreplan.business.resources.entities.Machine;
import org.libreplan.business.resources.entities.Resource;
import org.libreplan.business.resources.entities.Worker;
import org.libreplan.ws.calendars.api.BaseCalendarDTO;
import org.libreplan.ws.calendars.impl.CalendarConverter;
import org.libreplan.ws.common.impl.DateConverter;
import org.libreplan.ws.common.impl.InstanceNotFoundRecoverableErrorException;
import org.libreplan.ws.costcategories.api.CostCategoryDTO;
import org.libreplan.ws.resources.api.CalendarAvailabilityDTO;
import org.libreplan.ws.resources.api.CriterionSatisfactionDTO;
import org.libreplan.ws.resources.api.MachineDTO;
import org.libreplan.ws.resources.api.ResourceCalendarDTO;
import org.libreplan.ws.resources.api.ResourceDTO;
import org.libreplan.ws.resources.api.ResourcesCostCategoryAssignmentDTO;
import org.libreplan.ws.resources.api.WorkerDTO;
import org.libreplan.ws.resources.criterion.api.CriterionDTO;
import org.libreplan.ws.resources.criterion.api.CriterionTypeDTO;
/**
* Converter from/to resource-related entities to/from DTOs.
*
* @author Fernando Bellas Permuy <fbellas@udc.es>
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/
public class ResourceConverter {
private ResourceConverter() {
}
public static final Resource toEntity(ResourceDTO resourceDTO) {
checkResourceDTOType(resourceDTO);
Resource resource;
if (resourceDTO instanceof MachineDTO) {
resource = createResourceWithBasicData((MachineDTO) resourceDTO);
} else {
resource = createResourceWithBasicData((WorkerDTO) resourceDTO);
}
addCriterionSatisfactions(resource, resourceDTO.criterionSatisfactions);
setResourceCalendar(resource, resourceDTO.calendar);
addResourcesCostCategoryAssignments(resource, resourceDTO.resourcesCostCategoryAssignments);
return resource;
}
public static final void updateResource(Resource resource, ResourceDTO resourceDTO) {
checkResourceDTOType(resourceDTO);
updateBasicData(resource, resourceDTO);
updateResourceCalendar(resource, resourceDTO.calendar);
updateCriterionSatisfactions(resource, resourceDTO.criterionSatisfactions);
updateResourcesCostCategoryAssignments(resource, resourceDTO.resourcesCostCategoryAssignments);
}
private static final Machine createResourceWithBasicData(MachineDTO machineDTO) {
return Machine.createUnvalidated(
StringUtils.trim(machineDTO.code),
StringUtils.trim(machineDTO.name),
StringUtils.trim(machineDTO.description));
}
private static final Worker createResourceWithBasicData(WorkerDTO workerDTO) {
return Worker.createUnvalidated(
StringUtils.trim(workerDTO.code),
StringUtils.trim(workerDTO.firstName),
StringUtils.trim(workerDTO.surname),
StringUtils.trim(workerDTO.nif));
}
private static void addCriterionSatisfactions(Resource resource, List<CriterionSatisfactionDTO> criterionSatisfactions) {
for (CriterionSatisfactionDTO criterionSatisfactionDTO : criterionSatisfactions) {
CriterionSatisfaction criterionSatisfaction = toEntity(criterionSatisfactionDTO, resource);
resource.addUnvalidatedSatisfaction(criterionSatisfaction);
}
}
private static CriterionSatisfaction toEntity(CriterionSatisfactionDTO criterionSatisfactionDTO, Resource resource) {
if (StringUtils.isBlank(criterionSatisfactionDTO.criterionTypeName)) {
throw new ValidationException("criterion type name not specified");
}
if (StringUtils.isBlank(criterionSatisfactionDTO.criterionName)) {
throw new ValidationException("criterion name not specified");
}
try {
return CriterionSatisfaction.createUnvalidated(
StringUtils.trim(criterionSatisfactionDTO.code),
StringUtils.trim(criterionSatisfactionDTO.criterionTypeName),
StringUtils.trim(criterionSatisfactionDTO.criterionName),
resource,
DateConverter.toLocalDate(criterionSatisfactionDTO.startDate),
DateConverter.toLocalDate(criterionSatisfactionDTO.endDate));
} catch (InstanceNotFoundException e) {
if (e.getClassName().equals(CriterionType.class.getName())) {
throw new InstanceNotFoundRecoverableErrorException(CriterionTypeDTO.ENTITY_TYPE, e.getKey().toString());
} else {
throw new InstanceNotFoundRecoverableErrorException(CriterionDTO.ENTITY_TYPE, e.getKey().toString());
}
}
}
private static void setResourceCalendar(Resource resource, ResourceCalendarDTO calendar) {
String calendarCode = null;
if (calendar != null) {
calendarCode = calendar.parent;
}
try {
resource.setResourceCalendar(StringUtils.trim(calendarCode));
// Copy the data of the resource calendar DTO
updateBasicPropertiesResourceCalendar(calendar, resource.getCalendar());
} catch (InstanceNotFoundException e) {
throw new InstanceNotFoundRecoverableErrorException(ResourceCalendarDTO.ENTITY_TYPE, e.getKey().toString());
} catch (MultipleInstancesException e) {
throw new ValidationException(MessageFormat.format(
"there exist multiple resource calendars with name {0}", calendarCode));
}
}
private static void updateBasicPropertiesResourceCalendar(ResourceCalendarDTO calendarDTO, ResourceCalendar calendar) {
if (calendarDTO != null) {
if (!StringUtils.isBlank(calendarDTO.name)) {
calendar.setName(calendarDTO.name);
}
if (!StringUtils.isBlank(calendarDTO.code)) {
calendar.setCode(calendarDTO.code);
} else {
throw new ValidationException("missing code in the resource calendar");
}
if (calendarDTO.capacity != null) {
calendar.setCapacity(calendarDTO.capacity);
}
}
}
private static void addResourcesCostCategoryAssignments(
Resource resource, List<ResourcesCostCategoryAssignmentDTO> resourcesCostCategoryAssignments) {
for (ResourcesCostCategoryAssignmentDTO assignmentDTO : resourcesCostCategoryAssignments) {
ResourcesCostCategoryAssignment assignment = toEntity(assignmentDTO, resource);
resource.addUnvalidatedResourcesCostCategoryAssignment(assignment);
}
}
private static ResourcesCostCategoryAssignment toEntity(
ResourcesCostCategoryAssignmentDTO assignmentDTO, Resource resource) {
if (StringUtils.isBlank(assignmentDTO.costCategoryName)) {
throw new ValidationException("cost category name not specified");
}
try {
return ResourcesCostCategoryAssignment.createUnvalidated(
assignmentDTO.code,
StringUtils.trim(assignmentDTO.costCategoryName), resource,
DateConverter.toLocalDate(assignmentDTO.startDate),
DateConverter.toLocalDate(assignmentDTO.endDate));
} catch (InstanceNotFoundException e) {
throw new InstanceNotFoundRecoverableErrorException(CostCategoryDTO.ENTITY_TYPE, e.getKey().toString());
}
}
private static void updateBasicData(Resource resource,
ResourceDTO resourceDTO) {
if (resource instanceof Machine && resourceDTO instanceof MachineDTO) {
Machine machine = (Machine) resource;
MachineDTO machineDTO = (MachineDTO) resourceDTO;
machine.updateUnvalidated(StringUtils.trim(machineDTO.name), StringUtils.trim(machineDTO.description));
} else if (resource instanceof Worker && resourceDTO instanceof WorkerDTO) {
Worker worker = (Worker) resource;
WorkerDTO workerDTO = (WorkerDTO) resourceDTO;
worker.updateUnvalidated(
StringUtils.trim(workerDTO.firstName),
StringUtils.trim(workerDTO.surname),
StringUtils.trim(workerDTO.nif));
} else {
throw new ValidationException(MessageFormat.format(
"Incompatible update: stored resource is not of type: {0}", resourceDTO.getEntityType()));
}
}
/** Do not remove parameters */
private static void updateResourceCalendar(Resource resource, ResourceCalendarDTO calendarDTO) {
// TODO Decide policy to update calendar
// (e.g. previous calendar must be removed?, if new calendar is the same as previous, must be reinitialized again?, etc.)
}
private static void updateCriterionSatisfactions(
Resource resource, List<CriterionSatisfactionDTO> criterionSatisfactions) {
for (CriterionSatisfactionDTO i : criterionSatisfactions) {
try {
CriterionSatisfaction criterionSatisfaction = resource.getCriterionSatisfactionByCode(i.code);
updateCriterionSatisfaction(criterionSatisfaction, i);
} catch (InstanceNotFoundException e) {
CriterionSatisfaction criterionSatisfaction = toEntity(i, resource);
resource.addUnvalidatedSatisfaction(criterionSatisfaction);
}
}
}
private static void updateCriterionSatisfaction(
CriterionSatisfaction criterionSatisfaction, CriterionSatisfactionDTO criterionSatisfactionDTO) {
try {
criterionSatisfaction.updateUnvalidated(
StringUtils.trim(criterionSatisfactionDTO.criterionTypeName),
StringUtils.trim(criterionSatisfactionDTO.criterionName),
DateConverter.toLocalDate(criterionSatisfactionDTO.startDate),
DateConverter.toLocalDate(criterionSatisfactionDTO.endDate));
} catch (InstanceNotFoundException e) {
if (e.getClassName().equals(CriterionType.class.getName())) {
throw new InstanceNotFoundRecoverableErrorException(CriterionTypeDTO.ENTITY_TYPE, e.getKey().toString());
} else {
throw new InstanceNotFoundRecoverableErrorException(CriterionDTO.ENTITY_TYPE, e.getKey().toString());
}
}
}
private static void updateResourcesCostCategoryAssignments(
Resource resource, List<ResourcesCostCategoryAssignmentDTO> resourcesCostCategoryAssignments) {
for (ResourcesCostCategoryAssignmentDTO i : resourcesCostCategoryAssignments) {
try {
ResourcesCostCategoryAssignment assignment = resource.getResourcesCostCategoryAssignmentByCode(i.code);
updateResourcesCostCategoryAssignment(assignment, i);
} catch (InstanceNotFoundException e) {
ResourcesCostCategoryAssignment assignment = toEntity(i, resource);
resource.addUnvalidatedResourcesCostCategoryAssignment(assignment);
}
}
}
private static void updateResourcesCostCategoryAssignment(
ResourcesCostCategoryAssignment assignment, ResourcesCostCategoryAssignmentDTO i) {
try {
assignment.updateUnvalidated(
StringUtils.trim(i.costCategoryName),
DateConverter.toLocalDate(i.startDate),
DateConverter.toLocalDate(i.endDate));
} catch (InstanceNotFoundException e) {
throw new InstanceNotFoundRecoverableErrorException(CostCategoryDTO.ENTITY_TYPE, e.getKey().toString());
}
}
private static void checkResourceDTOType(ResourceDTO resourceDTO) {
if (!(resourceDTO instanceof MachineDTO) && !(resourceDTO instanceof WorkerDTO)) {
throw new ValidationException(MessageFormat.format(
"Service does not manage resource of type: {0}", resourceDTO.getEntityType()));
}
}
public static ResourceDTO toDTO(Resource resource) {
ResourceDTO resourceDTO;
if (resource instanceof Worker) {
resourceDTO = toDTO((Worker) resource);
} else if (resource instanceof Machine) {
resourceDTO = toDTO((Machine) resource);
} else {
return null;
}
List<CriterionSatisfactionDTO> criterionSatisfactionDTOs = new ArrayList<>();
for (CriterionSatisfaction criterionSatisfaction : resource.getCriterionSatisfactions()) {
criterionSatisfactionDTOs.add(toDTO(criterionSatisfaction));
}
resourceDTO.criterionSatisfactions = criterionSatisfactionDTOs;
List<ResourcesCostCategoryAssignmentDTO> resourcesCostCategoryAssignmentDTOs = new ArrayList<>();
for (ResourcesCostCategoryAssignment resourcesCostCategoryAssignment : resource.getResourcesCostCategoryAssignments()) {
resourcesCostCategoryAssignmentDTOs.add(toDTO(resourcesCostCategoryAssignment));
}
resourceDTO.resourcesCostCategoryAssignments = resourcesCostCategoryAssignmentDTOs;
resourceDTO.calendar = toDTO(resource.getCalendar());
return resourceDTO;
}
private static WorkerDTO toDTO(Worker worker) {
return new WorkerDTO(worker.getCode(), worker.getFirstName(), worker.getSurname(), worker.getNif());
}
private static MachineDTO toDTO(Machine machine) {
return new MachineDTO(machine.getCode(), machine.getName(), machine.getDescription());
}
private static CriterionSatisfactionDTO toDTO(CriterionSatisfaction criterionSatisfaction) {
return new CriterionSatisfactionDTO(
criterionSatisfaction.getCode(),
criterionSatisfaction.getCriterion().getType().getName(),
criterionSatisfaction.getCriterion().getName(),
DateConverter.toXMLGregorianCalendar(criterionSatisfaction.getStartDate()),
DateConverter.toXMLGregorianCalendar(criterionSatisfaction.getEndDate()));
}
private static ResourcesCostCategoryAssignmentDTO toDTO(ResourcesCostCategoryAssignment resourcesCostCategoryAssignment) {
Date initDate = (resourcesCostCategoryAssignment.getInitDate() == null)
? null
: resourcesCostCategoryAssignment.getInitDate().toDateTimeAtStartOfDay().toDate();
Date endDate = (resourcesCostCategoryAssignment.getEndDate() == null)
? null
: resourcesCostCategoryAssignment.getEndDate().toDateTimeAtStartOfDay().toDate();
return new ResourcesCostCategoryAssignmentDTO(
resourcesCostCategoryAssignment.getCode(),
resourcesCostCategoryAssignment.getCostCategory().getName(),
DateConverter.toXMLGregorianCalendar(initDate),
DateConverter.toXMLGregorianCalendar(endDate));
}
public static ResourceCalendarDTO toDTO(ResourceCalendar calendar) {
BaseCalendarDTO baseCalendarDTO = CalendarConverter.toDTO(calendar);
List<CalendarAvailabilityDTO> calendarAvailabilityDTOs = new ArrayList<>();
for (CalendarAvailability calendarAvailability : calendar.getCalendarAvailabilities()) {
calendarAvailabilityDTOs.add(toDTO(calendarAvailability));
}
return new ResourceCalendarDTO(
baseCalendarDTO.code, baseCalendarDTO.name, baseCalendarDTO.parent,
calendar.getCapacity(), baseCalendarDTO.calendarExceptions, baseCalendarDTO.calendarData,
calendarAvailabilityDTOs);
}
private static CalendarAvailabilityDTO toDTO(CalendarAvailability calendarAvailability) {
Date startDate = calendarAvailability.getStartDate().toDateTimeAtStartOfDay().toDate();
Date endDate = null;
if (calendarAvailability.getEndDate() != null) {
endDate = calendarAvailability.getEndDate().toDateTimeAtStartOfDay().toDate();
}
return new CalendarAvailabilityDTO(calendarAvailability.getCode(), startDate, endDate);
}
}