ItEr47S12CUImportacionRecursosProductivosItEr46S13: ResourceServiceREST adapted to GenericRESTService and added support for recoverable errors.

ResourceServiceREST has been adapted to GenericRESTService. Updating functionality in ResourceServiceREST is not implemented yet.

As part of this patch, the generic infraestructure for REST services has been improved. In particular, recoverable error support has been provided. Exceptions representing recoverable errors must extend from RecoverableErrorException. To demonstrate this capability, ResourceServiceREST nows reports non-existent calendars, criterions, critetion types, and cost categories as recoverable errors.
This commit is contained in:
Fernando Bellas Permuy 2010-02-09 16:20:30 +01:00 committed by Javier Moran Rua
parent de3adddecc
commit 22c883820a
23 changed files with 912 additions and 592 deletions

View file

@ -67,7 +67,7 @@ public class IntegrationEntityDAO<E extends IntegrationEntity>
} }
E entity = (E) getSession().createCriteria(getEntityClass()).add( E entity = (E) getSession().createCriteria(getEntityClass()).add(
Restrictions.eq("code", code).ignoreCase()).uniqueResult(); Restrictions.eq("code", code.trim()).ignoreCase()).uniqueResult();
if (entity == null) { if (entity == null) {
throw new InstanceNotFoundException( throw new InstanceNotFoundException(

View file

@ -20,15 +20,12 @@
package org.navalplanner.business.costcategories.entities; package org.navalplanner.business.costcategories.entities;
import static org.navalplanner.business.i18n.I18nHelper._;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.hibernate.validator.AssertTrue; import org.hibernate.validator.AssertTrue;
import org.hibernate.validator.NotNull; import org.hibernate.validator.NotNull;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
import org.navalplanner.business.common.IntegrationEntity; import org.navalplanner.business.common.IntegrationEntity;
import org.navalplanner.business.common.Registry; import org.navalplanner.business.common.Registry;
import org.navalplanner.business.common.exceptions.CreateUnvalidatedException;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException; import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.costcategories.daos.IResourcesCostCategoryAssignmentDAO; import org.navalplanner.business.costcategories.daos.IResourcesCostCategoryAssignmentDAO;
import org.navalplanner.business.resources.entities.Resource; import org.navalplanner.business.resources.entities.Resource;
@ -56,25 +53,16 @@ public class ResourcesCostCategoryAssignment extends IntegrationEntity {
return (ResourcesCostCategoryAssignment) create(new ResourcesCostCategoryAssignment()); return (ResourcesCostCategoryAssignment) create(new ResourcesCostCategoryAssignment());
} }
/**
* @throws InstanceNotFoundException if cost category does not exist
*/
public static ResourcesCostCategoryAssignment createUnvalidated( public static ResourcesCostCategoryAssignment createUnvalidated(
String code, String costCategoryName, Resource resource, String code, String costCategoryName, Resource resource,
LocalDate initDate, LocalDate endDate) LocalDate initDate, LocalDate endDate)
throws CreateUnvalidatedException { throws InstanceNotFoundException {
/* Get CostCategory. */ CostCategory costCategory = Registry.getCostCategoryDAO().findUniqueByName(
if (StringUtils.isBlank(costCategoryName)) { StringUtils.trim(costCategoryName));
throw new CreateUnvalidatedException(
_("cost category name not specified"));
}
CostCategory costCategory = null;
try {
costCategory = Registry.getCostCategoryDAO().findUniqueByName(
StringUtils.trim(costCategoryName));
} catch (InstanceNotFoundException e) {
throw new CreateUnvalidatedException(
_("{0}: cost category does not exist", costCategoryName));
}
/* Create instance of ResourcesCostCategoryAssignment. */ /* Create instance of ResourcesCostCategoryAssignment. */
ResourcesCostCategoryAssignment assignment = ResourcesCostCategoryAssignment assignment =

View file

@ -22,7 +22,7 @@ package org.navalplanner.business.resources.daos;
import java.util.List; import java.util.List;
import org.navalplanner.business.common.daos.IGenericDAO; import org.navalplanner.business.common.daos.IIntegrationEntityDAO;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException; import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.resources.entities.Machine; import org.navalplanner.business.resources.entities.Machine;
@ -31,8 +31,9 @@ import org.navalplanner.business.resources.entities.Machine;
* *
* @author Diego Pino Garcia <dpino@igalia.com> * @author Diego Pino Garcia <dpino@igalia.com>
* @author Javier Moran Rua <jmoran@igalia.com> * @author Javier Moran Rua <jmoran@igalia.com>
* @author Fernando Bellas Permuy <fbellas@udc.es>
*/ */
public interface IMachineDAO extends IGenericDAO<Machine, Long> { public interface IMachineDAO extends IIntegrationEntityDAO<Machine> {
/** /**
* Returns machines which name/NIF partially matches with name * Returns machines which name/NIF partially matches with name

View file

@ -23,7 +23,7 @@ package org.navalplanner.business.resources.daos;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import org.navalplanner.business.common.daos.IGenericDAO; import org.navalplanner.business.common.daos.IIntegrationEntityDAO;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException; import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.reports.dtos.HoursWorkedPerWorkerDTO; import org.navalplanner.business.reports.dtos.HoursWorkedPerWorkerDTO;
import org.navalplanner.business.resources.entities.Worker; import org.navalplanner.business.resources.entities.Worker;
@ -37,7 +37,7 @@ import org.springframework.transaction.annotation.Transactional;
* @author Diego Pino Garcia <dpino@igalia.com> * @author Diego Pino Garcia <dpino@igalia.com>
* *
*/ */
public interface IWorkerDAO extends IGenericDAO<Worker, Long> { public interface IWorkerDAO extends IIntegrationEntityDAO<Worker> {
/** /**
* Returns workers which name/NIF partially matches with name * Returns workers which name/NIF partially matches with name

View file

@ -22,9 +22,8 @@ package org.navalplanner.business.resources.daos;
import java.util.List; import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions; import org.hibernate.criterion.Restrictions;
import org.navalplanner.business.common.daos.GenericDAOHibernate; import org.navalplanner.business.common.daos.IntegrationEntityDAO;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException; import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.resources.entities.Machine; import org.navalplanner.business.resources.entities.Machine;
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinition;
@ -33,15 +32,17 @@ import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
/** /**
* Hibernate DAO for the <code>Machine</code> entity. * Hibernate DAO for the <code>Machine</code> entity.
* *
* @author Diego Pino Garcia <dpino@igalia.com> * @author Diego Pino Garcia <dpino@igalia.com>
* @author Javier Moran Rua <jmoran@igalia.com> * @author Javier Moran Rua <jmoran@igalia.com>
* @author Fernando Bellas Permuy <fbellas@udc.es>
*/ */
@Repository @Repository
@Scope(BeanDefinition.SCOPE_SINGLETON) @Scope(BeanDefinition.SCOPE_SINGLETON)
public class MachineDAO extends GenericDAOHibernate<Machine, Long> public class MachineDAO extends IntegrationEntityDAO<Machine>
implements IMachineDAO { implements IMachineDAO {
@Override @Override
@ -61,14 +62,9 @@ public class MachineDAO extends GenericDAOHibernate<Machine, Long>
@Override @Override
public Machine findUniqueByCode(String code) public Machine findUniqueByCode(String code)
throws InstanceNotFoundException { throws InstanceNotFoundException {
Criteria criteria = getSession().createCriteria(Machine.class);
criteria.add(Restrictions.eq("code", code).ignoreCase());
List<Machine> list = criteria.list(); return findExistingEntityByCode(code);
if (list.size() != 1) {
throw new InstanceNotFoundException(code, Machine.class.getName());
}
return list.get(0);
} }
@Override @Override

View file

@ -26,7 +26,7 @@ import java.util.List;
import org.hibernate.Criteria; import org.hibernate.Criteria;
import org.hibernate.Query; import org.hibernate.Query;
import org.hibernate.criterion.Restrictions; import org.hibernate.criterion.Restrictions;
import org.navalplanner.business.common.daos.GenericDAOHibernate; import org.navalplanner.business.common.daos.IntegrationEntityDAO;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException; import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.reports.dtos.HoursWorkedPerWorkerDTO; import org.navalplanner.business.reports.dtos.HoursWorkedPerWorkerDTO;
import org.navalplanner.business.resources.entities.Worker; import org.navalplanner.business.resources.entities.Worker;
@ -36,6 +36,7 @@ import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
/** /**
* Hibernate DAO for the <code>Worker</code> entity. * Hibernate DAO for the <code>Worker</code> entity.
* *
@ -46,7 +47,7 @@ import org.springframework.transaction.annotation.Transactional;
*/ */
@Repository @Repository
@Scope(BeanDefinition.SCOPE_SINGLETON) @Scope(BeanDefinition.SCOPE_SINGLETON)
public class WorkerDAO extends GenericDAOHibernate<Worker, Long> public class WorkerDAO extends IntegrationEntityDAO<Worker>
implements IWorkerDAO { implements IWorkerDAO {
@Override @Override

View file

@ -20,19 +20,15 @@
package org.navalplanner.business.resources.entities; package org.navalplanner.business.resources.entities;
import static org.navalplanner.business.i18n.I18nHelper._;
import java.util.Comparator; import java.util.Comparator;
import java.util.Date; import java.util.Date;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder.ToStringBuilder;
import org.hibernate.validator.AssertTrue; import org.hibernate.validator.AssertTrue;
import org.hibernate.validator.NotNull; import org.hibernate.validator.NotNull;
import org.navalplanner.business.common.IntegrationEntity; import org.navalplanner.business.common.IntegrationEntity;
import org.navalplanner.business.common.Registry; import org.navalplanner.business.common.Registry;
import org.navalplanner.business.common.exceptions.CreateUnvalidatedException;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException; import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.resources.daos.ICriterionSatisfactionDAO; import org.navalplanner.business.resources.daos.ICriterionSatisfactionDAO;
import org.navalplanner.business.resources.daos.ICriterionTypeDAO; import org.navalplanner.business.resources.daos.ICriterionTypeDAO;
@ -75,44 +71,25 @@ public class CriterionSatisfaction extends IntegrationEntity {
} }
/**
* @throws InstanceNotFoundException if criterion type or criterion does
* not exist
*/
public static CriterionSatisfaction createUnvalidated( public static CriterionSatisfaction createUnvalidated(
String code, String criterionTypeName, String criterionName, String code, String criterionTypeName, String criterionName,
Resource resource, Date startDate, Date finishDate) Resource resource, Date startDate, Date finishDate)
throws CreateUnvalidatedException { throws InstanceNotFoundException {
ICriterionTypeDAO criterionTypeDAO = ICriterionTypeDAO criterionTypeDAO =
Registry.getCriterionTypeDAO(); Registry.getCriterionTypeDAO();
/* Get CriterionType. */ /* Get CriterionType. */
if (StringUtils.isBlank(criterionTypeName)) { CriterionType criterionType = criterionTypeDAO.findUniqueByName(
throw new CreateUnvalidatedException( criterionTypeName);
_("criterion type name not specified"));
}
CriterionType criterionType = null;
try {
criterionType = criterionTypeDAO.findUniqueByName(
criterionTypeName);
} catch (InstanceNotFoundException e) {
throw new CreateUnvalidatedException(
_("{0}: criterion type does not exist", criterionTypeName));
}
/* Get Criterion. */ /* Get Criterion. */
if (StringUtils.isBlank(criterionName)) { Criterion criterion = criterionType.getCriterion(
throw new CreateUnvalidatedException( criterionName);
_("criterion name not specified"));
}
Criterion criterion = null;
try {
criterion = criterionType.getCriterion(
criterionName);
} catch (InstanceNotFoundException e) {
throw new CreateUnvalidatedException(
_("{0}: criterion is not of type {1}", criterionName,
criterionTypeName));
}
/* Create instance of CriterionSatisfaction. */ /* Create instance of CriterionSatisfaction. */
CriterionSatisfaction criterionSatisfaction = CriterionSatisfaction criterionSatisfaction =

View file

@ -27,7 +27,6 @@ import java.util.List;
import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
/** /**
* DTO for modeling the list of constraint violations on a given instance. * DTO for modeling the list of constraint violations on a given instance.
@ -57,10 +56,12 @@ public class InstanceConstraintViolationsDTO {
@XmlAttribute(name=ENTITY_TYPE_ATTRIBUTE_NAME) @XmlAttribute(name=ENTITY_TYPE_ATTRIBUTE_NAME)
public String entityType; public String entityType;
@XmlElementWrapper(name="constraint-violations")
@XmlElement(name="constraint-violation") @XmlElement(name="constraint-violation")
public List<ConstraintViolationDTO> constraintViolations; public List<ConstraintViolationDTO> constraintViolations;
@XmlElement(name="recoverable-error")
public RecoverableErrorDTO recoverableError;
@XmlElement(name="internal-error") @XmlElement(name="internal-error")
public InternalErrorDTO internalError; public InternalErrorDTO internalError;
@ -93,6 +94,15 @@ public class InstanceConstraintViolationsDTO {
} }
public InstanceConstraintViolationsDTO(
InstanceConstraintViolationsDTOId instanceId,
RecoverableErrorDTO recoverableError) {
this(instanceId);
this.recoverableError = recoverableError;
}
public InstanceConstraintViolationsDTO( public InstanceConstraintViolationsDTO(
InstanceConstraintViolationsDTOId instanceId, InstanceConstraintViolationsDTOId instanceId,
InternalErrorDTO internalError) { InternalErrorDTO internalError) {
@ -144,8 +154,23 @@ public class InstanceConstraintViolationsDTO {
ENTITY_TYPE_ATTRIBUTE_NAME + " = " + entityType + ENTITY_TYPE_ATTRIBUTE_NAME + " = " + entityType +
" **"); " **");
for (ConstraintViolationDTO i : constraintViolations) { if (internalError != null) {
printWriter.println(i);
printWriter.println("Internal error:");
printWriter.println(internalError);
} else if (constraintViolations != null) {
printWriter.println("Constraint violations:");
for (ConstraintViolationDTO i : constraintViolations) {
printWriter.println(i);
}
} else if (recoverableError != null) {
printWriter.println("Recoverable error:");
printWriter.println(recoverableError);
} }
printWriter.close(); printWriter.close();

View file

@ -20,23 +20,28 @@
package org.navalplanner.ws.common.api; package org.navalplanner.ws.common.api;
import java.io.PrintWriter;
import java.io.StringWriter;
import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
/** /**
* DTO for modeling the response to be returned when an internal service error * DTO for modeling an internal error.
* occurs.
* *
* @author Fernando Bellas Permuy <fbellas@udc.es> * @author Fernando Bellas Permuy <fbellas@udc.es>
*/ */
@XmlRootElement(name="internal-error") @XmlRootElement(name="internal-error")
public class InternalErrorDTO { public class InternalErrorDTO {
@XmlAttribute public final static String MESSAGE_ATTRIBUTE_NAME = "message";
public final static String STACK_TRACE_ATTRIBUTE_NAME = "stack-trace";
@XmlAttribute(name=MESSAGE_ATTRIBUTE_NAME)
public String message; public String message;
@XmlElement(name="stack-trace") @XmlElement(name=STACK_TRACE_ATTRIBUTE_NAME)
public String stackTrace; public String stackTrace;
public InternalErrorDTO() {} public InternalErrorDTO() {}
@ -46,4 +51,18 @@ public class InternalErrorDTO {
this.stackTrace = stackTrace; this.stackTrace = stackTrace;
} }
@Override
public String toString() {
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
printWriter.println(MESSAGE_ATTRIBUTE_NAME + " = " + message);
printWriter.println(STACK_TRACE_ATTRIBUTE_NAME + " = " + stackTrace);
printWriter.close();
return stringWriter.toString();
}
} }

View file

@ -0,0 +1,61 @@
/*
* This file is part of NavalPlan
*
* Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.navalplanner.ws.common.api;
import java.io.PrintWriter;
import java.io.StringWriter;
import javax.xml.bind.annotation.XmlAttribute;
/**
* DTO for modeling a property, containing a name and a value.
*
* @author Fernando Bellas Permuy <fbellas@udc.es>
*/
public class PropertyDTO {
@XmlAttribute
public String name;
@XmlAttribute
public String value;
public PropertyDTO() {}
public PropertyDTO(String name, String value) {
this.name = name;
this.value = value;
}
@Override
public String toString() {
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
printWriter.print(name + " = " + value);
printWriter.close();
return stringWriter.toString();
}
}

View file

@ -0,0 +1,80 @@
/*
* This file is part of NavalPlan
*
* Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.navalplanner.ws.common.api;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
/**
* DTO for modeling a recoverable error.
*
* @author Fernando Bellas Permuy <fbellas@udc.es>
*/
public class RecoverableErrorDTO {
public final static String ERROR_CODE_ATTRIBUTE_NAME = "error-code";
public final static String MESSAGE_ATTRIBUTE_NAME = "message";
@XmlAttribute(name=ERROR_CODE_ATTRIBUTE_NAME)
public int errorCode;
@XmlAttribute(name=MESSAGE_ATTRIBUTE_NAME)
public String message;
@XmlElement(name="property")
public List<PropertyDTO> properties;
public RecoverableErrorDTO() {}
public RecoverableErrorDTO(int errorCode, String message,
List<PropertyDTO> properties) {
this.errorCode = errorCode;
this.message = message;
this.properties = properties;
}
@Override
public String toString() {
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
printWriter.println(
ERROR_CODE_ATTRIBUTE_NAME + " = " + errorCode + " - " +
MESSAGE_ATTRIBUTE_NAME + " = " + message);
for (PropertyDTO p : properties) {
printWriter.println(p);
}
printWriter.close();
return stringWriter.toString();
}
}

View file

@ -22,6 +22,7 @@ package org.navalplanner.ws.common.impl;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import org.hibernate.validator.InvalidValue; import org.hibernate.validator.InvalidValue;
import org.navalplanner.business.common.exceptions.ValidationException; import org.navalplanner.business.common.exceptions.ValidationException;
@ -29,6 +30,8 @@ import org.navalplanner.ws.common.api.ConstraintViolationDTO;
import org.navalplanner.ws.common.api.InstanceConstraintViolationsDTO; import org.navalplanner.ws.common.api.InstanceConstraintViolationsDTO;
import org.navalplanner.ws.common.api.InstanceConstraintViolationsDTOId; import org.navalplanner.ws.common.api.InstanceConstraintViolationsDTOId;
import org.navalplanner.ws.common.api.InternalErrorDTO; import org.navalplanner.ws.common.api.InternalErrorDTO;
import org.navalplanner.ws.common.api.PropertyDTO;
import org.navalplanner.ws.common.api.RecoverableErrorDTO;
/** /**
* Converter for constraint violations. * Converter for constraint violations.
@ -115,6 +118,29 @@ public class ConstraintViolationConverter {
} }
public final static InstanceConstraintViolationsDTO toDTO(
InstanceConstraintViolationsDTOId instanceId,
RecoverableErrorException recoverableErrorException) {
List<PropertyDTO> properties = new ArrayList<PropertyDTO>();
for (Map.Entry<String, String> p :
recoverableErrorException.getProperties().entrySet()) {
properties.add(new PropertyDTO(p.getKey(), p.getValue()));
}
RecoverableErrorDTO recoverableErrorDTO = new RecoverableErrorDTO(
recoverableErrorException.getErrorCode().ordinal() + 1,
recoverableErrorException.getMessage(),
properties);
return new InstanceConstraintViolationsDTO(instanceId,
recoverableErrorDTO);
}
public final static InstanceConstraintViolationsDTO toDTO( public final static InstanceConstraintViolationsDTO toDTO(
InstanceConstraintViolationsDTOId instanceId, InstanceConstraintViolationsDTOId instanceId,
RuntimeException runtimeException) { RuntimeException runtimeException) {

View file

@ -57,7 +57,8 @@ public abstract class GenericRESTService<E extends IntegrationEntity,
* It saves (inserts or updates) a list of entities. Each entity is * It saves (inserts or updates) a list of entities. Each entity is
* saved in a separate transaction. * saved in a separate transaction.
*/ */
protected InstanceConstraintViolationsListDTO save(List<DTO> entityDTOs) { protected InstanceConstraintViolationsListDTO save(
List<? extends DTO> entityDTOs) {
List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList = List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList =
new ArrayList<InstanceConstraintViolationsDTO>(); new ArrayList<InstanceConstraintViolationsDTO>();
@ -75,6 +76,11 @@ public abstract class GenericRESTService<E extends IntegrationEntity,
ConstraintViolationConverter.toDTO( ConstraintViolationConverter.toDTO(
Util.generateInstanceConstraintViolationsDTOId( Util.generateInstanceConstraintViolationsDTOId(
numItem, entityDTO), e); numItem, entityDTO), e);
} catch (RecoverableErrorException e) {
instanceConstraintViolationsDTO =
ConstraintViolationConverter.toDTO(
Util.generateInstanceConstraintViolationsDTOId(
numItem, entityDTO), e);
} catch (RuntimeException e) { } catch (RuntimeException e) {
instanceConstraintViolationsDTO = instanceConstraintViolationsDTO =
ConstraintViolationConverter.toDTO( ConstraintViolationConverter.toDTO(
@ -100,9 +106,15 @@ public abstract class GenericRESTService<E extends IntegrationEntity,
* It saves (inserts or updates) an entity DTO by using a new transaction. * It saves (inserts or updates) an entity DTO by using a new transaction.
* *
* @throws ValidationException if validations are not passed * @throws ValidationException if validations are not passed
* @throws RecoverableErrorException if a recoverable error occurs
*/ */
protected void insertOrUpdate(final DTO entityDTO) protected void insertOrUpdate(final DTO entityDTO)
throws ValidationException { throws ValidationException, RecoverableErrorException {
/*
* NOTE: ValidationException and RecoverableErrorException are runtime
* exceptions. In consequence, if any of them occurs, transaction is
* automatically rolled back.
*/
IOnTransaction<Void> save = new IOnTransaction<Void>() { IOnTransaction<Void> save = new IOnTransaction<Void>() {
@ -122,13 +134,22 @@ public abstract class GenericRESTService<E extends IntegrationEntity,
} }
/* /*
* Save the entity (insert or update). If validations are * Save the entity (insert or update).
* not passed (they are automatically executed by *
* GenericDAO::save), the transaction is rolled back since * IGenericDAO::save first reattaches the object into the
* ValidationException is a runtime exception, automatically * underlying ORM session, and then calls BaseEntity::validate.
* discarding any change made to the entity. * 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).
* *
*/ */
entity.validate();
entityDAO.save(entity); entityDAO.save(entity);
return null; return null;
@ -143,8 +164,14 @@ public abstract class GenericRESTService<E extends IntegrationEntity,
/** /**
* It creates an entity from a DTO. * It creates an entity from a DTO.
*
* @throws ValidationException if it is not possible to create the entity
* because some very important constraint is violated
* @throws RecoverableErrorException if a recoverable
* error occurs
*/ */
protected abstract E toEntity(DTO entityDTO); protected abstract E toEntity(DTO entityDTO)
throws ValidationException, RecoverableErrorException;
/** /**
* It creates a DTO from an entity. * It creates a DTO from an entity.
@ -160,10 +187,12 @@ public abstract class GenericRESTService<E extends IntegrationEntity,
/** /**
* It must update the entity from the DTO. * It must update the entity from the DTO.
* *
* @throws ValidationException if updating is not possible * @throws ValidationException if updating is not possible because some
* very important constraint is violated
* @throws RecoverableErrorException if a recoverable error occurs
*/ */
protected abstract void updateEntity(E entity, DTO entityDTO) protected abstract void updateEntity(E entity, DTO entityDTO)
throws ValidationException; throws ValidationException, RecoverableErrorException;
/** /**
* It returns a list of DTOs from a list of entities. * It returns a list of DTOs from a list of entities.

View file

@ -0,0 +1,56 @@
/*
* This file is part of NavalPlan
*
* Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.navalplanner.ws.common.impl;
import static org.navalplanner.web.I18nHelper._;
import java.util.HashMap;
import java.util.Map;
/**
* A recoverable error modeling "instance not found".
*
* @author Fernando Bellas Permuy <fbellas@udc.es>
*/
@SuppressWarnings("serial")
public class InstanceNotFoundRecoverableErrorException
extends RecoverableErrorException {
/**
*
* @param type type of the instance not found
* @param value name of the instance not found
*/
public InstanceNotFoundRecoverableErrorException(String type,
String value) {
super(_("instance not found"),
RecoverableErrorCodeEnum.INSTANCE_NOT_FOUND);
Map<String, String> properties = new HashMap<String, String>();
properties.put("type", type);
properties.put("value", value);
setProperties(properties);
}
}

View file

@ -18,19 +18,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.navalplanner.business.common.exceptions; package org.navalplanner.ws.common.impl;
/** /**
* An exception representing that a "createUnvalidated" method in an entity * An enumeration to specify all types of recoverable errors.
* class could not create an instance.
* *
* @author Fernando Bellas Permuy <fbellas@udc.es> * @author Fernando Bellas Permuy <fbellas@udc.es>
*/ */
@SuppressWarnings("serial") public enum RecoverableErrorCodeEnum {
public class CreateUnvalidatedException extends Exception { INSTANCE_NOT_FOUND
public CreateUnvalidatedException(String message) {
super(message);
}
} }

View file

@ -0,0 +1,56 @@
/*
* This file is part of NavalPlan
*
* Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.navalplanner.ws.common.impl;
import java.util.Map;
/**
* An exception to modeling a recoverable error.
*
* @author Fernando Bellas Permuy <fbellas@udc.es>
*/
@SuppressWarnings("serial")
public abstract class RecoverableErrorException extends RuntimeException {
private RecoverableErrorCodeEnum errorCode;
private Map<String, String> properties;
protected RecoverableErrorException(String message,
RecoverableErrorCodeEnum errorCode) {
super(message);
this.errorCode = errorCode;
}
public RecoverableErrorCodeEnum getErrorCode() {
return errorCode;
}
public Map<String, String> getProperties() {
return properties;
}
protected void setProperties(Map<String, String> properties) {
this.properties = properties;
}
}

View file

@ -111,7 +111,7 @@ public final class CriterionConverter {
} }
public final static void updateCriterionType(CriterionType criterionType, public final static void updateCriterionType(CriterionType criterionType,
CriterionTypeDTO criterionTypeDTO) throws ValidationException { CriterionTypeDTO criterionTypeDTO) {
/* 1: Get criterion wrappers with parent code. */ /* 1: Get criterion wrappers with parent code. */
Set<CriterionDTOWithParentCode> criterionWrappers = Set<CriterionDTOWithParentCode> criterionWrappers =

View file

@ -25,20 +25,24 @@ import static org.navalplanner.web.I18nHelper._;
import java.util.List; import java.util.List;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.navalplanner.business.common.exceptions.CreateUnvalidatedException;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException; import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.common.exceptions.MultipleInstancesException; import org.navalplanner.business.common.exceptions.MultipleInstancesException;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.navalplanner.business.costcategories.entities.ResourcesCostCategoryAssignment; import org.navalplanner.business.costcategories.entities.ResourcesCostCategoryAssignment;
import org.navalplanner.business.resources.entities.CriterionSatisfaction; import org.navalplanner.business.resources.entities.CriterionSatisfaction;
import org.navalplanner.business.resources.entities.CriterionType;
import org.navalplanner.business.resources.entities.Machine; import org.navalplanner.business.resources.entities.Machine;
import org.navalplanner.business.resources.entities.Resource; import org.navalplanner.business.resources.entities.Resource;
import org.navalplanner.business.resources.entities.Worker; import org.navalplanner.business.resources.entities.Worker;
import org.navalplanner.ws.common.impl.DateConverter; import org.navalplanner.ws.common.impl.DateConverter;
import org.navalplanner.ws.common.impl.InstanceNotFoundRecoverableErrorException;
import org.navalplanner.ws.resources.api.CriterionSatisfactionDTO; import org.navalplanner.ws.resources.api.CriterionSatisfactionDTO;
import org.navalplanner.ws.resources.api.MachineDTO; import org.navalplanner.ws.resources.api.MachineDTO;
import org.navalplanner.ws.resources.api.ResourceDTO; import org.navalplanner.ws.resources.api.ResourceDTO;
import org.navalplanner.ws.resources.api.ResourcesCostCategoryAssignmentDTO; import org.navalplanner.ws.resources.api.ResourcesCostCategoryAssignmentDTO;
import org.navalplanner.ws.resources.api.WorkerDTO; import org.navalplanner.ws.resources.api.WorkerDTO;
import org.navalplanner.ws.resources.criterion.api.CriterionDTO;
import org.navalplanner.ws.resources.criterion.api.CriterionTypeDTO;
/** /**
* Converter from/to resource-related entities to/from DTOs. * Converter from/to resource-related entities to/from DTOs.
@ -49,8 +53,7 @@ public class ResourceConverter {
private ResourceConverter() {} private ResourceConverter() {}
public final static Resource toEntity(ResourceDTO resourceDTO) public final static Resource toEntity(ResourceDTO resourceDTO) {
throws CreateUnvalidatedException {
Resource resource; Resource resource;
@ -96,8 +99,7 @@ public class ResourceConverter {
} }
private static void addCriterionSatisfactions(Resource resource, private static void addCriterionSatisfactions(Resource resource,
List<CriterionSatisfactionDTO> criterionSatisfactions) List<CriterionSatisfactionDTO> criterionSatisfactions) {
throws CreateUnvalidatedException {
for (CriterionSatisfactionDTO criterionSatisfactionDTO : for (CriterionSatisfactionDTO criterionSatisfactionDTO :
criterionSatisfactions) { criterionSatisfactions) {
@ -112,30 +114,56 @@ public class ResourceConverter {
} }
private static CriterionSatisfaction toEntity( private static CriterionSatisfaction toEntity(
CriterionSatisfactionDTO criterionSatisfactionDTO, Resource resource) CriterionSatisfactionDTO criterionSatisfactionDTO, Resource resource) {
throws CreateUnvalidatedException {
return CriterionSatisfaction.createUnvalidated( if (StringUtils.isBlank(criterionSatisfactionDTO.criterionTypeName)) {
StringUtils.trim(criterionSatisfactionDTO.code), throw new ValidationException(
StringUtils.trim(criterionSatisfactionDTO.criterionTypeName), _("criterion type name not specified"));
StringUtils.trim(criterionSatisfactionDTO.criterionName), }
resource,
DateConverter.toDate(criterionSatisfactionDTO.startDate), if (StringUtils.isBlank(criterionSatisfactionDTO.criterionName)) {
DateConverter.toDate(criterionSatisfactionDTO.endDate)); throw new ValidationException(
_("criterion name not specified"));
}
try {
return CriterionSatisfaction.createUnvalidated(
StringUtils.trim(criterionSatisfactionDTO.code),
StringUtils.trim(criterionSatisfactionDTO.criterionTypeName),
StringUtils.trim(criterionSatisfactionDTO.criterionName),
resource,
DateConverter.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 setResourceCalendar(Resource resource, private static void setResourceCalendar(Resource resource,
String calendarName) throws CreateUnvalidatedException { String calendarName) {
try { try {
resource.setResourceCalendar(calendarName); resource.setResourceCalendar(calendarName);
} catch (InstanceNotFoundException e) { } catch (InstanceNotFoundException e) {
throw new CreateUnvalidatedException( throw new InstanceNotFoundRecoverableErrorException(
_("{0}: calendar not found", calendarName)); "resource-calendar", e.getKey().toString());
// TODO: literal "resource-calendar" should possibly be
// replaced by ResourceCalendarDTO.ENTITY_TYPE if
// ResourceCalendarDTO is created in the future.
} catch (MultipleInstancesException e) { } catch (MultipleInstancesException e) {
throw new CreateUnvalidatedException( throw new ValidationException(
_("there exist multiple calendars with name {0}", _("there exist multiple resource calendars with name {0}",
calendarName)); calendarName));
} }
@ -143,8 +171,7 @@ public class ResourceConverter {
private static void addResourcesCostCategoryAssignments( private static void addResourcesCostCategoryAssignments(
Resource resource, List<ResourcesCostCategoryAssignmentDTO> Resource resource, List<ResourcesCostCategoryAssignmentDTO>
resourcesCostCategoryAssignments) resourcesCostCategoryAssignments) {
throws CreateUnvalidatedException {
for (ResourcesCostCategoryAssignmentDTO assignmentDTO : for (ResourcesCostCategoryAssignmentDTO assignmentDTO :
resourcesCostCategoryAssignments) { resourcesCostCategoryAssignments) {
@ -158,13 +185,25 @@ public class ResourceConverter {
} }
private static ResourcesCostCategoryAssignment toEntity( private static ResourcesCostCategoryAssignment toEntity(
ResourcesCostCategoryAssignmentDTO assignmentDTO, Resource resource) ResourcesCostCategoryAssignmentDTO assignmentDTO, Resource resource) {
throws CreateUnvalidatedException {
return ResourcesCostCategoryAssignment.createUnvalidated( if (StringUtils.isBlank(assignmentDTO.costCategoryName)) {
assignmentDTO.code, assignmentDTO.costCategoryName, resource, throw new ValidationException(
DateConverter.toLocalDate(assignmentDTO.startDate), _("cost category name not specified"));
DateConverter.toLocalDate(assignmentDTO.endDate)); }
try {
return ResourcesCostCategoryAssignment.createUnvalidated(
assignmentDTO.code, 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.
}
} }

View file

@ -20,35 +20,22 @@
package org.navalplanner.ws.resources.impl; package org.navalplanner.ws.resources.impl;
import static org.navalplanner.web.I18nHelper._;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.POST; import javax.ws.rs.POST;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
import org.apache.commons.lang.StringUtils; import org.navalplanner.business.common.daos.IIntegrationEntityDAO;
import org.navalplanner.business.common.exceptions.CreateUnvalidatedException;
import org.navalplanner.business.common.exceptions.ValidationException; import org.navalplanner.business.common.exceptions.ValidationException;
import org.navalplanner.business.resources.daos.IResourceDAO; import org.navalplanner.business.resources.daos.IResourceDAO;
import org.navalplanner.business.resources.entities.Resource; import org.navalplanner.business.resources.entities.Resource;
import org.navalplanner.ws.common.api.InstanceConstraintViolationsDTO;
import org.navalplanner.ws.common.api.InstanceConstraintViolationsListDTO; import org.navalplanner.ws.common.api.InstanceConstraintViolationsListDTO;
import org.navalplanner.ws.common.impl.ConstraintViolationConverter; import org.navalplanner.ws.common.impl.GenericRESTService;
import org.navalplanner.ws.common.impl.Util;
import org.navalplanner.ws.resources.api.IResourceService; import org.navalplanner.ws.resources.api.IResourceService;
import org.navalplanner.ws.resources.api.MachineDTO;
import org.navalplanner.ws.resources.api.ResourceDTO; import org.navalplanner.ws.resources.api.ResourceDTO;
import org.navalplanner.ws.resources.api.ResourceListDTO; import org.navalplanner.ws.resources.api.ResourceListDTO;
import org.navalplanner.ws.resources.api.WorkerDTO;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/** /**
* REST-based implementation of <code>IResourceService</code>. * REST-based implementation of <code>IResourceService</code>.
@ -58,7 +45,9 @@ import org.springframework.transaction.annotation.Transactional;
@Path("/resources/") @Path("/resources/")
@Produces("application/xml") @Produces("application/xml")
@Service("resourceServiceREST") @Service("resourceServiceREST")
public class ResourceServiceREST implements IResourceService { public class ResourceServiceREST
extends GenericRESTService<Resource, ResourceDTO>
implements IResourceService {
@Autowired @Autowired
private IResourceDAO resourceDAO; private IResourceDAO resourceDAO;
@ -66,117 +55,32 @@ public class ResourceServiceREST implements IResourceService {
@Override @Override
@POST @POST
@Consumes("application/xml") @Consumes("application/xml")
@Transactional
public InstanceConstraintViolationsListDTO addResources( public InstanceConstraintViolationsListDTO addResources(
ResourceListDTO resources) { ResourceListDTO resources) {
List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList = return save(resources.resources);
new ArrayList<InstanceConstraintViolationsDTO>();
int instanceNumber = 1;
Set<String> resourceUserProvidedIds = new HashSet<String>();
/* Process resources. */
for (ResourceDTO resourceDTO : resources.resources) {
InstanceConstraintViolationsDTO instanceConstraintViolationsDTO =
null;
Resource resource = null;
/* Convert DTO to entity. */
try {
resource = ResourceConverter.toEntity(resourceDTO);
} catch (CreateUnvalidatedException e) {
instanceConstraintViolationsDTO =
InstanceConstraintViolationsDTO.create(
Util.generateInstanceConstraintViolationsDTOId(
(long) instanceNumber, resourceDTO),
e.getMessage());
}
/* Validate resource. */
if (resource != null) {
try {
if (resourceUserProvidedIds.contains(
getUserProvidedId(resourceDTO).toLowerCase())) {
instanceConstraintViolationsDTO =
InstanceConstraintViolationsDTO.create(
Util.generateInstanceConstraintViolationsDTOId(
(long) instanceNumber, resourceDTO),
getDuplicatedImportedResourceErrorMessage(
resourceDTO));
} else {
/*
* See CriterionServiceREST::addCriterionTypes for a
* justification of the explicit use of
* BaseEntity::validate.
*
*/
resource.validate();
resourceDAO.save(resource);
resourceUserProvidedIds.add(
getUserProvidedId(resourceDTO).toLowerCase());
}
} catch (ValidationException e) {
instanceConstraintViolationsDTO =
ConstraintViolationConverter.toDTO(
Util.generateInstanceConstraintViolationsDTOId(
(long) instanceNumber, resourceDTO), e);
}
}
/* Add constraint violations (if any). */
if (instanceConstraintViolationsDTO != null) {
instanceConstraintViolationsList.add(
instanceConstraintViolationsDTO);
}
instanceNumber++;
}
return new InstanceConstraintViolationsListDTO(
instanceConstraintViolationsList);
} }
private String getUserProvidedId(ResourceDTO resourceDTO) { @Override
protected Resource toEntity(ResourceDTO entityDTO) {
if (resourceDTO instanceof MachineDTO) { return ResourceConverter.toEntity(entityDTO);
MachineDTO m = (MachineDTO) resourceDTO;
return "machine" + '-' + StringUtils.trim(m.code);
} else if (resourceDTO instanceof WorkerDTO) {
WorkerDTO w = (WorkerDTO) resourceDTO;
return "worker" + '-' + StringUtils.trim(w.firstName) +
'-' + StringUtils.trim(w.surname) + '-' +
StringUtils.trim(w.nif);
} else {
throw new RuntimeException(
_("Service does not manage resource of type: {0}",
resourceDTO.getClass().getName()));
}
} }
private String getDuplicatedImportedResourceErrorMessage( @Override
ResourceDTO resourceDTO) { protected ResourceDTO toDTO(Resource entity) {
return null; // This service does not provide finder methods.
}
if (resourceDTO instanceof MachineDTO) { @Override
return _("code is used by another machine being imported"); protected IIntegrationEntityDAO<Resource> getIntegrationEntityDAO() {
} else if (resourceDTO instanceof WorkerDTO) { return resourceDAO;
return _("first name, surname, and nif are used by another " + }
"worker being imported");
} else {
throw new RuntimeException(
_("Service does not manage resource of type: {0}",
resourceDTO.getClass().getName()));
}
@Override
protected void updateEntity(Resource entity, ResourceDTO entityDTO)
throws ValidationException {
// FIXME: updated functionality not implemented yet.
} }
} }

View file

@ -21,6 +21,7 @@
package org.navalplanner.web.test.ws.common; package org.navalplanner.web.test.ws.common;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import java.util.List; import java.util.List;
@ -90,6 +91,8 @@ public class Util {
assertTrue( assertTrue(
instanceConstraintViolationsList.toString(), instanceConstraintViolationsList.toString(),
instanceConstraintViolationsList.size() == 1); instanceConstraintViolationsList.size() == 1);
assertNoRecoverableError(instanceConstraintViolationsList.get(0));
assertNoInternalError(instanceConstraintViolationsList.get(0));
assertNotNull(instanceConstraintViolationsList.get(0). assertNotNull(instanceConstraintViolationsList.get(0).
constraintViolations); constraintViolations);
assertTrue( assertTrue(
@ -115,6 +118,8 @@ public class Util {
for (InstanceConstraintViolationsDTO i : for (InstanceConstraintViolationsDTO i :
instanceConstraintViolationsList) { instanceConstraintViolationsList) {
assertNoRecoverableError(i);
assertNoInternalError(i);
assertNotNull(i.constraintViolations); assertNotNull(i.constraintViolations);
assertTrue( assertTrue(
i.constraintViolations.toString(), i.constraintViolations.toString(),
@ -123,4 +128,44 @@ public class Util {
} }
public static void assertOneRecoverableError(
InstanceConstraintViolationsListDTO
instanceConstraintViolationsListDTO) {
List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList =
instanceConstraintViolationsListDTO.
instanceConstraintViolationsList;
assertNotNull(instanceConstraintViolationsListDTO.
instanceConstraintViolationsList);
assertTrue(
instanceConstraintViolationsList.toString(),
instanceConstraintViolationsList.size() == 1);
assertNoConstraintViolations(instanceConstraintViolationsList.get(0));
assertNoInternalError(instanceConstraintViolationsList.get(0));
assertNotNull(instanceConstraintViolationsList.get(0).recoverableError);
}
private static void assertNoConstraintViolations(
InstanceConstraintViolationsDTO i) {
assertNull(i.toString(), i.constraintViolations);
}
private static void assertNoRecoverableError(
InstanceConstraintViolationsDTO i) {
assertNull(i.toString(), i.recoverableError);
}
private static void assertNoInternalError(
InstanceConstraintViolationsDTO i) {
assertNull(i.toString(), i.internalError);
}
} }

View file

@ -26,11 +26,11 @@ import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import static org.navalplanner.business.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_FILE; import static org.navalplanner.business.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_FILE;
import static org.navalplanner.web.WebappGlobalNames.WEBAPP_SPRING_CONFIG_FILE; import static org.navalplanner.web.WebappGlobalNames.WEBAPP_SPRING_CONFIG_FILE;
import static org.navalplanner.web.WebappGlobalNames.WEBAPP_SPRING_SECURITY_CONFIG_FILE;
import static org.navalplanner.web.test.WebappGlobalNames.WEBAPP_SPRING_CONFIG_TEST_FILE; import static org.navalplanner.web.test.WebappGlobalNames.WEBAPP_SPRING_CONFIG_TEST_FILE;
import static org.navalplanner.web.test.ws.common.Util.assertNoConstraintViolations; import static org.navalplanner.web.test.ws.common.Util.assertNoConstraintViolations;
import static org.navalplanner.web.test.ws.common.Util.assertOneConstraintViolation; import static org.navalplanner.web.test.ws.common.Util.assertOneConstraintViolation;
import static org.navalplanner.web.test.ws.common.Util.assertOneConstraintViolationPerInstance; import static org.navalplanner.web.test.ws.common.Util.assertOneConstraintViolationPerInstance;
import static org.navalplanner.web.test.ws.common.Util.assertOneRecoverableError;
import static org.navalplanner.web.test.ws.common.Util.getUniqueName; import static org.navalplanner.web.test.ws.common.Util.getUniqueName;
import java.util.ArrayList; import java.util.ArrayList;
@ -50,13 +50,11 @@ import org.navalplanner.business.common.IAdHocTransactionService;
import org.navalplanner.business.common.IOnTransaction; import org.navalplanner.business.common.IOnTransaction;
import org.navalplanner.business.common.daos.IConfigurationDAO; import org.navalplanner.business.common.daos.IConfigurationDAO;
import org.navalplanner.business.common.entities.IConfigurationBootstrap; 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.daos.ICostCategoryDAO;
import org.navalplanner.business.costcategories.entities.CostCategory; import org.navalplanner.business.costcategories.entities.CostCategory;
import org.navalplanner.business.resources.daos.ICriterionTypeDAO; import org.navalplanner.business.resources.daos.ICriterionTypeDAO;
import org.navalplanner.business.resources.daos.IMachineDAO; import org.navalplanner.business.resources.daos.IMachineDAO;
import org.navalplanner.business.resources.daos.IResourceDAO; 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.Criterion;
import org.navalplanner.business.resources.entities.CriterionSatisfaction; import org.navalplanner.business.resources.entities.CriterionSatisfaction;
import org.navalplanner.business.resources.entities.CriterionType; import org.navalplanner.business.resources.entities.CriterionType;
@ -73,7 +71,6 @@ import org.navalplanner.ws.resources.api.ResourceListDTO;
import org.navalplanner.ws.resources.api.ResourcesCostCategoryAssignmentDTO; import org.navalplanner.ws.resources.api.ResourcesCostCategoryAssignmentDTO;
import org.navalplanner.ws.resources.api.WorkerDTO; import org.navalplanner.ws.resources.api.WorkerDTO;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.NotTransactional;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -84,9 +81,8 @@ import org.springframework.transaction.annotation.Transactional;
* @author Fernando Bellas Permuy <fbellas@udc.es> * @author Fernando Bellas Permuy <fbellas@udc.es>
*/ */
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { BUSINESS_SPRING_CONFIG_FILE, @ContextConfiguration(locations = {BUSINESS_SPRING_CONFIG_FILE,
WEBAPP_SPRING_CONFIG_FILE, WEBAPP_SPRING_CONFIG_TEST_FILE, WEBAPP_SPRING_CONFIG_FILE, WEBAPP_SPRING_CONFIG_TEST_FILE})
WEBAPP_SPRING_SECURITY_CONFIG_FILE })
@Transactional @Transactional
public class ResourceServiceTest { public class ResourceServiceTest {
@ -99,9 +95,6 @@ public class ResourceServiceTest {
@Autowired @Autowired
private IMachineDAO machineDAO; private IMachineDAO machineDAO;
@Autowired
private IWorkerDAO workerDAO;
@Autowired @Autowired
private ICriterionTypeDAO criterionTypeDAO; private ICriterionTypeDAO criterionTypeDAO;
@ -122,32 +115,40 @@ public class ResourceServiceTest {
@Before @Before
public void loadConfiguration() { public void loadConfiguration() {
configurationBootstrap.loadRequiredData();
IOnTransaction<Void> load =
new IOnTransaction<Void>() {
@Override
public Void execute() {
configurationBootstrap.loadRequiredData();
return null;
}
};
transactionService.runOnAnotherTransaction(load);
} }
@Test @Test
public void testAddResourcesWithBasicContraintViolations() public void testAddResourcesWithBasicContraintViolations() {
throws InstanceNotFoundException {
/* Create resource DTOs. */ /* Create resource DTOs. */
String m1Code = ' ' + getUniqueName() + ' '; // Blank spaces MachineDTO m1 = new MachineDTO("name", "desc");
// intentionally MachineDTO m2 = new MachineDTO(" ", null, ""); // Missing code and name
// added (OK).
MachineDTO m1 = new MachineDTO(m1Code, "name", "desc");
MachineDTO m2 = new MachineDTO("", null, ""); // Missing code and name
// (description is // (description is
// optional). // optional).
String w1Nif = ' ' + getUniqueName() + ' '; // Blank spaces
// intentionally WorkerDTO w1 = new WorkerDTO(getUniqueName(), "w1-surname", "w1-nif");
// added (OK). WorkerDTO w2 = new WorkerDTO(null, "", null, ""); // Missing code, first
WorkerDTO w1 = new WorkerDTO("w1-first-name", "w1-surname", w1Nif); // name, surname, and
WorkerDTO w2 = new WorkerDTO("", null, ""); // Missing first name, // nif.
// surname, and nif.
/* Test. */ /* Test. */
List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList = List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList =
resourceService.addResources(createResourceListDTO(m1, m2, w1, w2)). resourceService.addResources(
instanceConstraintViolationsList; createResourceListDTO(m1, m2, w1, w2)).
instanceConstraintViolationsList;
assertTrue( assertTrue(
instanceConstraintViolationsList.toString(), instanceConstraintViolationsList.toString(),
@ -161,35 +162,13 @@ public class ResourceServiceTest {
instanceConstraintViolationsList.get(1). instanceConstraintViolationsList.get(1).
constraintViolations.toString(), constraintViolations.toString(),
instanceConstraintViolationsList.get(1). instanceConstraintViolationsList.get(1).
constraintViolations.size() == 3); // w2 constraint violations. constraintViolations.size() == 4); // w2 constraint violations.
machineDAO.findUniqueByCode(m1Code.trim()); assertTrue(resourceDAO.existsByCode(m1.code));
assertTrue( assertTrue(resourceDAO.existsByCode(w1.code));
workerDAO.findByFirstNameSecondNameAndNif(
w1.firstName, w1.surname, w1.nif.trim()).size() == 1);
} }
@Test @Test
@NotTransactional
public void testAddMachineWithExistingCode()
throws InstanceNotFoundException {
/* Create a machine. */
Machine m1 = Machine.createUnvalidated(getUniqueName(), "name", "desc");
saveResource(m1);
/* Create a machine DTO with the same code. */
MachineDTO m2 = new MachineDTO(m1.getCode(), "name", "desc");
/* Test. */
assertOneConstraintViolation(
resourceService.addResources(createResourceListDTO(m2)));
machineDAO.findUniqueByCodeInAnotherTransaction(m1.getCode());
}
@Test
@NotTransactional
public void testAddWorkerWithExistingFirstNameSurnameAndNif() { public void testAddWorkerWithExistingFirstNameSurnameAndNif() {
/* Create a worker. */ /* Create a worker. */
@ -207,29 +186,55 @@ public class ResourceServiceTest {
/* Test. */ /* Test. */
assertOneConstraintViolation( assertOneConstraintViolation(
resourceService.addResources(createResourceListDTO(w2))); resourceService.addResources(createResourceListDTO(w2)));
assertTrue( assertFalse(resourceDAO.existsByCode(w2.code));
workerDAO.findByFirstNameSecondNameAndNifAnotherTransaction(
w2.firstName, w2.surname, w2.nif).size() == 1);
} }
@Test @Test
public void testAddResourcesWithDuplicateResourcesBeingImported() public void testAddResourceWithCriterionSatisfactions() {
throws InstanceNotFoundException {
/* Create resource DTOs. */ /* Create a criterion type. */
MachineDTO m1 = new MachineDTO(getUniqueName(), "m1-name", "m1-desc"); CriterionType ct = createCriterionType();
MachineDTO m2 = new MachineDTO(' ' + m1.code.toUpperCase() + ' ',
"m2-name", "m2-desc"); /* Create a resource DTO. */
WorkerDTO w1 = new WorkerDTO(getUniqueName(), "w1-surname", "w1-nif"); MachineDTO m1 = new MachineDTO("name", "desc");
WorkerDTO w2 = new WorkerDTO(w1.firstName, CriterionSatisfactionDTO cs1m1 =
' ' + w1.surname.toUpperCase() + ' ', w1.nif); new CriterionSatisfactionDTO(
' ' + ct.getName().toUpperCase() + // Upper case and blank
' ', " C1 ", // spaces intentionally
// added (OK).
getDate(2001, 1, 1), getDate(2001, 2, 1));
m1.criterionSatisfactions.add(cs1m1);
m1.criterionSatisfactions.add(
new CriterionSatisfactionDTO(ct.getName(), "c2",
getDate(2001, 1, 1), null));
MachineDTO m2 = new MachineDTO("name", "desc");
m2.criterionSatisfactions.add(
new CriterionSatisfactionDTO(cs1m1.code, ct.getName(), "c1",
getDate(2001, 1, 1), null)); // Repeated criterion satisfaction
// code (used by another machine).
m2.criterionSatisfactions.add(
new CriterionSatisfactionDTO(null, ct.getName(), "c2",
getDate(2001, 1, 1), null)); // Missing criterion satisfaction
// code.
MachineDTO m3 = new MachineDTO("name", "desc");
CriterionSatisfactionDTO cs1m3 =
new CriterionSatisfactionDTO(ct.getName(), "c1",
getDate(2001, 1, 1), getDate(2001, 2, 1));
m3.criterionSatisfactions.add(cs1m3);
m3.criterionSatisfactions.add(
new CriterionSatisfactionDTO(
cs1m3.code, // Repeated criterion satisfaction code in this
// machine.
ct.getName(), "c2",
getDate(2001, 1, 1), null));
/* Test. */ /* Test. */
List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList = List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList =
resourceService.addResources(createResourceListDTO(m1, m2, w1, w2)). resourceService.addResources(createResourceListDTO(m1, m2, m3)).
instanceConstraintViolationsList; instanceConstraintViolationsList;
assertTrue( assertTrue(
instanceConstraintViolationsList.toString(), instanceConstraintViolationsList.toString(),
@ -238,49 +243,16 @@ public class ResourceServiceTest {
instanceConstraintViolationsList.get(0). instanceConstraintViolationsList.get(0).
constraintViolations.toString(), constraintViolations.toString(),
instanceConstraintViolationsList.get(0). instanceConstraintViolationsList.get(0).
constraintViolations.size() == 1); constraintViolations.size() == 2); // m2 constraint violations.
assertTrue( assertTrue(
instanceConstraintViolationsList.get(1). instanceConstraintViolationsList.get(1).
constraintViolations.toString(), constraintViolations.toString(),
instanceConstraintViolationsList.get(1). instanceConstraintViolationsList.get(1).
constraintViolations.size() == 1); constraintViolations.size() == 1); // m3 constraint violations.
machineDAO.findUniqueByCode(m1.code); assertFalse(resourceDAO.existsByCode(m2.code));
assertTrue( assertFalse(resourceDAO.existsByCode(m3.code));
workerDAO.findByFirstNameSecondNameAndNif(
w1.firstName, w1.surname, w1.nif.trim()).size() == 1);
} Machine machine = machineDAO.findExistingEntityByCode(m1.code);
@Test
@NotTransactional
public void testAddResourceWithCriterionSatisfactions()
throws InstanceNotFoundException {
/* Create a criterion type. */
CriterionType ct = createCriterionType();
/* Create a resource DTO. */
MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc");
machineDTO.criterionSatisfactions.add(
new CriterionSatisfactionDTO(
' ' + ct.getName().toUpperCase() + // Upper case and blank
' ', " C1 ", // spaces intentionally
// added (OK).
getDate(2001, 1, 1), getDate(2001, 2, 1)));
machineDTO.criterionSatisfactions.add(
new CriterionSatisfactionDTO(ct.getName(), "c2",
getDate(2001, 1, 1), null));
/* Test. */
List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList =
resourceService.addResources(createResourceListDTO(machineDTO)).
instanceConstraintViolationsList;
assertTrue(
instanceConstraintViolationsList.toString(),
instanceConstraintViolationsList.isEmpty());
Machine machine = findUniqueMachineByCodeInitialized(machineDTO.code);
assertTrue(machine.getCriterionSatisfactions().size() == 2); assertTrue(machine.getCriterionSatisfactions().size() == 2);
for (CriterionSatisfaction cs : machine.getCriterionSatisfactions()) { for (CriterionSatisfaction cs : machine.getCriterionSatisfactions()) {
@ -290,17 +262,18 @@ public class ResourceServiceTest {
} }
} }
assertFalse(resourceDAO.existsByCode(m2.code));
} }
@Test @Test
@NotTransactional
public void testAddResourceWithCriterionSatisfactionWithoutStartDate() { public void testAddResourceWithCriterionSatisfactionWithoutStartDate() {
/* Create a criterion type. */ /* Create a criterion type. */
CriterionType ct = createCriterionType(); CriterionType ct = createCriterionType();
/* Create a machine DTO. */ /* Create a machine DTO. */
MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc"); MachineDTO machineDTO = new MachineDTO("name", "desc");
machineDTO.criterionSatisfactions.add( machineDTO.criterionSatisfactions.add(
new CriterionSatisfactionDTO(ct.getName() , "c1", new CriterionSatisfactionDTO(ct.getName() , "c1",
null, getDate(2001, 1, 1))); // Missing start date. null, getDate(2001, 1, 1))); // Missing start date.
@ -308,20 +281,18 @@ public class ResourceServiceTest {
/* Test. */ /* Test. */
assertOneConstraintViolation( assertOneConstraintViolation(
resourceService.addResources(createResourceListDTO(machineDTO))); resourceService.addResources(createResourceListDTO(machineDTO)));
assertFalse(machineDAO.existsMachineWithCodeInAnotherTransaction( assertFalse(resourceDAO.existsByCode(machineDTO.code));
machineDTO.code));
} }
@Test @Test
@NotTransactional
public void testAddResourceWithCriterionSatisfactionWithNegativeInterval() { public void testAddResourceWithCriterionSatisfactionWithNegativeInterval() {
/* Create a criterion type. */ /* Create a criterion type. */
CriterionType ct = createCriterionType(); CriterionType ct = createCriterionType();
/* Create a machine DTO. */ /* Create a machine DTO. */
MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc"); MachineDTO machineDTO = new MachineDTO("name", "desc");
machineDTO.criterionSatisfactions.add( machineDTO.criterionSatisfactions.add(
new CriterionSatisfactionDTO(ct.getName() , "c1", new CriterionSatisfactionDTO(ct.getName() , "c1",
getDate(2000, 2, 1), getDate(2000, 1, 1))); getDate(2000, 2, 1), getDate(2000, 1, 1)));
@ -329,13 +300,11 @@ public class ResourceServiceTest {
/* Test. */ /* Test. */
assertOneConstraintViolation( assertOneConstraintViolation(
resourceService.addResources(createResourceListDTO(machineDTO))); resourceService.addResources(createResourceListDTO(machineDTO)));
assertFalse(machineDAO.existsMachineWithCodeInAnotherTransaction( assertFalse(resourceDAO.existsByCode(machineDTO.code));
machineDTO.code));
} }
@Test @Test
@NotTransactional
public void testAddResourceWithOverlappingCriterionSatisfactionsAllowed() { public void testAddResourceWithOverlappingCriterionSatisfactionsAllowed() {
/* Create a criterion type. */ /* Create a criterion type. */
@ -353,13 +322,11 @@ public class ResourceServiceTest {
/* Test. */ /* Test. */
assertNoConstraintViolations( assertNoConstraintViolations(
resourceService.addResources(createResourceListDTO(machineDTO))); resourceService.addResources(createResourceListDTO(machineDTO)));
assertTrue(machineDAO.existsMachineWithCodeInAnotherTransaction( assertTrue(resourceDAO.existsByCode(machineDTO.code));
machineDTO.code));
} }
@Test @Test
@NotTransactional
public void testAddResourceWithOverlappingCriterionSatisfactions() { public void testAddResourceWithOverlappingCriterionSatisfactions() {
/* Create criterion types. */ /* Create criterion types. */
@ -395,22 +362,20 @@ public class ResourceServiceTest {
MachineDTO m = (MachineDTO) r; MachineDTO m = (MachineDTO) r;
assertFalse( assertFalse(
"Machine " + m.name + " not expected", "Machine " + m.name + " not expected",
machineDAO.existsMachineWithCodeInAnotherTransaction( resourceDAO.existsByCode(((MachineDTO) r).code));
((MachineDTO) r).code));
} }
} }
@Test @Test
@NotTransactional public void testAddResourcesWithCriterionSatisfactionsWithIncorrectCriterionType() {
public void testAddResourcesWithCriterionSatisfactionsWithIncorrectType() {
/* Create two criterion types. */ /* Create two criterion types. */
CriterionType machineCt = createCriterionType(ResourceEnum.MACHINE); CriterionType machineCt = createCriterionType(ResourceEnum.MACHINE);
CriterionType workerCt = createCriterionType(ResourceEnum.WORKER); CriterionType workerCt = createCriterionType(ResourceEnum.WORKER);
/* Create resource DTOs. */ /* Create resource DTOs. */
MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc"); MachineDTO machineDTO = new MachineDTO("name", "desc");
machineDTO.criterionSatisfactions.add( machineDTO.criterionSatisfactions.add(
new CriterionSatisfactionDTO(workerCt.getName() , "c1", new CriterionSatisfactionDTO(workerCt.getName() , "c1",
getDate(2001, 1, 1), null)); // Incorrect type. getDate(2001, 1, 1), null)); // Incorrect type.
@ -422,158 +387,29 @@ public class ResourceServiceTest {
/* Test. */ /* Test. */
assertOneConstraintViolation( assertOneConstraintViolation(
resourceService.addResources(createResourceListDTO(machineDTO))); resourceService.addResources(createResourceListDTO(machineDTO)));
assertFalse(machineDAO.existsMachineWithCodeInAnotherTransaction( assertFalse(
machineDTO.code)); resourceDAO.existsByCode(machineDTO.code));
assertOneConstraintViolation( assertOneConstraintViolation(
resourceService.addResources(createResourceListDTO(workerDTO))); resourceService.addResources(createResourceListDTO(workerDTO)));
assertTrue(workerDAO.findByFirstNameSecondNameAndNifAnotherTransaction( assertFalse(resourceDAO.existsByCode(workerDTO.code));
workerDTO.firstName, workerDTO.surname, workerDTO.nif).size() == 0);
} }
@Test @Test
@NotTransactional public void testAddResourcesWithCriterionSatisfactionsWithMissingNames() {
public void testAddResourcesWithCriterionSatisfactionsWithIncorrectNames() {
/* Create a criterion type. */ /* Create a criterion type. */
CriterionType ct = createCriterionType(); CriterionType ct = createCriterionType();
/* Create machines DTOs. */ /* Create machines DTOs. */
MachineDTO m1 = new MachineDTO(getUniqueName(), "m1", "desc"); MachineDTO m1 = new MachineDTO("m1", "desc");
m1.criterionSatisfactions.add( m1.criterionSatisfactions.add(
new CriterionSatisfactionDTO("", "X", // Missing criterion type. new CriterionSatisfactionDTO("", "X", // Missing criterion type.
getDate(2001, 1, 1), null)); getDate(2001, 1, 1), null));
MachineDTO m2 = new MachineDTO(getUniqueName(), "m2", "desc"); MachineDTO m2 = new MachineDTO("m2", "desc");
m2.criterionSatisfactions.add( m2.criterionSatisfactions.add(
new CriterionSatisfactionDTO(ct.getName(), // Missing criterion. new CriterionSatisfactionDTO(ct.getName(), // Missing criterion.
null, getDate(2001, 1, 1), null)); null, getDate(2001, 1, 1), null));
MachineDTO m3 = new MachineDTO(getUniqueName(), "m3", "desc");
m3.criterionSatisfactions.add(
new CriterionSatisfactionDTO(
ct.getName() + 'X', // Non-existent criterion type.
"c1", getDate(2001, 1, 1), null));
MachineDTO m4 = new MachineDTO(getUniqueName(), "m4", "desc");
m4.criterionSatisfactions.add(
new CriterionSatisfactionDTO(
ct.getName(),
"c1" + 'X', // Criterion name is not of ct's type.
getDate(2001, 1, 1), null));
/* Test. */
ResourceListDTO resourceDTOs = createResourceListDTO(m1, m2, m3, m4);
assertOneConstraintViolationPerInstance(
resourceService.addResources(resourceDTOs),
resourceDTOs.resources.size());
for (ResourceDTO r : resourceDTOs.resources) {
MachineDTO m = (MachineDTO) r;
assertFalse(
"Machine " + m.name + " not expected",
machineDAO.existsMachineWithCodeInAnotherTransaction(
((MachineDTO) r).code));
}
}
@Test
@NotTransactional
public void testAddResourceWithDefaultCalendar()
throws InstanceNotFoundException {
/* Create a machine DTO. */
MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc");
/* Test. */
assertNoConstraintViolations(resourceService.
addResources(createResourceListDTO(machineDTO)));
Machine machine = findUniqueMachineByCodeInitialized(machineDTO.code);
assertEquals(getDefaultCalendar().getId(),
machine.getCalendar().getParent().getId());
}
@Test
@NotTransactional
public void testAddResourceWithSpecificCalendar()
throws InstanceNotFoundException {
/* Create a base calendar. */
BaseCalendar baseCalendar = createBaseCalendar();
/* Create a machine DTO. */
MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc");
machineDTO.calendarName =
' ' + baseCalendar.getName().toUpperCase() + ' ';
/* Test. */
assertNoConstraintViolations(resourceService.
addResources(createResourceListDTO(machineDTO)));
Machine machine = findUniqueMachineByCodeInitialized(machineDTO.code);
assertEquals(baseCalendar.getId(),
machine.getCalendar().getParent().getId());
}
@Test
@NotTransactional
public void testAddResourceWithNonExistentCalendar()
throws InstanceNotFoundException {
/* Create a machine DTO. */
MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc");
machineDTO.calendarName = getUniqueName();
/* Test. */
assertOneConstraintViolation(resourceService.
addResources(createResourceListDTO(machineDTO)));
assertFalse(machineDAO.existsMachineWithCodeInAnotherTransaction(
machineDTO.code));
}
@Test
@NotTransactional
public void testAddResourceWithCostAssignments() {
/* Create a CostCategory. */
CostCategory costCategory = createCostCategory();
/* Create resource DTOs. */
MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc");
machineDTO.resourcesCostCategoryAssignments.add(
new ResourcesCostCategoryAssignmentDTO(
' ' + costCategory.getName().toUpperCase() + ' ',
getDate(2001, 1, 1), null));
machineDTO.resourcesCostCategoryAssignments.add(
new ResourcesCostCategoryAssignmentDTO(
costCategory.getName(),
getDate(2000, 1, 1), getDate(2000, 4, 1)));
/* Test. */
assertNoConstraintViolations(
resourceService.addResources(createResourceListDTO(machineDTO)));
assertTrue(machineDAO.existsMachineWithCodeInAnotherTransaction(
machineDTO.code));
}
@Test
@NotTransactional
public void testAddResourcesWithCostAssignmentWithIncorrectCategoryNames() {
/* Create a resource DTOs. */
MachineDTO m1 = new MachineDTO(getUniqueName(), "m1", "desc");
m1.resourcesCostCategoryAssignments.add(
new ResourcesCostCategoryAssignmentDTO(
null, // Cost category not specified.
getDate(2000, 1, 1), null));
MachineDTO m2 = new MachineDTO(getUniqueName(), "m2", "desc");
m2.resourcesCostCategoryAssignments.add(
new ResourcesCostCategoryAssignmentDTO(
getUniqueName(), // Non-existent cost category.
getDate(2000, 1, 1), null));
/* Test. */ /* Test. */
ResourceListDTO resourceDTOs = createResourceListDTO(m1, m2); ResourceListDTO resourceDTOs = createResourceListDTO(m1, m2);
@ -586,20 +422,200 @@ public class ResourceServiceTest {
MachineDTO m = (MachineDTO) r; MachineDTO m = (MachineDTO) r;
assertFalse( assertFalse(
"Machine " + m.name + " not expected", "Machine " + m.name + " not expected",
machineDAO.existsMachineWithCodeInAnotherTransaction(m.code)); resourceDAO.existsByCode(((MachineDTO) r).code));
}; }
}
@Test
public void testAddResourceWithCriterionSatisfactionsWithNonExistentCriterionType() {
/* Create a machine DTO. */
MachineDTO machineDTO = new MachineDTO("name", "desc");
machineDTO.criterionSatisfactions.add(
new CriterionSatisfactionDTO(getUniqueName() , "c1",
getDate(2000, 1, 1), null));
/* Test. */
assertOneRecoverableError(
resourceService.addResources(createResourceListDTO(machineDTO)));
assertFalse(resourceDAO.existsByCode(machineDTO.code));
}
@Test
public void testAddResourceWithCriterionSatisfactionsWithNonExistentCriterion() {
/* Create a criterion type. */
CriterionType ct = createCriterionType();
/* Create a machine DTO. */
MachineDTO machineDTO = new MachineDTO("name", "desc");
machineDTO.criterionSatisfactions.add(
new CriterionSatisfactionDTO(ct.getName(), getUniqueName(),
getDate(2000, 1, 1), null));
/* Test. */
assertOneRecoverableError(
resourceService.addResources(createResourceListDTO(machineDTO)));
assertFalse(resourceDAO.existsByCode(machineDTO.code));
}
@Test
public void testAddResourceWithDefaultCalendar() {
/* Create a machine DTO. */
MachineDTO machineDTO = new MachineDTO("name", "desc");
/* Test. */
assertNoConstraintViolations(resourceService.
addResources(createResourceListDTO(machineDTO)));
Machine machine = machineDAO.findExistingEntityByCode(machineDTO.code);
assertEquals(getDefaultCalendar().getId(),
machine.getCalendar().getParent().getId());
}
@Test
public void testAddResourceWithSpecificCalendar() {
/* Create a base calendar. */
BaseCalendar baseCalendar = createBaseCalendar();
/* Create a machine DTO. */
MachineDTO machineDTO = new MachineDTO("name", "desc");
machineDTO.calendarName =
' ' + baseCalendar.getName().toUpperCase() + ' ';
/* Test. */
assertNoConstraintViolations(resourceService.
addResources(createResourceListDTO(machineDTO)));
Machine machine = machineDAO.findExistingEntityByCode(machineDTO.code);
assertEquals(baseCalendar.getId(),
machine.getCalendar().getParent().getId());
}
@Test
public void testAddResourceWithNonExistentCalendar() {
/* Create a machine DTO. */
MachineDTO machineDTO = new MachineDTO("name", "desc");
machineDTO.calendarName = getUniqueName();
/* Test. */
assertOneRecoverableError(resourceService.
addResources(createResourceListDTO(machineDTO)));
assertFalse(resourceDAO.existsByCode(machineDTO.code));
}
@Test
public void testAddResourceWithCostAssignments() {
/* Create a CostCategory. */
CostCategory costCategory = createCostCategory();
/* Create resource DTOs. */
MachineDTO m1 = new MachineDTO("name", "desc");
ResourcesCostCategoryAssignmentDTO a1m1 =
new ResourcesCostCategoryAssignmentDTO(
' ' + costCategory.getName().toUpperCase() + ' ',
getDate(2001, 1, 1), null);
m1.resourcesCostCategoryAssignments.add(a1m1);
m1.resourcesCostCategoryAssignments.add(
new ResourcesCostCategoryAssignmentDTO(
costCategory.getName(),
getDate(2000, 1, 1), getDate(2000, 4, 1)));
MachineDTO m2 = new MachineDTO("name", "desc");
m2.resourcesCostCategoryAssignments.add(
new ResourcesCostCategoryAssignmentDTO(a1m1.code,
costCategory.getName().toUpperCase(),
getDate(2001, 1, 1), null)); // Repeated assignment code
// (used by another machine).
m2.resourcesCostCategoryAssignments.add(
new ResourcesCostCategoryAssignmentDTO(null,
costCategory.getName().toUpperCase(),
getDate(2000, 1, 1), getDate(2000, 4, 1))); // Missing
// assignment code.
MachineDTO m3 = new MachineDTO("name", "desc");
ResourcesCostCategoryAssignmentDTO a1m3 =
new ResourcesCostCategoryAssignmentDTO(costCategory.getName(),
getDate(2001, 1, 1), null);
m3.resourcesCostCategoryAssignments.add(a1m3);
m3.resourcesCostCategoryAssignments.add(
new ResourcesCostCategoryAssignmentDTO(
a1m3.code, // Repeated assignment code in this machine.
costCategory.getName(),
getDate(2000, 1, 1), getDate(2000, 4, 1)));
/* Test. */
List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList =
resourceService.addResources(createResourceListDTO(m1, m2, m3)).
instanceConstraintViolationsList;
assertTrue(
instanceConstraintViolationsList.toString(),
instanceConstraintViolationsList.size() == 2);
assertTrue(
instanceConstraintViolationsList.get(0).
constraintViolations.toString(),
instanceConstraintViolationsList.get(0).
constraintViolations.size() == 2); // m2 constraint violations.
assertTrue(
instanceConstraintViolationsList.get(1).
constraintViolations.toString(),
instanceConstraintViolationsList.get(1).
constraintViolations.size() == 1); // m3 constraint violations.
assertTrue(resourceDAO.existsByCode(m1.code));
assertFalse(resourceDAO.existsByCode(m2.code));
}
@Test
public void testAddResourcesWithCostAssignmentWithMissingCostCategoryName() {
/* Create a resource DTO. */
MachineDTO machineDTO = new MachineDTO("name", "desc");
machineDTO.resourcesCostCategoryAssignments.add(
new ResourcesCostCategoryAssignmentDTO(
"", null, getDate(2000, 1, 1), null));
/* Test. */
assertOneConstraintViolation(
resourceService.addResources(createResourceListDTO(machineDTO)));
assertFalse(resourceDAO.existsByCode(machineDTO.code));
}
@Test
public void testAddResourcesWithCostAssignmentWithNonExistentCostCategory() {
/* Create a resource DTO. */
MachineDTO machineDTO = new MachineDTO("name", "desc");
machineDTO.resourcesCostCategoryAssignments.add(
new ResourcesCostCategoryAssignmentDTO(
getUniqueName(), getDate(2000, 1, 1), null));
/* Test. */
assertOneRecoverableError(
resourceService.addResources(createResourceListDTO(machineDTO)));
assertFalse(resourceDAO.existsByCode(machineDTO.code));
} }
@Test @Test
@NotTransactional
public void testAddResourceWithCostAssignmentWithoutStartDate() { public void testAddResourceWithCostAssignmentWithoutStartDate() {
/* Create a CostCategory. */ /* Create a CostCategory. */
CostCategory costCategory = createCostCategory(); CostCategory costCategory = createCostCategory();
/* Create a resource DTO. */ /* Create a resource DTO. */
MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc"); MachineDTO machineDTO = new MachineDTO("name", "desc");
machineDTO.resourcesCostCategoryAssignments.add( machineDTO.resourcesCostCategoryAssignments.add(
new ResourcesCostCategoryAssignmentDTO( new ResourcesCostCategoryAssignmentDTO(
costCategory.getName(), null, // Start date not specified. costCategory.getName(), null, // Start date not specified.
@ -608,20 +624,18 @@ public class ResourceServiceTest {
/* Test. */ /* Test. */
assertOneConstraintViolation( assertOneConstraintViolation(
resourceService.addResources(createResourceListDTO(machineDTO))); resourceService.addResources(createResourceListDTO(machineDTO)));
assertFalse(machineDAO.existsMachineWithCodeInAnotherTransaction( assertFalse(resourceDAO.existsByCode(machineDTO.code));
machineDTO.code));
} }
@Test @Test
@NotTransactional
public void testAddResourceWithCostAssignmentWithNegativeInterval() { public void testAddResourceWithCostAssignmentWithNegativeInterval() {
/* Create a CostCategory. */ /* Create a CostCategory. */
CostCategory costCategory = createCostCategory(); CostCategory costCategory = createCostCategory();
/* Create a resource DTO. */ /* Create a resource DTO. */
MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc"); MachineDTO machineDTO = new MachineDTO("name", "desc");
machineDTO.resourcesCostCategoryAssignments.add( machineDTO.resourcesCostCategoryAssignments.add(
new ResourcesCostCategoryAssignmentDTO( new ResourcesCostCategoryAssignmentDTO(
costCategory.getName(), costCategory.getName(),
@ -630,13 +644,11 @@ public class ResourceServiceTest {
/* Test. */ /* Test. */
assertOneConstraintViolation( assertOneConstraintViolation(
resourceService.addResources(createResourceListDTO(machineDTO))); resourceService.addResources(createResourceListDTO(machineDTO)));
assertFalse(machineDAO.existsMachineWithCodeInAnotherTransaction( assertFalse(resourceDAO.existsByCode(machineDTO.code));
machineDTO.code));
} }
@Test @Test
@NotTransactional
public void testAddResourcesWithOverlappingInCostAssignments() { public void testAddResourcesWithOverlappingInCostAssignments() {
/* Create a CostCategory. */ /* Create a CostCategory. */
@ -703,8 +715,7 @@ public class ResourceServiceTest {
MachineDTO m = (MachineDTO) r; MachineDTO m = (MachineDTO) r;
assertFalse( assertFalse(
"Machine " + m.name + " not expected", "Machine " + m.name + " not expected",
machineDAO.existsMachineWithCodeInAnotherTransaction( resourceDAO.existsByCode(((MachineDTO) r).code));
((MachineDTO) r).code));
} }
} }
@ -742,45 +753,7 @@ public class ResourceServiceTest {
} }
}; };
return transactionService.runOnTransaction(createCriterionType); return transactionService.runOnAnotherTransaction(createCriterionType);
}
private Machine findUniqueMachineByCodeInitialized(final String code)
throws InstanceNotFoundException {
IOnTransaction<Machine> find = new IOnTransaction<Machine>() {
@Override
public Machine execute() {
try {
return (Machine) initializeResource(
machineDAO.findUniqueByCode(code));
} catch (InstanceNotFoundException e) {
return null;
}
}
};
Machine machine = transactionService.runOnTransaction(find);
if (machine == null) {
throw new InstanceNotFoundException(code, Machine.class.getName());
} else {
return machine;
}
}
private Resource initializeResource(Resource resource) {
for (CriterionSatisfaction cs : resource.getCriterionSatisfactions()) {
cs.getCriterion().getType().getName();
}
resource.getCalendar().getParent();
return resource;
} }
@ -795,7 +768,7 @@ public class ResourceServiceTest {
} }
}; };
transactionService.runOnTransaction(save); transactionService.runOnAnotherTransaction(save);
} }
@ -809,7 +782,7 @@ public class ResourceServiceTest {
} }
}; };
return transactionService.runOnTransaction(find); return transactionService.runOnAnotherTransaction(find);
} }
@ -827,7 +800,7 @@ public class ResourceServiceTest {
} }
}; };
return transactionService.runOnTransaction(create); return transactionService.runOnAnotherTransaction(create);
} }
@ -858,7 +831,7 @@ public class ResourceServiceTest {
} }
}; };
return transactionService.runOnTransaction(create); return transactionService.runOnAnotherTransaction(create);
} }
@ -870,8 +843,7 @@ public class ResourceServiceTest {
String criterionName2, XMLGregorianCalendar startDate2, String criterionName2, XMLGregorianCalendar startDate2,
XMLGregorianCalendar endDate2) { XMLGregorianCalendar endDate2) {
MachineDTO machineDTO = new MachineDTO(getUniqueName(), machineName, MachineDTO machineDTO = new MachineDTO(machineName, "desc");
"desc");
machineDTO.criterionSatisfactions.add( machineDTO.criterionSatisfactions.add(
new CriterionSatisfactionDTO(criterionTypeName, criterionName1, new CriterionSatisfactionDTO(criterionTypeName, criterionName1,
@ -889,8 +861,7 @@ public class ResourceServiceTest {
XMLGregorianCalendar startDate1, XMLGregorianCalendar endDate1, XMLGregorianCalendar startDate1, XMLGregorianCalendar endDate1,
XMLGregorianCalendar startDate2, XMLGregorianCalendar endDate2) { XMLGregorianCalendar startDate2, XMLGregorianCalendar endDate2) {
MachineDTO machineDTO = new MachineDTO(getUniqueName(), machineName, MachineDTO machineDTO = new MachineDTO(machineName, "desc");
"desc");
machineDTO.resourcesCostCategoryAssignments.add( machineDTO.resourcesCostCategoryAssignments.add(
new ResourcesCostCategoryAssignmentDTO( new ResourcesCostCategoryAssignmentDTO(

View file

@ -47,7 +47,6 @@ import org.navalplanner.ws.resources.criterion.api.CriterionTypeDTO;
import org.navalplanner.ws.resources.criterion.api.CriterionTypeListDTO; import org.navalplanner.ws.resources.criterion.api.CriterionTypeListDTO;
import org.navalplanner.ws.resources.criterion.api.ICriterionService; import org.navalplanner.ws.resources.criterion.api.ICriterionService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.NotTransactional;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -59,7 +58,7 @@ import org.springframework.transaction.annotation.Transactional;
*/ */
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { BUSINESS_SPRING_CONFIG_FILE, @ContextConfiguration(locations = { BUSINESS_SPRING_CONFIG_FILE,
WEBAPP_SPRING_CONFIG_FILE, WEBAPP_SPRING_CONFIG_TEST_FILE }) WEBAPP_SPRING_CONFIG_FILE, WEBAPP_SPRING_CONFIG_TEST_FILE })
@Transactional @Transactional
public class CriterionServiceTest { public class CriterionServiceTest {
@ -70,7 +69,6 @@ public class CriterionServiceTest {
private ICriterionTypeDAO criterionTypeDAO; private ICriterionTypeDAO criterionTypeDAO;
@Test @Test
@NotTransactional
public void testAddAndGetCriterionTypes() { public void testAddAndGetCriterionTypes() {
/* Build criterion type "ct1" (5 constraint violations). */ /* Build criterion type "ct1" (5 constraint violations). */
@ -100,8 +98,7 @@ public class CriterionServiceTest {
ct1Criterions.add(ct1c3); ct1Criterions.add(ct1c3);
ct1Criterions.add(ct1c4); ct1Criterions.add(ct1c4);
ct1Criterions.add(ct1c5); ct1Criterions.add(ct1c5);
String ct1Name = null; CriterionTypeDTO ct1 = new CriterionTypeDTO(null, "desc",
CriterionTypeDTO ct1 = new CriterionTypeDTO(ct1Name, "desc",
false, true, true, ResourceEnumDTO.RESOURCE, // Missing criterion false, true, true, ResourceEnumDTO.RESOURCE, // Missing criterion
ct1Criterions); // type name. ct1Criterions); // type name.
@ -118,8 +115,7 @@ public class CriterionServiceTest {
List<CriterionDTO> ct2Criterions = new ArrayList<CriterionDTO>(); List<CriterionDTO> ct2Criterions = new ArrayList<CriterionDTO>();
ct2Criterions.add(ct2c1); ct2Criterions.add(ct2c1);
ct2Criterions.add(ct2c2); ct2Criterions.add(ct2c2);
String ct2Name = getUniqueName(); CriterionTypeDTO ct2 = new CriterionTypeDTO(getUniqueName(), "desc",
CriterionTypeDTO ct2 = new CriterionTypeDTO(ct2Name, "desc",
true, true, false, ResourceEnumDTO.RESOURCE, ct2Criterions); true, true, false, ResourceEnumDTO.RESOURCE, ct2Criterions);
/* Build criterion type "ct3" (OK). */ /* Build criterion type "ct3" (OK). */
@ -134,14 +130,13 @@ public class CriterionServiceTest {
List<CriterionDTO> ct3Criterions = new ArrayList<CriterionDTO>(); List<CriterionDTO> ct3Criterions = new ArrayList<CriterionDTO>();
ct3Criterions.add(ct3c1); ct3Criterions.add(ct3c1);
ct3Criterions.add(ct3c2); ct3Criterions.add(ct3c2);
String ct3Name = getUniqueName(); CriterionTypeDTO ct3 = new CriterionTypeDTO(getUniqueName(), "desc",
CriterionTypeDTO ct3 = new CriterionTypeDTO(ct3Name, "desc",
true, true, true, ResourceEnumDTO.RESOURCE, ct3Criterions); true, true, true, ResourceEnumDTO.RESOURCE, ct3Criterions);
/* Build criterion type "ct4" (1 constraint violation). */ /* Build criterion type "ct4" (1 constraint violation). */
CriterionTypeDTO ct4 = CriterionTypeDTO ct4 =
new CriterionTypeDTO( // Repeated criterion new CriterionTypeDTO( // Repeated criterion
' ' + ct3Name.toUpperCase() + ' ', // type name. ' ' + ct3.name.toUpperCase() + ' ', // type name.
"desc", true, true, true, "desc", true, true, true,
ResourceEnumDTO.RESOURCE, new ArrayList<CriterionDTO>()); ResourceEnumDTO.RESOURCE, new ArrayList<CriterionDTO>());
@ -154,9 +149,19 @@ public class CriterionServiceTest {
CriterionTypeDTO ct5 = new CriterionTypeDTO(getUniqueName(), "desc", CriterionTypeDTO ct5 = new CriterionTypeDTO(getUniqueName(), "desc",
true, true, true, ResourceEnumDTO.RESOURCE, ct5Criterions); true, true, true, ResourceEnumDTO.RESOURCE, ct5Criterions);
/* Build criterion type "ct6" (2 constraint violations). */
CriterionDTO ct6c1 = new CriterionDTO(null, // Missing criterion code.
"c1", true, new ArrayList<CriterionDTO>());
List<CriterionDTO> ct6Criterions = new ArrayList<CriterionDTO>();
ct6Criterions.add(ct6c1);
CriterionTypeDTO ct6 =
new CriterionTypeDTO(null, getUniqueName(), // Missing criterion
// type code.
"desc", true, true, true, ResourceEnumDTO.RESOURCE, ct6Criterions);
/* Criterion type list. */ /* Criterion type list. */
CriterionTypeListDTO criterionTypes = CriterionTypeListDTO criterionTypes =
createCriterionTypeListDTO(ct1, ct2, ct3, ct4, ct5); createCriterionTypeListDTO(ct1, ct2, ct3, ct4, ct5, ct6);
List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList = List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList =
criterionService.addCriterionTypes(criterionTypes). criterionService.addCriterionTypes(criterionTypes).
@ -164,40 +169,47 @@ public class CriterionServiceTest {
assertTrue( assertTrue(
instanceConstraintViolationsList.toString(), instanceConstraintViolationsList.toString(),
instanceConstraintViolationsList.size() == 4); instanceConstraintViolationsList.size() == 5);
assertTrue( assertTrue(
instanceConstraintViolationsList.get(0). instanceConstraintViolationsList.get(0).
constraintViolations.toString(), constraintViolations.toString(),
instanceConstraintViolationsList.get(0). instanceConstraintViolationsList.get(0).
constraintViolations.size() == 5); constraintViolations.size() == 5); // ct1 constraint violations.
assertTrue( assertTrue(
instanceConstraintViolationsList.get(1). instanceConstraintViolationsList.get(1).
constraintViolations.toString(), constraintViolations.toString(),
instanceConstraintViolationsList.get(1). instanceConstraintViolationsList.get(1).
constraintViolations.size() == 2); constraintViolations.size() == 2); // ct2 constraint violations.
assertTrue( assertTrue(
instanceConstraintViolationsList.get(2). instanceConstraintViolationsList.get(2).
constraintViolations.toString(), constraintViolations.toString(),
instanceConstraintViolationsList.get(2). instanceConstraintViolationsList.get(2).
constraintViolations.size() == 1); constraintViolations.size() == 1); // ct4 constraint violations.
assertTrue( assertTrue(
instanceConstraintViolationsList.get(3). instanceConstraintViolationsList.get(3).
constraintViolations.toString(), constraintViolations.toString(),
instanceConstraintViolationsList.get(3). instanceConstraintViolationsList.get(3).
constraintViolations.size() == 1); constraintViolations.size() == 1); // ct5 constraint violations.
assertTrue(
instanceConstraintViolationsList.get(4).
constraintViolations.toString(),
instanceConstraintViolationsList.get(4).
constraintViolations.size() == 2); // ct6 constraint violations.
/* Find criterion types. */ /* Find criterion types. */
List<CriterionTypeDTO> returnedCriterionTypes = List<CriterionTypeDTO> returnedCriterionTypes =
criterionService.getCriterionTypes().criterionTypes; criterionService.getCriterionTypes().criterionTypes;
assertFalse(containsCriterionType(returnedCriterionTypes, ct1Name)); /* Test. */
assertFalse(containsCriterionType(returnedCriterionTypes, ct2Name)); assertFalse(criterionTypeDAO.existsByCode(ct2.code));
assertTrue(containsCriterionType(returnedCriterionTypes, ct3Name)); assertTrue(criterionTypeDAO.existsByCode(ct3.code));
assertFalse(criterionTypeDAO.existsByCode(ct4.code));
assertTrue(containsCriterionType(returnedCriterionTypes, ct3.code));
} }
@Test @Test
@Transactional
public void testUpdateCriterionType() throws InstanceNotFoundException { public void testUpdateCriterionType() throws InstanceNotFoundException {
/* Build criterion type with criteria: c1, c2->c2-1. */ /* Build criterion type with criteria: c1, c2->c2-1. */
@ -286,10 +298,10 @@ public class CriterionServiceTest {
} }
private boolean containsCriterionType( private boolean containsCriterionType(
List<CriterionTypeDTO> criterionTypes, String criterionTypeName) { List<CriterionTypeDTO> criterionTypes, String code) {
for (CriterionTypeDTO c : criterionTypes) { for (CriterionTypeDTO c : criterionTypes) {
if (c.name.equals(criterionTypeName)) { if (c.code.equals(code)) {
return true; return true;
} }
} }

View file

@ -24,35 +24,51 @@
</criterion-satisfaction-list> </criterion-satisfaction-list>
</machine> </machine>
<!-- Another machine is being imported with the same code. -->
<machine code="m1" name="m3-name" description="m3-desc"/>
<!-- OK or not OK depending on the existence of "TestCalendar". -->
<machine code="m4" name="m4-name" description="m4-desc"
calendar-name="TestCalendar"/>
<!-- [It assumes existence of "TestCostCategory"] OK. --> <!-- [It assumes existence of "TestCostCategory"] OK. -->
<machine code="m5" name="m5-name" description="m5-desc"> <machine code="m3" name="m3-name" description="m3-desc">
<resources-cost-category-assignment-list> <resources-cost-category-assignment-list>
<resources-cost-category-assignment <resources-cost-category-assignment
code="m5-a1" code="m3-a1"
cost-category-name="TestCostCategory" cost-category-name="TestCostCategory"
start-date="2001-01-01"/> start-date="2001-01-01"/>
<resources-cost-category-assignment <resources-cost-category-assignment
code="m5-a2" code="m3-a2"
cost-category-name="TestCostCategory" cost-category-name="TestCostCategory"
start-date="2000-01-01" start-date="2000-01-01"
end-date="2000-04-01"/> end-date="2000-04-01"/>
</resources-cost-category-assignment-list> </resources-cost-category-assignment-list>
</machine> </machine>
<!-- [It assumes existence of "TestCostCategory"] Missing start date. --> <!-- [It assumes existence of "TestCostCategory"] Repeated cost assignment
code (used by another machine). -->
<machine code="m4" name="m4-name" description="m4-desc">
<resources-cost-category-assignment-list>
<resources-cost-category-assignment
code="m3-a1"
cost-category-name="TestCostCategory"
start-date="2001-01-01"/>
</resources-cost-category-assignment-list>
</machine>
<!-- OK or not OK depending on the existence of "TestCalendar". -->
<machine code="m5" name="m5-name" description="m5-desc"
calendar-name="TestCalendar"/>
<!-- [It assumes existence of "TestCostCategory"] Missing start date and
code, and repeated code in cost assignments. -->
<machine code="m6" name="m6-name" description="m6-desc"> <machine code="m6" name="m6-name" description="m6-desc">
<resources-cost-category-assignment-list> <resources-cost-category-assignment-list>
<resources-cost-category-assignment <resources-cost-category-assignment
code="m6-a1" code="m6-a1"
cost-category-name="TestCostCategory" cost-category-name="TestCostCategory"
end-date="2000-01-01"/> end-date="2000-01-01"/>
<resources-cost-category-assignment
cost-category-name="TestCostCategory"
start-date="2001-01-01"/>
<resources-cost-category-assignment
code="m6-a1"
cost-category-name="TestCostCategory"
start-date="2000-01-01" end-date="2000-02-01"/>
</resources-cost-category-assignment-list> </resources-cost-category-assignment-list>
</machine> </machine>
@ -106,7 +122,8 @@
</criterion-satisfaction-list> </criterion-satisfaction-list>
</worker> </worker>
<!-- Missing start date in criterion satisfaction. --> <!-- Missing start date and code, and repeated code in criterion
satisfactions. -->
<worker code="w2" first-name="w2-firstName" surname="w2-surname" nif="w2-nif"> <worker code="w2" first-name="w2-firstName" surname="w2-surname" nif="w2-nif">
<criterion-satisfaction-list> <criterion-satisfaction-list>
<criterion-satisfaction <criterion-satisfaction
@ -114,6 +131,15 @@
criterion-type-name="LEAVE" criterion-type-name="LEAVE"
criterion-name="paternityLeave" criterion-name="paternityLeave"
end-date="2009-12-25"/> end-date="2009-12-25"/>
<criterion-satisfaction
criterion-type-name="LEAVE"
criterion-name="paternityLeave"
start-date="2009-12-25"/>
<criterion-satisfaction
code="w2-s1"
criterion-type-name="LEAVE"
criterion-name="paternityLeave"
start-date="2000-01-01" end="2000-02-01"/>
</criterion-satisfaction-list> </criterion-satisfaction-list>
</worker> </worker>
@ -290,8 +316,22 @@
</criterion-satisfaction-list> </criterion-satisfaction-list>
</worker> </worker>
<!-- Another worker is being imported with the same first name, surname, <!-- There is another worker with the same first name, surname, and nif. -->
and nif. -->
<worker code="w15" first-name="w1-firstName" surname="w1-surname" nif="w1-nif"/> <worker code="w15" first-name="w1-firstName" surname="w1-surname" nif="w1-nif"/>
<!-- Repeated criterion satisfaction code (used by another worker). -->
<worker code="w16" first-name="w16-firstName" surname="w16-surname" nif="w16-nif">
<criterion-satisfaction-list>
<criterion-satisfaction
code="w1-s1"
criterion-type-name="WORK_RELATIONSHIP"
criterion-name="hiredResourceWorkingRelationship"
start-date="2009-01-01"
end-date=""/>
</criterion-satisfaction-list>
</worker>
<!-- Missing code. -->
<worker first-name="w17-firstName" surname="w17-surname" nif="w17-nif"/>
</resource-list> </resource-list>