diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/common/daos/GenericDAOHibernate.java b/navalplanner-business/src/main/java/org/navalplanner/business/common/daos/GenericDAOHibernate.java index f6261e2b7..8a2bbd0c6 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/common/daos/GenericDAOHibernate.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/common/daos/GenericDAOHibernate.java @@ -94,6 +94,10 @@ public class GenericDAOHibernate{ */ public void save(E entity) throws ValidationException; + /** + * Unlike save, 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 diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/entities/ResourcesCostCategoryAssignment.java b/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/entities/ResourcesCostCategoryAssignment.java index d4915c320..19fc377e9 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/entities/ResourcesCostCategoryAssignment.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/entities/ResourcesCostCategoryAssignment.java @@ -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; diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Criterion.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Criterion.java index 7bf9f53a0..bdb16b9de 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Criterion.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Criterion.java @@ -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)); } diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionSatisfaction.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionSatisfaction.java index eb61f0efb..bdd376839 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionSatisfaction.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionSatisfaction.java @@ -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! */ diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionType.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionType.java index 5cd7e2346..2c68da68f 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionType.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionType.java @@ -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)); } diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Machine.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Machine.java index 7509154c0..68e7720b6 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Machine.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Machine.java @@ -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! */ diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Resource.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Resource.java index 1b55943d1..e30b2b68c 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Resource.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Resource.java @@ -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 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) diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Worker.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Worker.java index b5103ef92..bab974938 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Worker.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Worker.java @@ -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; diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/GenericRESTService.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/GenericRESTService.java index 1837c772b..9247d079d 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/GenericRESTService.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/GenericRESTService.java @@ -134,23 +134,10 @@ public abstract class GenericRESTService 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); - } - - } - } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/impl/ResourceConverter.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/impl/ResourceConverter.java index 12ce3a7bb..a3c8a9ed9 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/impl/ResourceConverter.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/impl/ResourceConverter.java @@ -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 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 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())); + } } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/impl/ResourceServiceREST.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/impl/ResourceServiceREST.java index 2382ae3be..c5caccdbc 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/impl/ResourceServiceREST.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/impl/ResourceServiceREST.java @@ -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); + } } diff --git a/navalplanner-webapp/src/test/java/org/navalplanner/web/test/ws/resources/api/ResourceServiceTest.java b/navalplanner-webapp/src/test/java/org/navalplanner/web/test/ws/resources/api/ResourceServiceTest.java index 59bad2ac4..cc8c2cd8f 100644 --- a/navalplanner-webapp/src/test/java/org/navalplanner/web/test/ws/resources/api/ResourceServiceTest.java +++ b/navalplanner-webapp/src/test/java/org/navalplanner/web/test/ws/resources/api/ResourceServiceTest.java @@ -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); + + } + } diff --git a/scripts/rest-clients/README b/scripts/rest-clients/README index 048693da3..8eb0f4d0e 100644 --- a/scripts/rest-clients/README +++ b/scripts/rest-clients/README @@ -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 diff --git a/scripts/rest-clients/resources-sample.xml b/scripts/rest-clients/resources-sample.xml index fc7a00274..df40f83fb 100644 --- a/scripts/rest-clients/resources-sample.xml +++ b/scripts/rest-clients/resources-sample.xml @@ -16,7 +16,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +