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:
Fernando Bellas Permuy 2010-02-11 20:44:14 +01:00 committed by Javier Moran Rua
parent c9ea9ea65d
commit 664d7a8f63
17 changed files with 580 additions and 85 deletions

View file

@ -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);

View file

@ -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

View file

@ -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;

View file

@ -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));
}

View file

@ -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!
*/

View file

@ -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));
}

View file

@ -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!
*/

View file

@ -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)

View file

@ -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;

View file

@ -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;

View file

@ -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);
}
}
}

View file

@ -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()));
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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

View file

@ -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"

View 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>