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(
Restrictions.eq("code", code).ignoreCase()).uniqueResult();
Restrictions.eq("code", code.trim()).ignoreCase()).uniqueResult();
if (entity == null) {
throw new InstanceNotFoundException(

View file

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

View file

@ -22,7 +22,7 @@ package org.navalplanner.business.resources.daos;
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.resources.entities.Machine;
@ -31,8 +31,9 @@ import org.navalplanner.business.resources.entities.Machine;
*
* @author Diego Pino Garcia <dpino@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

View file

@ -23,7 +23,7 @@ package org.navalplanner.business.resources.daos;
import java.util.Date;
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.reports.dtos.HoursWorkedPerWorkerDTO;
import org.navalplanner.business.resources.entities.Worker;
@ -37,7 +37,7 @@ import org.springframework.transaction.annotation.Transactional;
* @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

View file

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

View file

@ -26,7 +26,7 @@ import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Query;
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.reports.dtos.HoursWorkedPerWorkerDTO;
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.Transactional;
/**
* Hibernate DAO for the <code>Worker</code> entity.
*
@ -46,7 +47,7 @@ import org.springframework.transaction.annotation.Transactional;
*/
@Repository
@Scope(BeanDefinition.SCOPE_SINGLETON)
public class WorkerDAO extends GenericDAOHibernate<Worker, Long>
public class WorkerDAO extends IntegrationEntityDAO<Worker>
implements IWorkerDAO {
@Override

View file

@ -20,19 +20,15 @@
package org.navalplanner.business.resources.entities;
import static org.navalplanner.business.i18n.I18nHelper._;
import java.util.Comparator;
import java.util.Date;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.hibernate.validator.AssertTrue;
import org.hibernate.validator.NotNull;
import org.navalplanner.business.common.IntegrationEntity;
import org.navalplanner.business.common.Registry;
import org.navalplanner.business.common.exceptions.CreateUnvalidatedException;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.resources.daos.ICriterionSatisfactionDAO;
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(
String code, String criterionTypeName, String criterionName,
Resource resource, Date startDate, Date finishDate)
throws CreateUnvalidatedException {
throws InstanceNotFoundException {
ICriterionTypeDAO criterionTypeDAO =
Registry.getCriterionTypeDAO();
/* Get CriterionType. */
if (StringUtils.isBlank(criterionTypeName)) {
throw new CreateUnvalidatedException(
_("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));
}
CriterionType criterionType = criterionTypeDAO.findUniqueByName(
criterionTypeName);
/* Get Criterion. */
if (StringUtils.isBlank(criterionName)) {
throw new CreateUnvalidatedException(
_("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));
}
Criterion criterion = criterionType.getCriterion(
criterionName);
/* Create instance of CriterionSatisfaction. */
CriterionSatisfaction criterionSatisfaction =

View file

@ -27,7 +27,6 @@ import java.util.List;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
/**
* 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)
public String entityType;
@XmlElementWrapper(name="constraint-violations")
@XmlElement(name="constraint-violation")
public List<ConstraintViolationDTO> constraintViolations;
@XmlElement(name="recoverable-error")
public RecoverableErrorDTO recoverableError;
@XmlElement(name="internal-error")
public InternalErrorDTO internalError;
@ -93,6 +94,15 @@ public class InstanceConstraintViolationsDTO {
}
public InstanceConstraintViolationsDTO(
InstanceConstraintViolationsDTOId instanceId,
RecoverableErrorDTO recoverableError) {
this(instanceId);
this.recoverableError = recoverableError;
}
public InstanceConstraintViolationsDTO(
InstanceConstraintViolationsDTOId instanceId,
InternalErrorDTO internalError) {
@ -144,8 +154,23 @@ public class InstanceConstraintViolationsDTO {
ENTITY_TYPE_ATTRIBUTE_NAME + " = " + entityType +
" **");
for (ConstraintViolationDTO i : constraintViolations) {
printWriter.println(i);
if (internalError != null) {
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();

View file

@ -20,23 +20,28 @@
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.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* DTO for modeling the response to be returned when an internal service error
* occurs.
* DTO for modeling an internal error.
*
* @author Fernando Bellas Permuy <fbellas@udc.es>
*/
@XmlRootElement(name="internal-error")
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;
@XmlElement(name="stack-trace")
@XmlElement(name=STACK_TRACE_ATTRIBUTE_NAME)
public String stackTrace;
public InternalErrorDTO() {}
@ -46,4 +51,18 @@ public class InternalErrorDTO {
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.List;
import java.util.Map;
import org.hibernate.validator.InvalidValue;
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.InstanceConstraintViolationsDTOId;
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.
@ -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(
InstanceConstraintViolationsDTOId instanceId,
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
* saved in a separate transaction.
*/
protected InstanceConstraintViolationsListDTO save(List<DTO> entityDTOs) {
protected InstanceConstraintViolationsListDTO save(
List<? extends DTO> entityDTOs) {
List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList =
new ArrayList<InstanceConstraintViolationsDTO>();
@ -75,6 +76,11 @@ public abstract class GenericRESTService<E extends IntegrationEntity,
ConstraintViolationConverter.toDTO(
Util.generateInstanceConstraintViolationsDTOId(
numItem, entityDTO), e);
} catch (RecoverableErrorException e) {
instanceConstraintViolationsDTO =
ConstraintViolationConverter.toDTO(
Util.generateInstanceConstraintViolationsDTOId(
numItem, entityDTO), e);
} catch (RuntimeException e) {
instanceConstraintViolationsDTO =
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.
*
* @throws ValidationException if validations are not passed
* @throws RecoverableErrorException if a recoverable error occurs
*/
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>() {
@ -122,13 +134,22 @@ public abstract class GenericRESTService<E extends IntegrationEntity,
}
/*
* Save the entity (insert or update). If validations are
* not passed (they are automatically executed by
* GenericDAO::save), the transaction is rolled back since
* ValidationException is a runtime exception, automatically
* discarding any change made to the entity.
* Save the entity (insert or update).
*
* IGenericDAO::save first reattaches the object into the
* underlying ORM session, and then calls BaseEntity::validate.
* Despite this, we must call BaseEntity::validate before
* IGenericDAO::save to avoid an invalid object to enter in
* the underlying ORM session. Otherwise, the ORM could try
* to flush the ORM session (with an invalid object violating
* database-level restrictions) when executing
* IGenericDAO::save, since this method calls
* BaseEntity::validate (after reattaching the object), which
* probably will cause queries to be launched to the database
* (which may cause the flushing).
*
*/
entity.validate();
entityDAO.save(entity);
return null;
@ -143,8 +164,14 @@ public abstract class GenericRESTService<E extends IntegrationEntity,
/**
* 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.
@ -160,10 +187,12 @@ public abstract class GenericRESTService<E extends IntegrationEntity,
/**
* 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)
throws ValidationException;
throws ValidationException, RecoverableErrorException;
/**
* 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/>.
*/
package org.navalplanner.business.common.exceptions;
package org.navalplanner.ws.common.impl;
/**
* An exception representing that a "createUnvalidated" method in an entity
* class could not create an instance.
* An enumeration to specify all types of recoverable errors.
*
* @author Fernando Bellas Permuy <fbellas@udc.es>
*/
@SuppressWarnings("serial")
public class CreateUnvalidatedException extends Exception {
public CreateUnvalidatedException(String message) {
super(message);
}
public enum RecoverableErrorCodeEnum {
INSTANCE_NOT_FOUND
}

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,
CriterionTypeDTO criterionTypeDTO) throws ValidationException {
CriterionTypeDTO criterionTypeDTO) {
/* 1: Get criterion wrappers with parent code. */
Set<CriterionDTOWithParentCode> criterionWrappers =

View file

@ -25,20 +25,24 @@ import static org.navalplanner.web.I18nHelper._;
import java.util.List;
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.MultipleInstancesException;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.navalplanner.business.costcategories.entities.ResourcesCostCategoryAssignment;
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.Resource;
import org.navalplanner.business.resources.entities.Worker;
import org.navalplanner.ws.common.impl.DateConverter;
import org.navalplanner.ws.common.impl.InstanceNotFoundRecoverableErrorException;
import org.navalplanner.ws.resources.api.CriterionSatisfactionDTO;
import org.navalplanner.ws.resources.api.MachineDTO;
import org.navalplanner.ws.resources.api.ResourceDTO;
import org.navalplanner.ws.resources.api.ResourcesCostCategoryAssignmentDTO;
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.
@ -49,8 +53,7 @@ public class ResourceConverter {
private ResourceConverter() {}
public final static Resource toEntity(ResourceDTO resourceDTO)
throws CreateUnvalidatedException {
public final static Resource toEntity(ResourceDTO resourceDTO) {
Resource resource;
@ -96,8 +99,7 @@ public class ResourceConverter {
}
private static void addCriterionSatisfactions(Resource resource,
List<CriterionSatisfactionDTO> criterionSatisfactions)
throws CreateUnvalidatedException {
List<CriterionSatisfactionDTO> criterionSatisfactions) {
for (CriterionSatisfactionDTO criterionSatisfactionDTO :
criterionSatisfactions) {
@ -112,30 +114,56 @@ public class ResourceConverter {
}
private static CriterionSatisfaction toEntity(
CriterionSatisfactionDTO criterionSatisfactionDTO, Resource resource)
throws CreateUnvalidatedException {
CriterionSatisfactionDTO criterionSatisfactionDTO, Resource resource) {
return CriterionSatisfaction.createUnvalidated(
StringUtils.trim(criterionSatisfactionDTO.code),
StringUtils.trim(criterionSatisfactionDTO.criterionTypeName),
StringUtils.trim(criterionSatisfactionDTO.criterionName),
resource,
DateConverter.toDate(criterionSatisfactionDTO.startDate),
DateConverter.toDate(criterionSatisfactionDTO.endDate));
if (StringUtils.isBlank(criterionSatisfactionDTO.criterionTypeName)) {
throw new ValidationException(
_("criterion type name not specified"));
}
if (StringUtils.isBlank(criterionSatisfactionDTO.criterionName)) {
throw new ValidationException(
_("criterion name not specified"));
}
try {
return CriterionSatisfaction.createUnvalidated(
StringUtils.trim(criterionSatisfactionDTO.code),
StringUtils.trim(criterionSatisfactionDTO.criterionTypeName),
StringUtils.trim(criterionSatisfactionDTO.criterionName),
resource,
DateConverter.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,
String calendarName) throws CreateUnvalidatedException {
String calendarName) {
try {
resource.setResourceCalendar(calendarName);
} catch (InstanceNotFoundException e) {
throw new CreateUnvalidatedException(
_("{0}: calendar not found", calendarName));
throw new InstanceNotFoundRecoverableErrorException(
"resource-calendar", e.getKey().toString());
// TODO: literal "resource-calendar" should possibly be
// replaced by ResourceCalendarDTO.ENTITY_TYPE if
// ResourceCalendarDTO is created in the future.
} catch (MultipleInstancesException e) {
throw new CreateUnvalidatedException(
_("there exist multiple calendars with name {0}",
throw new ValidationException(
_("there exist multiple resource calendars with name {0}",
calendarName));
}
@ -143,8 +171,7 @@ public class ResourceConverter {
private static void addResourcesCostCategoryAssignments(
Resource resource, List<ResourcesCostCategoryAssignmentDTO>
resourcesCostCategoryAssignments)
throws CreateUnvalidatedException {
resourcesCostCategoryAssignments) {
for (ResourcesCostCategoryAssignmentDTO assignmentDTO :
resourcesCostCategoryAssignments) {
@ -158,13 +185,25 @@ public class ResourceConverter {
}
private static ResourcesCostCategoryAssignment toEntity(
ResourcesCostCategoryAssignmentDTO assignmentDTO, Resource resource)
throws CreateUnvalidatedException {
ResourcesCostCategoryAssignmentDTO assignmentDTO, Resource resource) {
return ResourcesCostCategoryAssignment.createUnvalidated(
assignmentDTO.code, assignmentDTO.costCategoryName, resource,
DateConverter.toLocalDate(assignmentDTO.startDate),
DateConverter.toLocalDate(assignmentDTO.endDate));
if (StringUtils.isBlank(assignmentDTO.costCategoryName)) {
throw new ValidationException(
_("cost category name not specified"));
}
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;
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.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import org.apache.commons.lang.StringUtils;
import org.navalplanner.business.common.exceptions.CreateUnvalidatedException;
import org.navalplanner.business.common.daos.IIntegrationEntityDAO;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.navalplanner.business.resources.daos.IResourceDAO;
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.impl.ConstraintViolationConverter;
import org.navalplanner.ws.common.impl.Util;
import org.navalplanner.ws.common.impl.GenericRESTService;
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.ResourceListDTO;
import org.navalplanner.ws.resources.api.WorkerDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* REST-based implementation of <code>IResourceService</code>.
@ -58,7 +45,9 @@ import org.springframework.transaction.annotation.Transactional;
@Path("/resources/")
@Produces("application/xml")
@Service("resourceServiceREST")
public class ResourceServiceREST implements IResourceService {
public class ResourceServiceREST
extends GenericRESTService<Resource, ResourceDTO>
implements IResourceService {
@Autowired
private IResourceDAO resourceDAO;
@ -66,117 +55,32 @@ public class ResourceServiceREST implements IResourceService {
@Override
@POST
@Consumes("application/xml")
@Transactional
public InstanceConstraintViolationsListDTO addResources(
ResourceListDTO resources) {
List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList =
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);
return save(resources.resources);
}
private String getUserProvidedId(ResourceDTO resourceDTO) {
if (resourceDTO instanceof MachineDTO) {
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()));
}
@Override
protected Resource toEntity(ResourceDTO entityDTO) {
return ResourceConverter.toEntity(entityDTO);
}
private String getDuplicatedImportedResourceErrorMessage(
ResourceDTO resourceDTO) {
@Override
protected ResourceDTO toDTO(Resource entity) {
return null; // This service does not provide finder methods.
}
if (resourceDTO instanceof MachineDTO) {
return _("code is used by another machine being imported");
} else if (resourceDTO instanceof WorkerDTO) {
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 IIntegrationEntityDAO<Resource> getIntegrationEntityDAO() {
return resourceDAO;
}
@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;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.List;
@ -90,6 +91,8 @@ public class Util {
assertTrue(
instanceConstraintViolationsList.toString(),
instanceConstraintViolationsList.size() == 1);
assertNoRecoverableError(instanceConstraintViolationsList.get(0));
assertNoInternalError(instanceConstraintViolationsList.get(0));
assertNotNull(instanceConstraintViolationsList.get(0).
constraintViolations);
assertTrue(
@ -115,6 +118,8 @@ public class Util {
for (InstanceConstraintViolationsDTO i :
instanceConstraintViolationsList) {
assertNoRecoverableError(i);
assertNoInternalError(i);
assertNotNull(i.constraintViolations);
assertTrue(
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.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_SECURITY_CONFIG_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.assertOneConstraintViolation;
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 java.util.ArrayList;
@ -50,13 +50,11 @@ import org.navalplanner.business.common.IAdHocTransactionService;
import org.navalplanner.business.common.IOnTransaction;
import org.navalplanner.business.common.daos.IConfigurationDAO;
import org.navalplanner.business.common.entities.IConfigurationBootstrap;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.costcategories.daos.ICostCategoryDAO;
import org.navalplanner.business.costcategories.entities.CostCategory;
import org.navalplanner.business.resources.daos.ICriterionTypeDAO;
import org.navalplanner.business.resources.daos.IMachineDAO;
import org.navalplanner.business.resources.daos.IResourceDAO;
import org.navalplanner.business.resources.daos.IWorkerDAO;
import org.navalplanner.business.resources.entities.Criterion;
import org.navalplanner.business.resources.entities.CriterionSatisfaction;
import org.navalplanner.business.resources.entities.CriterionType;
@ -73,7 +71,6 @@ import org.navalplanner.ws.resources.api.ResourceListDTO;
import org.navalplanner.ws.resources.api.ResourcesCostCategoryAssignmentDTO;
import org.navalplanner.ws.resources.api.WorkerDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.NotTransactional;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
@ -84,9 +81,8 @@ import org.springframework.transaction.annotation.Transactional;
* @author Fernando Bellas Permuy <fbellas@udc.es>
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { BUSINESS_SPRING_CONFIG_FILE,
WEBAPP_SPRING_CONFIG_FILE, WEBAPP_SPRING_CONFIG_TEST_FILE,
WEBAPP_SPRING_SECURITY_CONFIG_FILE })
@ContextConfiguration(locations = {BUSINESS_SPRING_CONFIG_FILE,
WEBAPP_SPRING_CONFIG_FILE, WEBAPP_SPRING_CONFIG_TEST_FILE})
@Transactional
public class ResourceServiceTest {
@ -99,9 +95,6 @@ public class ResourceServiceTest {
@Autowired
private IMachineDAO machineDAO;
@Autowired
private IWorkerDAO workerDAO;
@Autowired
private ICriterionTypeDAO criterionTypeDAO;
@ -122,32 +115,40 @@ public class ResourceServiceTest {
@Before
public void loadConfiguration() {
configurationBootstrap.loadRequiredData();
IOnTransaction<Void> load =
new IOnTransaction<Void>() {
@Override
public Void execute() {
configurationBootstrap.loadRequiredData();
return null;
}
};
transactionService.runOnAnotherTransaction(load);
}
@Test
public void testAddResourcesWithBasicContraintViolations()
throws InstanceNotFoundException {
public void testAddResourcesWithBasicContraintViolations() {
/* Create resource DTOs. */
String m1Code = ' ' + getUniqueName() + ' '; // Blank spaces
// intentionally
// added (OK).
MachineDTO m1 = new MachineDTO(m1Code, "name", "desc");
MachineDTO m2 = new MachineDTO("", null, ""); // Missing code and name
MachineDTO m1 = new MachineDTO("name", "desc");
MachineDTO m2 = new MachineDTO(" ", null, ""); // Missing code and name
// (description is
// optional).
String w1Nif = ' ' + getUniqueName() + ' '; // Blank spaces
// intentionally
// added (OK).
WorkerDTO w1 = new WorkerDTO("w1-first-name", "w1-surname", w1Nif);
WorkerDTO w2 = new WorkerDTO("", null, ""); // Missing first name,
// surname, and nif.
WorkerDTO w1 = new WorkerDTO(getUniqueName(), "w1-surname", "w1-nif");
WorkerDTO w2 = new WorkerDTO(null, "", null, ""); // Missing code, first
// name, surname, and
// nif.
/* Test. */
List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList =
resourceService.addResources(createResourceListDTO(m1, m2, w1, w2)).
instanceConstraintViolationsList;
resourceService.addResources(
createResourceListDTO(m1, m2, w1, w2)).
instanceConstraintViolationsList;
assertTrue(
instanceConstraintViolationsList.toString(),
@ -161,35 +162,13 @@ public class ResourceServiceTest {
instanceConstraintViolationsList.get(1).
constraintViolations.toString(),
instanceConstraintViolationsList.get(1).
constraintViolations.size() == 3); // w2 constraint violations.
machineDAO.findUniqueByCode(m1Code.trim());
assertTrue(
workerDAO.findByFirstNameSecondNameAndNif(
w1.firstName, w1.surname, w1.nif.trim()).size() == 1);
constraintViolations.size() == 4); // w2 constraint violations.
assertTrue(resourceDAO.existsByCode(m1.code));
assertTrue(resourceDAO.existsByCode(w1.code));
}
@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() {
/* Create a worker. */
@ -207,29 +186,55 @@ public class ResourceServiceTest {
/* Test. */
assertOneConstraintViolation(
resourceService.addResources(createResourceListDTO(w2)));
assertTrue(
workerDAO.findByFirstNameSecondNameAndNifAnotherTransaction(
w2.firstName, w2.surname, w2.nif).size() == 1);
assertFalse(resourceDAO.existsByCode(w2.code));
}
@Test
public void testAddResourcesWithDuplicateResourcesBeingImported()
throws InstanceNotFoundException {
public void testAddResourceWithCriterionSatisfactions() {
/* Create resource DTOs. */
MachineDTO m1 = new MachineDTO(getUniqueName(), "m1-name", "m1-desc");
MachineDTO m2 = new MachineDTO(' ' + m1.code.toUpperCase() + ' ',
"m2-name", "m2-desc");
WorkerDTO w1 = new WorkerDTO(getUniqueName(), "w1-surname", "w1-nif");
WorkerDTO w2 = new WorkerDTO(w1.firstName,
' ' + w1.surname.toUpperCase() + ' ', w1.nif);
/* Create a criterion type. */
CriterionType ct = createCriterionType();
/* Create a resource DTO. */
MachineDTO m1 = new MachineDTO("name", "desc");
CriterionSatisfactionDTO cs1m1 =
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. */
List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList =
resourceService.addResources(createResourceListDTO(m1, m2, w1, w2)).
instanceConstraintViolationsList;
resourceService.addResources(createResourceListDTO(m1, m2, m3)).
instanceConstraintViolationsList;
assertTrue(
instanceConstraintViolationsList.toString(),
@ -238,49 +243,16 @@ public class ResourceServiceTest {
instanceConstraintViolationsList.get(0).
constraintViolations.toString(),
instanceConstraintViolationsList.get(0).
constraintViolations.size() == 1);
constraintViolations.size() == 2); // m2 constraint violations.
assertTrue(
instanceConstraintViolationsList.get(1).
constraintViolations.toString(),
instanceConstraintViolationsList.get(1).
constraintViolations.size() == 1);
machineDAO.findUniqueByCode(m1.code);
assertTrue(
workerDAO.findByFirstNameSecondNameAndNif(
w1.firstName, w1.surname, w1.nif.trim()).size() == 1);
constraintViolations.size() == 1); // m3 constraint violations.
assertFalse(resourceDAO.existsByCode(m2.code));
assertFalse(resourceDAO.existsByCode(m3.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);
Machine machine = machineDAO.findExistingEntityByCode(m1.code);
assertTrue(machine.getCriterionSatisfactions().size() == 2);
for (CriterionSatisfaction cs : machine.getCriterionSatisfactions()) {
@ -290,17 +262,18 @@ public class ResourceServiceTest {
}
}
assertFalse(resourceDAO.existsByCode(m2.code));
}
@Test
@NotTransactional
public void testAddResourceWithCriterionSatisfactionWithoutStartDate() {
/* Create a criterion type. */
CriterionType ct = createCriterionType();
/* Create a machine DTO. */
MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc");
MachineDTO machineDTO = new MachineDTO("name", "desc");
machineDTO.criterionSatisfactions.add(
new CriterionSatisfactionDTO(ct.getName() , "c1",
null, getDate(2001, 1, 1))); // Missing start date.
@ -308,20 +281,18 @@ public class ResourceServiceTest {
/* Test. */
assertOneConstraintViolation(
resourceService.addResources(createResourceListDTO(machineDTO)));
assertFalse(machineDAO.existsMachineWithCodeInAnotherTransaction(
machineDTO.code));
assertFalse(resourceDAO.existsByCode(machineDTO.code));
}
@Test
@NotTransactional
public void testAddResourceWithCriterionSatisfactionWithNegativeInterval() {
/* Create a criterion type. */
CriterionType ct = createCriterionType();
/* Create a machine DTO. */
MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc");
MachineDTO machineDTO = new MachineDTO("name", "desc");
machineDTO.criterionSatisfactions.add(
new CriterionSatisfactionDTO(ct.getName() , "c1",
getDate(2000, 2, 1), getDate(2000, 1, 1)));
@ -329,13 +300,11 @@ public class ResourceServiceTest {
/* Test. */
assertOneConstraintViolation(
resourceService.addResources(createResourceListDTO(machineDTO)));
assertFalse(machineDAO.existsMachineWithCodeInAnotherTransaction(
machineDTO.code));
assertFalse(resourceDAO.existsByCode(machineDTO.code));
}
@Test
@NotTransactional
public void testAddResourceWithOverlappingCriterionSatisfactionsAllowed() {
/* Create a criterion type. */
@ -353,13 +322,11 @@ public class ResourceServiceTest {
/* Test. */
assertNoConstraintViolations(
resourceService.addResources(createResourceListDTO(machineDTO)));
assertTrue(machineDAO.existsMachineWithCodeInAnotherTransaction(
machineDTO.code));
assertTrue(resourceDAO.existsByCode(machineDTO.code));
}
@Test
@NotTransactional
public void testAddResourceWithOverlappingCriterionSatisfactions() {
/* Create criterion types. */
@ -395,22 +362,20 @@ public class ResourceServiceTest {
MachineDTO m = (MachineDTO) r;
assertFalse(
"Machine " + m.name + " not expected",
machineDAO.existsMachineWithCodeInAnotherTransaction(
((MachineDTO) r).code));
resourceDAO.existsByCode(((MachineDTO) r).code));
}
}
@Test
@NotTransactional
public void testAddResourcesWithCriterionSatisfactionsWithIncorrectType() {
public void testAddResourcesWithCriterionSatisfactionsWithIncorrectCriterionType() {
/* Create two criterion types. */
CriterionType machineCt = createCriterionType(ResourceEnum.MACHINE);
CriterionType workerCt = createCriterionType(ResourceEnum.WORKER);
/* Create resource DTOs. */
MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc");
MachineDTO machineDTO = new MachineDTO("name", "desc");
machineDTO.criterionSatisfactions.add(
new CriterionSatisfactionDTO(workerCt.getName() , "c1",
getDate(2001, 1, 1), null)); // Incorrect type.
@ -422,158 +387,29 @@ public class ResourceServiceTest {
/* Test. */
assertOneConstraintViolation(
resourceService.addResources(createResourceListDTO(machineDTO)));
assertFalse(machineDAO.existsMachineWithCodeInAnotherTransaction(
machineDTO.code));
assertFalse(
resourceDAO.existsByCode(machineDTO.code));
assertOneConstraintViolation(
resourceService.addResources(createResourceListDTO(workerDTO)));
assertTrue(workerDAO.findByFirstNameSecondNameAndNifAnotherTransaction(
workerDTO.firstName, workerDTO.surname, workerDTO.nif).size() == 0);
assertFalse(resourceDAO.existsByCode(workerDTO.code));
}
@Test
@NotTransactional
public void testAddResourcesWithCriterionSatisfactionsWithIncorrectNames() {
public void testAddResourcesWithCriterionSatisfactionsWithMissingNames() {
/* Create a criterion type. */
CriterionType ct = createCriterionType();
/* Create machines DTOs. */
MachineDTO m1 = new MachineDTO(getUniqueName(), "m1", "desc");
MachineDTO m1 = new MachineDTO("m1", "desc");
m1.criterionSatisfactions.add(
new CriterionSatisfactionDTO("", "X", // Missing criterion type.
getDate(2001, 1, 1), null));
MachineDTO m2 = new MachineDTO(getUniqueName(), "m2", "desc");
MachineDTO m2 = new MachineDTO("m2", "desc");
m2.criterionSatisfactions.add(
new CriterionSatisfactionDTO(ct.getName(), // Missing criterion.
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. */
ResourceListDTO resourceDTOs = createResourceListDTO(m1, m2);
@ -586,20 +422,200 @@ public class ResourceServiceTest {
MachineDTO m = (MachineDTO) r;
assertFalse(
"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
@NotTransactional
public void testAddResourceWithCostAssignmentWithoutStartDate() {
/* Create a CostCategory. */
CostCategory costCategory = createCostCategory();
/* Create a resource DTO. */
MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc");
MachineDTO machineDTO = new MachineDTO("name", "desc");
machineDTO.resourcesCostCategoryAssignments.add(
new ResourcesCostCategoryAssignmentDTO(
costCategory.getName(), null, // Start date not specified.
@ -608,20 +624,18 @@ public class ResourceServiceTest {
/* Test. */
assertOneConstraintViolation(
resourceService.addResources(createResourceListDTO(machineDTO)));
assertFalse(machineDAO.existsMachineWithCodeInAnotherTransaction(
machineDTO.code));
assertFalse(resourceDAO.existsByCode(machineDTO.code));
}
@Test
@NotTransactional
public void testAddResourceWithCostAssignmentWithNegativeInterval() {
/* Create a CostCategory. */
CostCategory costCategory = createCostCategory();
/* Create a resource DTO. */
MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc");
MachineDTO machineDTO = new MachineDTO("name", "desc");
machineDTO.resourcesCostCategoryAssignments.add(
new ResourcesCostCategoryAssignmentDTO(
costCategory.getName(),
@ -630,13 +644,11 @@ public class ResourceServiceTest {
/* Test. */
assertOneConstraintViolation(
resourceService.addResources(createResourceListDTO(machineDTO)));
assertFalse(machineDAO.existsMachineWithCodeInAnotherTransaction(
machineDTO.code));
assertFalse(resourceDAO.existsByCode(machineDTO.code));
}
@Test
@NotTransactional
public void testAddResourcesWithOverlappingInCostAssignments() {
/* Create a CostCategory. */
@ -703,8 +715,7 @@ public class ResourceServiceTest {
MachineDTO m = (MachineDTO) r;
assertFalse(
"Machine " + m.name + " not expected",
machineDAO.existsMachineWithCodeInAnotherTransaction(
((MachineDTO) r).code));
resourceDAO.existsByCode(((MachineDTO) r).code));
}
}
@ -742,45 +753,7 @@ public class ResourceServiceTest {
}
};
return transactionService.runOnTransaction(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;
return transactionService.runOnAnotherTransaction(createCriterionType);
}
@ -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,
XMLGregorianCalendar endDate2) {
MachineDTO machineDTO = new MachineDTO(getUniqueName(), machineName,
"desc");
MachineDTO machineDTO = new MachineDTO(machineName, "desc");
machineDTO.criterionSatisfactions.add(
new CriterionSatisfactionDTO(criterionTypeName, criterionName1,
@ -889,8 +861,7 @@ public class ResourceServiceTest {
XMLGregorianCalendar startDate1, XMLGregorianCalendar endDate1,
XMLGregorianCalendar startDate2, XMLGregorianCalendar endDate2) {
MachineDTO machineDTO = new MachineDTO(getUniqueName(), machineName,
"desc");
MachineDTO machineDTO = new MachineDTO(machineName, "desc");
machineDTO.resourcesCostCategoryAssignments.add(
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.ICriterionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.NotTransactional;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
@ -59,7 +58,7 @@ import org.springframework.transaction.annotation.Transactional;
*/
@RunWith(SpringJUnit4ClassRunner.class)
@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
public class CriterionServiceTest {
@ -70,7 +69,6 @@ public class CriterionServiceTest {
private ICriterionTypeDAO criterionTypeDAO;
@Test
@NotTransactional
public void testAddAndGetCriterionTypes() {
/* Build criterion type "ct1" (5 constraint violations). */
@ -100,8 +98,7 @@ public class CriterionServiceTest {
ct1Criterions.add(ct1c3);
ct1Criterions.add(ct1c4);
ct1Criterions.add(ct1c5);
String ct1Name = null;
CriterionTypeDTO ct1 = new CriterionTypeDTO(ct1Name, "desc",
CriterionTypeDTO ct1 = new CriterionTypeDTO(null, "desc",
false, true, true, ResourceEnumDTO.RESOURCE, // Missing criterion
ct1Criterions); // type name.
@ -118,8 +115,7 @@ public class CriterionServiceTest {
List<CriterionDTO> ct2Criterions = new ArrayList<CriterionDTO>();
ct2Criterions.add(ct2c1);
ct2Criterions.add(ct2c2);
String ct2Name = getUniqueName();
CriterionTypeDTO ct2 = new CriterionTypeDTO(ct2Name, "desc",
CriterionTypeDTO ct2 = new CriterionTypeDTO(getUniqueName(), "desc",
true, true, false, ResourceEnumDTO.RESOURCE, ct2Criterions);
/* Build criterion type "ct3" (OK). */
@ -134,14 +130,13 @@ public class CriterionServiceTest {
List<CriterionDTO> ct3Criterions = new ArrayList<CriterionDTO>();
ct3Criterions.add(ct3c1);
ct3Criterions.add(ct3c2);
String ct3Name = getUniqueName();
CriterionTypeDTO ct3 = new CriterionTypeDTO(ct3Name, "desc",
CriterionTypeDTO ct3 = new CriterionTypeDTO(getUniqueName(), "desc",
true, true, true, ResourceEnumDTO.RESOURCE, ct3Criterions);
/* Build criterion type "ct4" (1 constraint violation). */
CriterionTypeDTO ct4 =
new CriterionTypeDTO( // Repeated criterion
' ' + ct3Name.toUpperCase() + ' ', // type name.
' ' + ct3.name.toUpperCase() + ' ', // type name.
"desc", true, true, true,
ResourceEnumDTO.RESOURCE, new ArrayList<CriterionDTO>());
@ -154,9 +149,19 @@ public class CriterionServiceTest {
CriterionTypeDTO ct5 = new CriterionTypeDTO(getUniqueName(), "desc",
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. */
CriterionTypeListDTO criterionTypes =
createCriterionTypeListDTO(ct1, ct2, ct3, ct4, ct5);
createCriterionTypeListDTO(ct1, ct2, ct3, ct4, ct5, ct6);
List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList =
criterionService.addCriterionTypes(criterionTypes).
@ -164,40 +169,47 @@ public class CriterionServiceTest {
assertTrue(
instanceConstraintViolationsList.toString(),
instanceConstraintViolationsList.size() == 4);
instanceConstraintViolationsList.size() == 5);
assertTrue(
instanceConstraintViolationsList.get(0).
constraintViolations.toString(),
instanceConstraintViolationsList.get(0).
constraintViolations.size() == 5);
constraintViolations.size() == 5); // ct1 constraint violations.
assertTrue(
instanceConstraintViolationsList.get(1).
constraintViolations.toString(),
instanceConstraintViolationsList.get(1).
constraintViolations.size() == 2);
constraintViolations.size() == 2); // ct2 constraint violations.
assertTrue(
instanceConstraintViolationsList.get(2).
constraintViolations.toString(),
instanceConstraintViolationsList.get(2).
constraintViolations.size() == 1);
constraintViolations.size() == 1); // ct4 constraint violations.
assertTrue(
instanceConstraintViolationsList.get(3).
constraintViolations.toString(),
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. */
List<CriterionTypeDTO> returnedCriterionTypes =
criterionService.getCriterionTypes().criterionTypes;
assertFalse(containsCriterionType(returnedCriterionTypes, ct1Name));
assertFalse(containsCriterionType(returnedCriterionTypes, ct2Name));
assertTrue(containsCriterionType(returnedCriterionTypes, ct3Name));
/* Test. */
assertFalse(criterionTypeDAO.existsByCode(ct2.code));
assertTrue(criterionTypeDAO.existsByCode(ct3.code));
assertFalse(criterionTypeDAO.existsByCode(ct4.code));
assertTrue(containsCriterionType(returnedCriterionTypes, ct3.code));
}
@Test
@Transactional
public void testUpdateCriterionType() throws InstanceNotFoundException {
/* Build criterion type with criteria: c1, c2->c2-1. */
@ -286,10 +298,10 @@ public class CriterionServiceTest {
}
private boolean containsCriterionType(
List<CriterionTypeDTO> criterionTypes, String criterionTypeName) {
List<CriterionTypeDTO> criterionTypes, String code) {
for (CriterionTypeDTO c : criterionTypes) {
if (c.name.equals(criterionTypeName)) {
if (c.code.equals(code)) {
return true;
}
}

View file

@ -24,35 +24,51 @@
</criterion-satisfaction-list>
</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. -->
<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
code="m5-a1"
code="m3-a1"
cost-category-name="TestCostCategory"
start-date="2001-01-01"/>
<resources-cost-category-assignment
code="m5-a2"
code="m3-a2"
cost-category-name="TestCostCategory"
start-date="2000-01-01"
end-date="2000-04-01"/>
</resources-cost-category-assignment-list>
</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">
<resources-cost-category-assignment-list>
<resources-cost-category-assignment
code="m6-a1"
cost-category-name="TestCostCategory"
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>
</machine>
@ -106,7 +122,8 @@
</criterion-satisfaction-list>
</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">
<criterion-satisfaction-list>
<criterion-satisfaction
@ -114,6 +131,15 @@
criterion-type-name="LEAVE"
criterion-name="paternityLeave"
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>
</worker>
@ -290,8 +316,22 @@
</criterion-satisfaction-list>
</worker>
<!-- Another worker is being imported with the same first name, surname,
and nif. -->
<!-- There is another worker with the same first name, surname, and 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>