From 22c883820a084486866e5869dbb1d9e35af586f7 Mon Sep 17 00:00:00 2001 From: Fernando Bellas Permuy Date: Tue, 9 Feb 2010 16:20:30 +0100 Subject: [PATCH] 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. --- .../common/daos/IntegrationEntityDAO.java | 2 +- .../ResourcesCostCategoryAssignment.java | 24 +- .../business/resources/daos/IMachineDAO.java | 5 +- .../business/resources/daos/IWorkerDAO.java | 4 +- .../business/resources/daos/MachineDAO.java | 16 +- .../business/resources/daos/WorkerDAO.java | 5 +- .../entities/CriterionSatisfaction.java | 41 +- .../api/InstanceConstraintViolationsDTO.java | 33 +- .../ws/common/api/InternalErrorDTO.java | 27 +- .../ws/common/api/PropertyDTO.java | 61 ++ .../ws/common/api/RecoverableErrorDTO.java | 80 +++ .../impl/ConstraintViolationConverter.java | 26 + .../ws/common/impl/GenericRESTService.java | 49 +- ...anceNotFoundRecoverableErrorException.java | 56 ++ .../common/impl/RecoverableErrorCodeEnum.java | 14 +- .../impl/RecoverableErrorException.java | 56 ++ .../criterion/impl/CriterionConverter.java | 2 +- .../ws/resources/impl/ResourceConverter.java | 93 ++- .../resources/impl/ResourceServiceREST.java | 138 +--- .../navalplanner/web/test/ws/common/Util.java | 45 ++ .../ws/resources/api/ResourceServiceTest.java | 603 +++++++++--------- .../criterion/api/CriterionServiceTest.java | 56 +- scripts/rest-clients/resources-sample.xml | 68 +- 23 files changed, 912 insertions(+), 592 deletions(-) create mode 100644 navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/PropertyDTO.java create mode 100644 navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/RecoverableErrorDTO.java create mode 100644 navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/InstanceNotFoundRecoverableErrorException.java rename navalplanner-business/src/main/java/org/navalplanner/business/common/exceptions/CreateUnvalidatedException.java => navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/RecoverableErrorCodeEnum.java (72%) create mode 100644 navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/RecoverableErrorException.java diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/common/daos/IntegrationEntityDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/common/daos/IntegrationEntityDAO.java index 8317def3c..ffbe0f218 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/common/daos/IntegrationEntityDAO.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/common/daos/IntegrationEntityDAO.java @@ -67,7 +67,7 @@ public class IntegrationEntityDAO } 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( diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/entities/ResourcesCostCategoryAssignment.java b/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/entities/ResourcesCostCategoryAssignment.java index 334ef67c2..d4915c320 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/entities/ResourcesCostCategoryAssignment.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/entities/ResourcesCostCategoryAssignment.java @@ -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 = diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/IMachineDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/IMachineDAO.java index 44469f06e..ff7d93125 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/IMachineDAO.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/IMachineDAO.java @@ -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 * @author Javier Moran Rua + * @author Fernando Bellas Permuy */ -public interface IMachineDAO extends IGenericDAO { +public interface IMachineDAO extends IIntegrationEntityDAO { /** * Returns machines which name/NIF partially matches with name diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/IWorkerDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/IWorkerDAO.java index 119b8e01d..7e2c3aeab 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/IWorkerDAO.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/IWorkerDAO.java @@ -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 * */ -public interface IWorkerDAO extends IGenericDAO { +public interface IWorkerDAO extends IIntegrationEntityDAO { /** * Returns workers which name/NIF partially matches with name diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/MachineDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/MachineDAO.java index 5d1c9ff45..e8a48394d 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/MachineDAO.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/MachineDAO.java @@ -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 Machine entity. * * @author Diego Pino Garcia * @author Javier Moran Rua + * @author Fernando Bellas Permuy */ @Repository @Scope(BeanDefinition.SCOPE_SINGLETON) -public class MachineDAO extends GenericDAOHibernate +public class MachineDAO extends IntegrationEntityDAO implements IMachineDAO { @Override @@ -61,14 +62,9 @@ public class MachineDAO extends GenericDAOHibernate @Override public Machine findUniqueByCode(String code) throws InstanceNotFoundException { - Criteria criteria = getSession().createCriteria(Machine.class); - criteria.add(Restrictions.eq("code", code).ignoreCase()); - List list = criteria.list(); - if (list.size() != 1) { - throw new InstanceNotFoundException(code, Machine.class.getName()); - } - return list.get(0); + return findExistingEntityByCode(code); + } @Override diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/WorkerDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/WorkerDAO.java index 7a2184d91..fe536f197 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/WorkerDAO.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/WorkerDAO.java @@ -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 Worker entity. * @@ -46,7 +47,7 @@ import org.springframework.transaction.annotation.Transactional; */ @Repository @Scope(BeanDefinition.SCOPE_SINGLETON) -public class WorkerDAO extends GenericDAOHibernate +public class WorkerDAO extends IntegrationEntityDAO implements IWorkerDAO { @Override diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionSatisfaction.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionSatisfaction.java index 6381764e4..eb61f0efb 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionSatisfaction.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionSatisfaction.java @@ -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 = diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/InstanceConstraintViolationsDTO.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/InstanceConstraintViolationsDTO.java index 92bdb771f..713c402f6 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/InstanceConstraintViolationsDTO.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/InstanceConstraintViolationsDTO.java @@ -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 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(); diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/InternalErrorDTO.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/InternalErrorDTO.java index c3e059602..ceedd5e72 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/InternalErrorDTO.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/InternalErrorDTO.java @@ -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 */ @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(); + + } + } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/PropertyDTO.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/PropertyDTO.java new file mode 100644 index 000000000..5abdbc0fd --- /dev/null +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/PropertyDTO.java @@ -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 . + */ + +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 + */ +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(); + + } + +} diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/RecoverableErrorDTO.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/RecoverableErrorDTO.java new file mode 100644 index 000000000..cd9ff6e7f --- /dev/null +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/RecoverableErrorDTO.java @@ -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 . + */ + +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 + */ +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 properties; + + public RecoverableErrorDTO() {} + + public RecoverableErrorDTO(int errorCode, String message, + List 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(); + + } + +} diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/ConstraintViolationConverter.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/ConstraintViolationConverter.java index 853d91bd8..a09d3fce0 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/ConstraintViolationConverter.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/ConstraintViolationConverter.java @@ -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 properties = new ArrayList(); + + for (Map.Entry 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) { diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/GenericRESTService.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/GenericRESTService.java index 55e5c0c3c..1837c772b 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/GenericRESTService.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/GenericRESTService.java @@ -57,7 +57,8 @@ public abstract class GenericRESTService entityDTOs) { + protected InstanceConstraintViolationsListDTO save( + List entityDTOs) { List instanceConstraintViolationsList = new ArrayList(); @@ -75,6 +76,11 @@ public abstract class GenericRESTService save = new IOnTransaction() { @@ -122,13 +134,22 @@ public abstract class GenericRESTService. + */ + +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 + */ +@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 properties = new HashMap(); + properties.put("type", type); + properties.put("value", value); + + setProperties(properties); + + } + +} diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/common/exceptions/CreateUnvalidatedException.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/RecoverableErrorCodeEnum.java similarity index 72% rename from navalplanner-business/src/main/java/org/navalplanner/business/common/exceptions/CreateUnvalidatedException.java rename to navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/RecoverableErrorCodeEnum.java index b60180b45..96bc94c08 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/common/exceptions/CreateUnvalidatedException.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/RecoverableErrorCodeEnum.java @@ -18,19 +18,13 @@ * along with this program. If not, see . */ -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 */ -@SuppressWarnings("serial") -public class CreateUnvalidatedException extends Exception { - - public CreateUnvalidatedException(String message) { - super(message); - } - +public enum RecoverableErrorCodeEnum { + INSTANCE_NOT_FOUND } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/RecoverableErrorException.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/RecoverableErrorException.java new file mode 100644 index 000000000..ad968f3bf --- /dev/null +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/RecoverableErrorException.java @@ -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 . + */ + +package org.navalplanner.ws.common.impl; + +import java.util.Map; + +/** + * An exception to modeling a recoverable error. + * + * @author Fernando Bellas Permuy + */ +@SuppressWarnings("serial") +public abstract class RecoverableErrorException extends RuntimeException { + + private RecoverableErrorCodeEnum errorCode; + private Map properties; + + protected RecoverableErrorException(String message, + RecoverableErrorCodeEnum errorCode) { + + super(message); + this.errorCode = errorCode; + + } + + public RecoverableErrorCodeEnum getErrorCode() { + return errorCode; + } + + public Map getProperties() { + return properties; + } + + protected void setProperties(Map properties) { + this.properties = properties; + } + +} diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/criterion/impl/CriterionConverter.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/criterion/impl/CriterionConverter.java index 443e7dab2..a1857670b 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/criterion/impl/CriterionConverter.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/criterion/impl/CriterionConverter.java @@ -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 criterionWrappers = diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/impl/ResourceConverter.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/impl/ResourceConverter.java index a255570ea..12ce3a7bb 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/impl/ResourceConverter.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/impl/ResourceConverter.java @@ -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 criterionSatisfactions) - throws CreateUnvalidatedException { + List 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 - 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. + } } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/impl/ResourceServiceREST.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/impl/ResourceServiceREST.java index c7609cfa7..2382ae3be 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/impl/ResourceServiceREST.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/impl/ResourceServiceREST.java @@ -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 IResourceService. @@ -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 + 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 instanceConstraintViolationsList = - new ArrayList(); - int instanceNumber = 1; - Set resourceUserProvidedIds = new HashSet(); - - /* 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 getIntegrationEntityDAO() { + return resourceDAO; + } + @Override + protected void updateEntity(Resource entity, ResourceDTO entityDTO) + throws ValidationException { + // FIXME: updated functionality not implemented yet. } } diff --git a/navalplanner-webapp/src/test/java/org/navalplanner/web/test/ws/common/Util.java b/navalplanner-webapp/src/test/java/org/navalplanner/web/test/ws/common/Util.java index 2922c349f..9d016d192 100644 --- a/navalplanner-webapp/src/test/java/org/navalplanner/web/test/ws/common/Util.java +++ b/navalplanner-webapp/src/test/java/org/navalplanner/web/test/ws/common/Util.java @@ -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 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); + + } + } diff --git a/navalplanner-webapp/src/test/java/org/navalplanner/web/test/ws/resources/api/ResourceServiceTest.java b/navalplanner-webapp/src/test/java/org/navalplanner/web/test/ws/resources/api/ResourceServiceTest.java index 709796b85..59bad2ac4 100644 --- a/navalplanner-webapp/src/test/java/org/navalplanner/web/test/ws/resources/api/ResourceServiceTest.java +++ b/navalplanner-webapp/src/test/java/org/navalplanner/web/test/ws/resources/api/ResourceServiceTest.java @@ -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 */ @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 load = + new IOnTransaction() { + + @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 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 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 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 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 find = new IOnTransaction() { - - @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( diff --git a/navalplanner-webapp/src/test/java/org/navalplanner/web/test/ws/resources/criterion/api/CriterionServiceTest.java b/navalplanner-webapp/src/test/java/org/navalplanner/web/test/ws/resources/criterion/api/CriterionServiceTest.java index 4f6041350..34056c363 100644 --- a/navalplanner-webapp/src/test/java/org/navalplanner/web/test/ws/resources/criterion/api/CriterionServiceTest.java +++ b/navalplanner-webapp/src/test/java/org/navalplanner/web/test/ws/resources/criterion/api/CriterionServiceTest.java @@ -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 ct2Criterions = new ArrayList(); 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 ct3Criterions = new ArrayList(); 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()); @@ -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()); + List ct6Criterions = new ArrayList(); + 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 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 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 criterionTypes, String criterionTypeName) { + List criterionTypes, String code) { for (CriterionTypeDTO c : criterionTypes) { - if (c.name.equals(criterionTypeName)) { + if (c.code.equals(code)) { return true; } } diff --git a/scripts/rest-clients/resources-sample.xml b/scripts/rest-clients/resources-sample.xml index ef71f7cd7..fc7a00274 100644 --- a/scripts/rest-clients/resources-sample.xml +++ b/scripts/rest-clients/resources-sample.xml @@ -24,35 +24,51 @@ - - - - - - - + - + + + + + + + + + + + + + @@ -106,7 +122,8 @@ - + + + @@ -290,8 +316,22 @@ - + + + + + + + + + + +