ItEr47S12CUImportacionRecursosProductivosItEr46S13: Added updating functionality to ResourceServiceREST
Updating functionality has been added to ResourceServiceREST. All data associated to a resource can be updated with the exception of the calendar field, since the updating semantics are only clearly defined for such field at this moment (what happens with the previous derived calendar: modified?, removed?, disabled?). As part of this patch, some improvements to CriterionServiceREST implementation have also been made. In particular, updateUnvalidated methods has been added to related entities (as in ResourceServiceREST). Unlike createUnvalidated methods, such methods are used for updating, and like createUnvalidated methods, non-valid fields are allowed. Finally, performance of GenericRESTService has been improved. Previously, validations were executed twice for each entity being imported due to previous limitations of IGenericDAO interface. Now, a new method has been added to IGenericDAO to make possible to execute validations only one time for each entity being imported.
This commit is contained in:
parent
c9ea9ea65d
commit
664d7a8f63
17 changed files with 580 additions and 85 deletions
|
|
@ -94,6 +94,10 @@ public class GenericDAOHibernate<E extends BaseEntity,
|
|||
entity.validate();
|
||||
}
|
||||
|
||||
public void saveWithoutValidating(E entity) {
|
||||
getSession().saveOrUpdate(entity);
|
||||
}
|
||||
|
||||
public void reattachUnmodifiedEntity(E entity) {
|
||||
|
||||
getSession().lock(entity, LockMode.NONE);
|
||||
|
|
|
|||
|
|
@ -55,6 +55,11 @@ public interface IGenericDAO <E, PK extends Serializable>{
|
|||
*/
|
||||
public void save(E entity) throws ValidationException;
|
||||
|
||||
/**
|
||||
* Unlike <code>save</code>, it does not execute validations.
|
||||
*/
|
||||
public void saveWithoutValidating(E entity);
|
||||
|
||||
/**
|
||||
* It reattaches the entity to the current session. This method bypasses
|
||||
* hibernate validations and must only be used on read only transaction
|
||||
|
|
|
|||
|
|
@ -77,6 +77,27 @@ public class ResourcesCostCategoryAssignment extends IntegrationEntity {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InstanceNotFoundException if cost category does not exist
|
||||
*/
|
||||
public void updateUnvalidated(String costCategoryName, LocalDate initDate,
|
||||
LocalDate endDate) throws InstanceNotFoundException {
|
||||
|
||||
if (!StringUtils.isBlank(costCategoryName)) {
|
||||
this.costCategory = Registry.getCostCategoryDAO().
|
||||
findUniqueByName(costCategoryName);
|
||||
}
|
||||
|
||||
if (initDate != null) {
|
||||
this.initDate = initDate;
|
||||
}
|
||||
|
||||
if (endDate != null) {
|
||||
this.endDate = endDate;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@NotNull(message="cost assignment's start date not specified")
|
||||
public LocalDate getInitDate() {
|
||||
return initDate;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import java.util.Date;
|
|||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.hibernate.validator.AssertTrue;
|
||||
|
|
@ -61,6 +62,18 @@ public class Criterion extends IntegrationEntity implements ICriterion {
|
|||
|
||||
}
|
||||
|
||||
public void updateUnvalidated(String name, Boolean active) {
|
||||
|
||||
if (!StringUtils.isBlank(name)) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
if (active != null) {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static Criterion create(CriterionType type) {
|
||||
return create(new Criterion(type));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ package org.navalplanner.business.resources.entities;
|
|||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang.builder.ToStringBuilder;
|
||||
import org.hibernate.validator.AssertTrue;
|
||||
|
|
@ -104,6 +105,43 @@ public class CriterionSatisfaction extends IntegrationEntity {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InstanceNotFoundException if criterion type or criterion does
|
||||
* not exist
|
||||
*/
|
||||
public void updateUnvalidated(String criterionTypeName,
|
||||
String criterionName, Date startDate, Date finishDate)
|
||||
throws InstanceNotFoundException {
|
||||
|
||||
CriterionType criterionType = null;
|
||||
|
||||
if (StringUtils.isBlank(criterionTypeName)) {
|
||||
criterionType = criterion.getType();
|
||||
} else {
|
||||
criterionType = Registry.getCriterionTypeDAO().findUniqueByName(
|
||||
criterionTypeName);
|
||||
}
|
||||
|
||||
String newCriterionName = null;
|
||||
|
||||
if (StringUtils.isBlank(criterionName)) {
|
||||
newCriterionName = StringUtils.trim(criterion.getName());
|
||||
} else {
|
||||
newCriterionName = criterionName;
|
||||
}
|
||||
|
||||
this.criterion = criterionType.getCriterion(newCriterionName);
|
||||
|
||||
if (startDate != null) {
|
||||
this.startDate = startDate;
|
||||
}
|
||||
|
||||
if (finishDate != null) {
|
||||
this.finishDate = finishDate;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for hibernate. Do not use!
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -80,6 +80,37 @@ public class CriterionType extends IntegrationEntity implements
|
|||
|
||||
}
|
||||
|
||||
public void updateUnvalidated(String name, String description,
|
||||
Boolean allowHierarchy, Boolean allowSimultaneousCriterionsPerResource,
|
||||
Boolean enabled, ResourceEnum resource) {
|
||||
|
||||
if (!StringUtils.isBlank(name)) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
if (!StringUtils.isBlank(description)) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
if (allowHierarchy != null) {
|
||||
this.allowHierarchy = allowHierarchy;
|
||||
}
|
||||
|
||||
if (allowSimultaneousCriterionsPerResource != null) {
|
||||
this.allowSimultaneousCriterionsPerResource =
|
||||
allowSimultaneousCriterionsPerResource;
|
||||
}
|
||||
|
||||
if (enabled != null) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
if (resource != null) {
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static CriterionType create(String name,String description) {
|
||||
return create(new CriterionType(name,description));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import java.util.Collections;
|
|||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.hibernate.validator.NotEmpty;
|
||||
import org.hibernate.validator.Valid;
|
||||
|
||||
|
|
@ -69,6 +70,18 @@ public class Machine extends Resource {
|
|||
|
||||
}
|
||||
|
||||
public void updateUnvalidated(String name, String description) {
|
||||
|
||||
if (!StringUtils.isBlank(name)) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
if (!StringUtils.isBlank(description)) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by Hibernate. Do not use!
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -118,6 +118,25 @@ public abstract class Resource extends IntegrationEntity {
|
|||
return satisfactionActives;
|
||||
}
|
||||
|
||||
public CriterionSatisfaction getCriterionSatisfactionByCode(String code)
|
||||
throws InstanceNotFoundException {
|
||||
|
||||
if (StringUtils.isBlank(code)) {
|
||||
throw new InstanceNotFoundException(code,
|
||||
CriterionSatisfaction.class.getName());
|
||||
}
|
||||
|
||||
for (CriterionSatisfaction i : criterionSatisfactions) {
|
||||
if (i.getCode().equalsIgnoreCase(StringUtils.trim(code))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
throw new InstanceNotFoundException(code,
|
||||
CriterionSatisfaction.class.getName());
|
||||
|
||||
}
|
||||
|
||||
public abstract String getShortDescription();
|
||||
|
||||
public abstract String getName();
|
||||
|
|
@ -699,7 +718,7 @@ public abstract class Resource extends IntegrationEntity {
|
|||
} else {
|
||||
|
||||
List<BaseCalendar> baseCalendars = Registry.getBaseCalendarDAO().
|
||||
findByName(StringUtils.trim(calendarName));
|
||||
findByName(calendarName);
|
||||
|
||||
if (baseCalendars.isEmpty()) {
|
||||
throw new InstanceNotFoundException(calendarName,
|
||||
|
|
@ -832,12 +851,42 @@ public abstract class Resource extends IntegrationEntity {
|
|||
return resourcesCostCategoryAssignments;
|
||||
}
|
||||
|
||||
public ResourcesCostCategoryAssignment
|
||||
getResourcesCostCategoryAssignmentByCode(String code)
|
||||
throws InstanceNotFoundException {
|
||||
|
||||
if (StringUtils.isBlank(code)) {
|
||||
throw new InstanceNotFoundException(code,
|
||||
ResourcesCostCategoryAssignment.class.getName());
|
||||
}
|
||||
|
||||
for (ResourcesCostCategoryAssignment i :
|
||||
resourcesCostCategoryAssignments) {
|
||||
|
||||
if (i.getCode().equalsIgnoreCase(StringUtils.trim(code))) {
|
||||
return i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
throw new InstanceNotFoundException(code,
|
||||
ResourcesCostCategoryAssignment.class.getName());
|
||||
|
||||
}
|
||||
|
||||
public void addResourcesCostCategoryAssignment(ResourcesCostCategoryAssignment assignment) {
|
||||
resourcesCostCategoryAssignments.add(assignment);
|
||||
if(assignment.getResource()!=this)
|
||||
assignment.setResource(this);
|
||||
}
|
||||
|
||||
public void addUnvalidatedResourcesCostCategoryAssignment(
|
||||
ResourcesCostCategoryAssignment assignment) {
|
||||
|
||||
resourcesCostCategoryAssignments.add(assignment);
|
||||
|
||||
}
|
||||
|
||||
public void removeResourcesCostCategoryAssignment(ResourcesCostCategoryAssignment assignment) {
|
||||
resourcesCostCategoryAssignments.remove(assignment);
|
||||
if(assignment.getResource()==this)
|
||||
|
|
|
|||
|
|
@ -59,6 +59,22 @@ public class Worker extends Resource {
|
|||
|
||||
}
|
||||
|
||||
public void updateUnvalidated(String firstName, String surname, String nif) {
|
||||
|
||||
if (!StringUtils.isBlank(firstName)) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
if (!StringUtils.isBlank(surname)) {
|
||||
this.surname = surname;
|
||||
}
|
||||
|
||||
if (!StringUtils.isBlank(nif)) {
|
||||
this.nif = nif;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String firstName;
|
||||
|
||||
private String surname;
|
||||
|
|
|
|||
|
|
@ -134,23 +134,10 @@ public abstract class GenericRESTService<E extends IntegrationEntity,
|
|||
}
|
||||
|
||||
/*
|
||||
* Save the entity (insert or update).
|
||||
*
|
||||
* IGenericDAO::save first reattaches the object into the
|
||||
* underlying ORM session, and then calls BaseEntity::validate.
|
||||
* Despite this, we must call BaseEntity::validate before
|
||||
* IGenericDAO::save to avoid an invalid object to enter in
|
||||
* the underlying ORM session. Otherwise, the ORM could try
|
||||
* to flush the ORM session (with an invalid object violating
|
||||
* database-level restrictions) when executing
|
||||
* IGenericDAO::save, since this method calls
|
||||
* BaseEntity::validate (after reattaching the object), which
|
||||
* probably will cause queries to be launched to the database
|
||||
* (which may cause the flushing).
|
||||
*
|
||||
* Validate and save (insert or update) the entity.
|
||||
*/
|
||||
entity.validate();
|
||||
entityDAO.save(entity);
|
||||
entityDAO.saveWithoutValidating(entity);
|
||||
|
||||
return null;
|
||||
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ public final class CriterionConverter {
|
|||
}
|
||||
|
||||
public final static void updateCriterionType(CriterionType criterionType,
|
||||
CriterionTypeDTO criterionTypeDTO) {
|
||||
CriterionTypeDTO criterionTypeDTO) throws ValidationException {
|
||||
|
||||
/* 1: Get criterion wrappers with parent code. */
|
||||
Set<CriterionDTOWithParentCode> criterionWrappers =
|
||||
|
|
@ -132,7 +132,9 @@ public final class CriterionConverter {
|
|||
try {
|
||||
Criterion criterion = criterionType.getCriterionByCode(
|
||||
criterionWrapper.dto.code);
|
||||
updateCriterionBasicProperties(criterion, criterionWrapper.dto);
|
||||
criterion.updateUnvalidated(
|
||||
StringUtils.trim(criterionWrapper.dto.name),
|
||||
criterionWrapper.dto.active);
|
||||
} catch (InstanceNotFoundException e) {
|
||||
criterionType.getCriterions().add(toEntityWithoutChildren(
|
||||
criterionWrapper.dto, criterionType, null));
|
||||
|
|
@ -158,7 +160,13 @@ public final class CriterionConverter {
|
|||
|
||||
|
||||
/* 4: Update criterion type basic properties. */
|
||||
updateCriterionTypeBasicProperties(criterionType, criterionTypeDTO);
|
||||
criterionType.updateUnvalidated(
|
||||
StringUtils.trim(criterionTypeDTO.name),
|
||||
StringUtils.trim(criterionTypeDTO.description),
|
||||
criterionTypeDTO.allowHierarchy,
|
||||
criterionTypeDTO.allowSimultaneousCriterionsPerResource,
|
||||
criterionTypeDTO.enabled,
|
||||
ResourceEnumConverter.fromDTO(criterionTypeDTO.resource));
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -208,49 +216,4 @@ public final class CriterionConverter {
|
|||
|
||||
}
|
||||
|
||||
private static void updateCriterionTypeBasicProperties(
|
||||
CriterionType criterionType, CriterionTypeDTO criterionTypeDTO) {
|
||||
|
||||
if (!StringUtils.isBlank(criterionTypeDTO.name)) {
|
||||
criterionType.setName(StringUtils.trim(criterionTypeDTO.name));
|
||||
}
|
||||
|
||||
if (!StringUtils.isBlank(criterionTypeDTO.description)) {
|
||||
criterionType.setDescription(
|
||||
StringUtils.trim(criterionTypeDTO.description));
|
||||
}
|
||||
|
||||
if (criterionTypeDTO.allowHierarchy != null) {
|
||||
criterionType.setAllowHierarchy(criterionTypeDTO.allowHierarchy);
|
||||
}
|
||||
|
||||
if (criterionTypeDTO.allowSimultaneousCriterionsPerResource != null) {
|
||||
criterionType.setAllowSimultaneousCriterionsPerResource(
|
||||
criterionTypeDTO.allowSimultaneousCriterionsPerResource);
|
||||
}
|
||||
|
||||
if (criterionTypeDTO.enabled != null) {
|
||||
criterionType.setEnabled(criterionTypeDTO.enabled);
|
||||
}
|
||||
|
||||
if (criterionTypeDTO.resource != null) {
|
||||
criterionType.setResource(
|
||||
ResourceEnumConverter.fromDTO(criterionTypeDTO.resource));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void updateCriterionBasicProperties(Criterion criterion,
|
||||
CriterionDTO criterionDTO) {
|
||||
|
||||
if (!StringUtils.isBlank(criterionDTO.name)) {
|
||||
criterion.setName(StringUtils.trim(criterionDTO.name));
|
||||
}
|
||||
|
||||
if (criterionDTO.active != null) {
|
||||
criterion.setActive(criterionDTO.active);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import org.navalplanner.business.resources.entities.Resource;
|
|||
import org.navalplanner.business.resources.entities.Worker;
|
||||
import org.navalplanner.ws.common.impl.DateConverter;
|
||||
import org.navalplanner.ws.common.impl.InstanceNotFoundRecoverableErrorException;
|
||||
import org.navalplanner.ws.common.impl.RecoverableErrorException;
|
||||
import org.navalplanner.ws.resources.api.CriterionSatisfactionDTO;
|
||||
import org.navalplanner.ws.resources.api.MachineDTO;
|
||||
import org.navalplanner.ws.resources.api.ResourceDTO;
|
||||
|
|
@ -51,20 +52,27 @@ import org.navalplanner.ws.resources.criterion.api.CriterionTypeDTO;
|
|||
*/
|
||||
public class ResourceConverter {
|
||||
|
||||
/*
|
||||
* These constants should probably be moved to XxxDTO.ENTITY_TYPE
|
||||
* if the corresponding DTOs are created in the future.
|
||||
*/
|
||||
private final static String RESOURCE_CALENDAR_ENTITY_TYPE =
|
||||
"resource-calendar";
|
||||
private final static String COST_CATEGORY_ENTITY_TYPE = "cost-category";
|
||||
|
||||
private ResourceConverter() {}
|
||||
|
||||
public final static Resource toEntity(ResourceDTO resourceDTO) {
|
||||
public final static Resource toEntity(ResourceDTO resourceDTO)
|
||||
throws ValidationException, RecoverableErrorException {
|
||||
|
||||
checkResourceDTOType(resourceDTO);
|
||||
|
||||
Resource resource;
|
||||
|
||||
if (resourceDTO instanceof MachineDTO) {
|
||||
resource = createResourceWithBasicData((MachineDTO) resourceDTO);
|
||||
} else if (resourceDTO instanceof WorkerDTO) {
|
||||
resource = createResourceWithBasicData((WorkerDTO) resourceDTO);
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
_("Service does not manage resource of type: {0}",
|
||||
resourceDTO.getClass().getName()));
|
||||
resource = createResourceWithBasicData((WorkerDTO) resourceDTO);
|
||||
}
|
||||
|
||||
addCriterionSatisfactions(resource,
|
||||
|
|
@ -77,6 +85,24 @@ public class ResourceConverter {
|
|||
|
||||
}
|
||||
|
||||
public final static void updateResource(Resource resource,
|
||||
ResourceDTO resourceDTO)
|
||||
throws ValidationException, RecoverableErrorException {
|
||||
|
||||
checkResourceDTOType(resourceDTO);
|
||||
|
||||
updateBasicData(resource, resourceDTO);
|
||||
|
||||
updateResourceCalendar(resource, resourceDTO.calendarName);
|
||||
|
||||
updateCriterionSatisfactions(resource,
|
||||
resourceDTO.criterionSatisfactions);
|
||||
|
||||
updateResourcesCostCategoryAssignments(resource,
|
||||
resourceDTO.resourcesCostCategoryAssignments);
|
||||
|
||||
}
|
||||
|
||||
private final static Machine createResourceWithBasicData(
|
||||
MachineDTO machineDTO) {
|
||||
|
||||
|
|
@ -154,13 +180,10 @@ public class ResourceConverter {
|
|||
String calendarName) {
|
||||
|
||||
try {
|
||||
resource.setResourceCalendar(calendarName);
|
||||
resource.setResourceCalendar(StringUtils.trim(calendarName));
|
||||
} catch (InstanceNotFoundException e) {
|
||||
throw new InstanceNotFoundRecoverableErrorException(
|
||||
"resource-calendar", e.getKey().toString());
|
||||
// TODO: literal "resource-calendar" should possibly be
|
||||
// replaced by ResourceCalendarDTO.ENTITY_TYPE if
|
||||
// ResourceCalendarDTO is created in the future.
|
||||
RESOURCE_CALENDAR_ENTITY_TYPE, e.getKey().toString());
|
||||
} catch (MultipleInstancesException e) {
|
||||
throw new ValidationException(
|
||||
_("there exist multiple resource calendars with name {0}",
|
||||
|
|
@ -178,7 +201,7 @@ public class ResourceConverter {
|
|||
|
||||
ResourcesCostCategoryAssignment assignment = toEntity(assignmentDTO,
|
||||
resource);
|
||||
resource.addResourcesCostCategoryAssignment(assignment);
|
||||
resource.addUnvalidatedResourcesCostCategoryAssignment(assignment);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -194,15 +217,160 @@ public class ResourceConverter {
|
|||
|
||||
try {
|
||||
return ResourcesCostCategoryAssignment.createUnvalidated(
|
||||
assignmentDTO.code, assignmentDTO.costCategoryName, resource,
|
||||
assignmentDTO.code,
|
||||
StringUtils.trim(assignmentDTO.costCategoryName), resource,
|
||||
DateConverter.toLocalDate(assignmentDTO.startDate),
|
||||
DateConverter.toLocalDate(assignmentDTO.endDate));
|
||||
} catch (InstanceNotFoundException e) {
|
||||
throw new InstanceNotFoundRecoverableErrorException(
|
||||
"cost-category", e.getKey().toString());
|
||||
// TODO: literal "cost-category" should possibly be replaced by
|
||||
// CostCategoryDTO.ENTITY_TYPE if CostCategoryDTO is created in the
|
||||
// future.
|
||||
COST_CATEGORY_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(
|
||||
_("Incompatible update: stored resource is not of type: {0}",
|
||||
resourceDTO.getEntityType()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static void updateResourceCalendar(Resource resource,
|
||||
String calendarName) {
|
||||
|
||||
// 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.toDate(criterionSatisfactionDTO.startDate),
|
||||
DateConverter.toDate(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(
|
||||
COST_CATEGORY_ENTITY_TYPE, e.getKey().toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void checkResourceDTOType(ResourceDTO resourceDTO) {
|
||||
|
||||
if (!(resourceDTO instanceof MachineDTO) &&
|
||||
!(resourceDTO instanceof WorkerDTO)) {
|
||||
|
||||
throw new ValidationException(
|
||||
_("Service does not manage resource of type: {0}",
|
||||
resourceDTO.getEntityType()));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import org.navalplanner.business.resources.daos.IResourceDAO;
|
|||
import org.navalplanner.business.resources.entities.Resource;
|
||||
import org.navalplanner.ws.common.api.InstanceConstraintViolationsListDTO;
|
||||
import org.navalplanner.ws.common.impl.GenericRESTService;
|
||||
import org.navalplanner.ws.common.impl.RecoverableErrorException;
|
||||
import org.navalplanner.ws.resources.api.IResourceService;
|
||||
import org.navalplanner.ws.resources.api.ResourceDTO;
|
||||
import org.navalplanner.ws.resources.api.ResourceListDTO;
|
||||
|
|
@ -63,8 +64,11 @@ public class ResourceServiceREST
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Resource toEntity(ResourceDTO entityDTO) {
|
||||
protected Resource toEntity(ResourceDTO entityDTO)
|
||||
throws ValidationException, RecoverableErrorException {
|
||||
|
||||
return ResourceConverter.toEntity(entityDTO);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -79,8 +83,10 @@ public class ResourceServiceREST
|
|||
|
||||
@Override
|
||||
protected void updateEntity(Resource entity, ResourceDTO entityDTO)
|
||||
throws ValidationException {
|
||||
// FIXME: updated functionality not implemented yet.
|
||||
throws ValidationException, RecoverableErrorException {
|
||||
|
||||
ResourceConverter.updateResource(entity, entityDTO);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,9 @@ import static org.navalplanner.web.test.ws.common.Util.assertOneRecoverableError
|
|||
import static org.navalplanner.web.test.ws.common.Util.getUniqueName;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.datatype.DatatypeConfigurationException;
|
||||
|
|
@ -41,6 +44,7 @@ import javax.xml.datatype.DatatypeConstants;
|
|||
import javax.xml.datatype.DatatypeFactory;
|
||||
import javax.xml.datatype.XMLGregorianCalendar;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
|
@ -50,11 +54,13 @@ import org.navalplanner.business.common.IAdHocTransactionService;
|
|||
import org.navalplanner.business.common.IOnTransaction;
|
||||
import org.navalplanner.business.common.daos.IConfigurationDAO;
|
||||
import org.navalplanner.business.common.entities.IConfigurationBootstrap;
|
||||
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
|
||||
import org.navalplanner.business.costcategories.daos.ICostCategoryDAO;
|
||||
import org.navalplanner.business.costcategories.entities.CostCategory;
|
||||
import org.navalplanner.business.resources.daos.ICriterionTypeDAO;
|
||||
import org.navalplanner.business.resources.daos.IMachineDAO;
|
||||
import org.navalplanner.business.resources.daos.IResourceDAO;
|
||||
import org.navalplanner.business.resources.daos.IWorkerDAO;
|
||||
import org.navalplanner.business.resources.entities.Criterion;
|
||||
import org.navalplanner.business.resources.entities.CriterionSatisfaction;
|
||||
import org.navalplanner.business.resources.entities.CriterionType;
|
||||
|
|
@ -95,6 +101,9 @@ public class ResourceServiceTest {
|
|||
@Autowired
|
||||
private IMachineDAO machineDAO;
|
||||
|
||||
@Autowired
|
||||
private IWorkerDAO workerDAO;
|
||||
|
||||
@Autowired
|
||||
private ICriterionTypeDAO criterionTypeDAO;
|
||||
|
||||
|
|
@ -720,6 +729,100 @@ public class ResourceServiceTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateResources() throws InstanceNotFoundException {
|
||||
|
||||
/* Create a criterion type and a cost category. */
|
||||
CriterionType ct = createCriterionType();
|
||||
CostCategory costCategory = createCostCategory();
|
||||
|
||||
/* Create a machine DTO. */
|
||||
MachineDTO m1 = new MachineDTO("name", "desc");
|
||||
CriterionSatisfactionDTO m1s1 = new CriterionSatisfactionDTO(
|
||||
ct.getName(), "c1", getDate(2000, 1, 1), getDate(2000, 2, 1));
|
||||
m1.criterionSatisfactions.add(m1s1);
|
||||
ResourcesCostCategoryAssignmentDTO m1a1 =
|
||||
new ResourcesCostCategoryAssignmentDTO(costCategory.getName(),
|
||||
getDate(2000, 1, 1), getDate(2000, 2, 1));
|
||||
m1.resourcesCostCategoryAssignments.add(m1a1);
|
||||
|
||||
/* Create a worker DTO. */
|
||||
WorkerDTO w1 = new WorkerDTO(getUniqueName(), "surname", "nif");
|
||||
CriterionSatisfactionDTO w1s1 = new CriterionSatisfactionDTO(
|
||||
ct.getName(), "c1", getDate(2000, 1, 1), getDate(2000, 2, 1));
|
||||
w1.criterionSatisfactions.add(w1s1);
|
||||
ResourcesCostCategoryAssignmentDTO w1a1 =
|
||||
new ResourcesCostCategoryAssignmentDTO(costCategory.getName(),
|
||||
getDate(2000, 1, 1), getDate(2000, 2, 1));
|
||||
w1.resourcesCostCategoryAssignments.add(w1a1);
|
||||
|
||||
/* Add resources. */
|
||||
assertNoConstraintViolations(
|
||||
resourceService.addResources(createResourceListDTO(m1, w1)));
|
||||
|
||||
/*
|
||||
* Build DTOs for making the following update:
|
||||
*
|
||||
* + m1: update name, m1s1's start date, and add a new cost category
|
||||
* assignment.
|
||||
* + w1: update surname, w1a1's start date, and add a new criterion
|
||||
* satisfaction.
|
||||
*/
|
||||
MachineDTO m1Updated = new MachineDTO(m1.code, "name" + "UPDATED",
|
||||
null);
|
||||
CriterionSatisfactionDTO m1s1Updated = new CriterionSatisfactionDTO(
|
||||
m1s1.code, null, null, getDate(2000, 1, 2), null);
|
||||
m1Updated.criterionSatisfactions.add(m1s1Updated);
|
||||
ResourcesCostCategoryAssignmentDTO m1a2 =
|
||||
new ResourcesCostCategoryAssignmentDTO(costCategory.getName(),
|
||||
getDate(2000, 3, 1), getDate(2000, 4, 1));
|
||||
m1Updated.resourcesCostCategoryAssignments.add(m1a2);
|
||||
|
||||
WorkerDTO w1Updated = new WorkerDTO(w1.code, null,
|
||||
"surname" + "UPDATED", null);
|
||||
CriterionSatisfactionDTO w1s2 = new CriterionSatisfactionDTO(
|
||||
ct.getName(), "c1", getDate(2000, 3, 1), getDate(2000, 4, 1));
|
||||
w1Updated.criterionSatisfactions.add(w1s2);
|
||||
ResourcesCostCategoryAssignmentDTO w1a1Updated =
|
||||
new ResourcesCostCategoryAssignmentDTO(w1a1.code, null,
|
||||
getDate(2000, 2, 1), null);
|
||||
w1Updated.resourcesCostCategoryAssignments.add(w1a1Updated);
|
||||
|
||||
/* Update resources and test. */
|
||||
assertNoConstraintViolations(
|
||||
resourceService.addResources(createResourceListDTO(m1Updated,
|
||||
w1Updated)));
|
||||
|
||||
/* Test machine update. */
|
||||
Machine m1Entity = machineDAO.findByCode(m1.code);
|
||||
|
||||
assertEquals(m1Updated.name, m1Entity.getName()); // Modified.
|
||||
assertEquals(m1.description, m1Entity.getDescription()); //Not modified.
|
||||
assertTrue(datesEquals( // Modified.
|
||||
m1s1Updated.startDate,
|
||||
m1Entity.getCriterionSatisfactionByCode(m1s1.code).getStartDate()));
|
||||
assertTrue(datesEquals( // Not modified.
|
||||
m1s1.endDate,
|
||||
m1Entity.getCriterionSatisfactionByCode(m1s1.code).getEndDate()));
|
||||
m1Entity.getResourcesCostCategoryAssignmentByCode(m1a2.code); // New.
|
||||
|
||||
/* Test worker update. */
|
||||
Worker w1Entity = workerDAO.findByCode(w1.code);
|
||||
|
||||
assertEquals(w1Updated.surname, w1Entity.getSurname()); // Modified.
|
||||
assertEquals(w1.firstName, w1Entity.getFirstName()); // Not modified.
|
||||
w1Entity.getCriterionSatisfactionByCode(w1s2.code); // New.
|
||||
assertTrue(datesEquals( // Modified.
|
||||
w1a1Updated.startDate,
|
||||
w1Entity.getResourcesCostCategoryAssignmentByCode(w1a1.code).
|
||||
getInitDate()));
|
||||
assertTrue(datesEquals( // Not modified.
|
||||
w1a1.endDate,
|
||||
w1Entity.getResourcesCostCategoryAssignmentByCode(w1a1.code).
|
||||
getEndDate()));
|
||||
|
||||
}
|
||||
|
||||
private CriterionType createCriterionType() {
|
||||
return createCriterionType(ResourceEnum.RESOURCE, true);
|
||||
}
|
||||
|
|
@ -885,4 +988,33 @@ public class ResourceServiceTest {
|
|||
|
||||
}
|
||||
|
||||
private boolean datesEquals(XMLGregorianCalendar date1, Date date2) {
|
||||
|
||||
GregorianCalendar date2AsGC = new GregorianCalendar();
|
||||
date2AsGC.setTime(date2);
|
||||
|
||||
return datesEquals(date1.toGregorianCalendar(), date2AsGC);
|
||||
|
||||
}
|
||||
|
||||
private boolean datesEquals(XMLGregorianCalendar date1, LocalDate date2) {
|
||||
|
||||
GregorianCalendar date2AsGC = new GregorianCalendar(
|
||||
date2.getYear(), date2.getMonthOfYear()-1, date2.getDayOfMonth());
|
||||
|
||||
return datesEquals(date1.toGregorianCalendar(), date2AsGC);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public boolean datesEquals(GregorianCalendar date1,
|
||||
GregorianCalendar date2) {
|
||||
|
||||
return date1.get(Calendar.YEAR) == date2.get(Calendar.YEAR) &&
|
||||
date1.get(Calendar.MONTH) == date2.get(Calendar.MONTH) &&
|
||||
date1.get(Calendar.DAY_OF_MONTH) ==
|
||||
date2.get(Calendar.DAY_OF_MONTH);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,9 @@
|
|||
- Check the returned errors are consistent with the comments in
|
||||
resources-sample.xml.
|
||||
|
||||
- Repeat with resources-update-sample.xml (resources-sample-mini.xml
|
||||
must be previously imported).
|
||||
|
||||
* Export order elements:
|
||||
|
||||
- export-order-element.sh ORDER-ELEMENT-CODE (authenticate with
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
<machine code="m2" name="m2-name" description="m2-desc">
|
||||
<criterion-satisfaction-list>
|
||||
<criterion-satisfaction
|
||||
code="m2-a1"
|
||||
code="m2-s1"
|
||||
criterion-type-name="WORK_RELATIONSHIP"
|
||||
criterion-name="hiredResourceWorkingRelationship"
|
||||
start-date="2009-01-01"
|
||||
|
|
|
|||
46
scripts/rest-clients/resources-update-sample.xml
Normal file
46
scripts/rest-clients/resources-update-sample.xml
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
|
||||
<!-- These updates could be part resources-sample-mini.xml, but have been
|
||||
extracted to an independent file for clarity (this way, by using the Web
|
||||
user interface, one can see the effects of importing
|
||||
resources-sample-mini.xml first, and then
|
||||
resources-update-sample.xml). -->
|
||||
|
||||
<resource-list xmlns="http://rest.ws.navalplanner.org">
|
||||
|
||||
<!-- OK (change name, machineA-s1's start date, and machineA-a2's start
|
||||
date). -->
|
||||
<machine code="machineA" name="name UPDATED">
|
||||
<criterion-satisfaction-list>
|
||||
<criterion-satisfaction
|
||||
code="machineA-s1"
|
||||
start-date="2009-02-01"/>
|
||||
</criterion-satisfaction-list>
|
||||
<resources-cost-category-assignment-list>
|
||||
<resources-cost-category-assignment
|
||||
code="machineA-a2"
|
||||
start-date="2000-02-01"/>
|
||||
</resources-cost-category-assignment-list>
|
||||
</machine>
|
||||
|
||||
<!-- OK (change first name, add one new criterion satisfaction and another
|
||||
new one cost category assignment). -->
|
||||
<worker code="workerA" first-name="workerA UPDATED">
|
||||
<criterion-satisfaction-list>
|
||||
<criterion-satisfaction
|
||||
code="workerA-s3"
|
||||
criterion-type-name="LEAVE"
|
||||
criterion-name="paternityLeave"
|
||||
start-date="2010-01-02"
|
||||
end-date="2010-01-03"/>
|
||||
</criterion-satisfaction-list>
|
||||
<resources-cost-category-assignment-list>
|
||||
<resources-cost-category-assignment
|
||||
code="workerA-a3"
|
||||
cost-category-name="TestCostCategory"
|
||||
start-date="2000-05-01"
|
||||
end-date="2000-06-01"/>
|
||||
</resources-cost-category-assignment-list>
|
||||
</worker>
|
||||
|
||||
</resource-list>
|
||||
Loading…
Add table
Reference in a new issue