From ed5c0976d2f0d8ea2ed19d2ef16300e63795020f Mon Sep 17 00:00:00 2001 From: Fernando Bellas Permuy Date: Wed, 23 Dec 2009 09:22:51 +0100 Subject: [PATCH] ItEr40S20CUImportacionRecursosProductivosItEr39S23: Added support for importing resources containing criterion satisfactions. Added support for importing resources containing criterion satisfactions. Complex validations are not implemented yet. --- .../business/common/StringUtils.java | 39 ++++ .../CreateUnvalidatedException.java | 36 ++++ .../entities/CriterionSatisfaction.java | 64 ++++++- .../resources/entities/CriterionType.java | 14 ++ .../business/resources/entities/Machine.java | 15 +- .../business/resources/entities/Resource.java | 7 + .../business/resources/entities/Worker.java | 20 +- .../ws/common/api/ConstraintViolationDTO.java | 6 +- .../api/InstanceConstraintViolationsDTO.java | 16 +- .../ws/common/impl/DateConverter.java | 91 +++++++++ .../api/CriterionSatisfactionDTO.java | 64 +++++++ .../ws/resources/api/IResourceService.java | 8 +- .../ws/resources/api/ResourceDTO.java | 11 ++ .../ws/resources/api/ResourceListDTO.java | 4 +- .../ws/resources/impl/ResourceConverter.java | 59 +++++- .../resources/impl/ResourceServiceREST.java | 44 +++-- .../ws/resources/api/ResourceServiceTest.java | 174 ++++++++++++++++++ scripts/rest-clients/resources-sample.xml | 15 +- 18 files changed, 651 insertions(+), 36 deletions(-) create mode 100644 navalplanner-business/src/main/java/org/navalplanner/business/common/StringUtils.java create mode 100644 navalplanner-business/src/main/java/org/navalplanner/business/common/exceptions/CreateUnvalidatedException.java create mode 100644 navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/DateConverter.java create mode 100644 navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/api/CriterionSatisfactionDTO.java diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/common/StringUtils.java b/navalplanner-business/src/main/java/org/navalplanner/business/common/StringUtils.java new file mode 100644 index 000000000..9d6c2c56e --- /dev/null +++ b/navalplanner-business/src/main/java/org/navalplanner/business/common/StringUtils.java @@ -0,0 +1,39 @@ +/* + * This file is part of ###PROJECT_NAME### + * + * 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.business.common; + +/** + * String utility methods. + * + * @author Fernando Bellas Permuy + */ +public class StringUtils { + + private StringUtils() {} + + /** + * Check if a String is null or "" after being trimmed. + */ + public static boolean isEmpty(String s) { + return s == null ? true : s.trim().equals(""); + } + +} diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/common/exceptions/CreateUnvalidatedException.java b/navalplanner-business/src/main/java/org/navalplanner/business/common/exceptions/CreateUnvalidatedException.java new file mode 100644 index 000000000..7f01ff8b4 --- /dev/null +++ b/navalplanner-business/src/main/java/org/navalplanner/business/common/exceptions/CreateUnvalidatedException.java @@ -0,0 +1,36 @@ +/* + * This file is part of ###PROJECT_NAME### + * + * 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.business.common.exceptions; + +/** + * An exception representing that a "createUnvalidated" method in an entity + * class could not create an instance. + * + * @author Fernando Bellas Permuy + */ +@SuppressWarnings("serial") +public class CreateUnvalidatedException extends Exception { + + public CreateUnvalidatedException(String message) { + super(message); + } + +} 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 b3a50634f..7c6ffec45 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,6 +20,8 @@ package org.navalplanner.business.resources.entities; +import static org.navalplanner.business.i18n.I18nHelper._; + import java.util.Comparator; import java.util.Date; @@ -27,9 +29,15 @@ import org.apache.commons.lang.Validate; import org.apache.commons.lang.builder.ToStringBuilder; import org.hibernate.validator.NotNull; import org.navalplanner.business.common.BaseEntity; +import org.navalplanner.business.common.Registry; +import org.navalplanner.business.common.StringUtils; +import org.navalplanner.business.common.exceptions.CreateUnvalidatedException; +import org.navalplanner.business.common.exceptions.InstanceNotFoundException; +import org.navalplanner.business.resources.daos.ICriterionTypeDAO; /** * Declares a interval of time in which the criterion is satisfied
* @author Óscar González Fernández + * @author Fernando Bellas Permuy */ public class CriterionSatisfaction extends BaseEntity { @@ -67,6 +75,58 @@ public class CriterionSatisfaction extends BaseEntity { return criterionSatisfaction; } + public static CriterionSatisfaction createUnvalidated( + String criterionTypeName, String criterionName, + Resource resource, Date startDate, Date finishDate) + throws CreateUnvalidatedException { + + ICriterionTypeDAO criterionTypeDAO = + Registry.getCriterionTypeDAO(); + + /* Get CriterionType. */ + if (StringUtils.isEmpty(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)); + } + + /* Get Criterion. */ + if (StringUtils.isEmpty(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)); + } + + /* Create instance of CriterionSatisfaction. */ + CriterionSatisfaction criterionSatisfaction = + new CriterionSatisfaction(); + criterionSatisfaction.setNewObject(true); + criterionSatisfaction.criterion = criterion; + criterionSatisfaction.resource = resource; + criterionSatisfaction.startDate = startDate; + criterionSatisfaction.finishDate = finishDate; + + return criterionSatisfaction; + + } + /** * Constructor for hibernate. Do not use! */ @@ -92,7 +152,6 @@ public class CriterionSatisfaction extends BaseEntity { } } - @NotNull private Date startDate; private Date finishDate; @@ -117,6 +176,7 @@ public class CriterionSatisfaction extends BaseEntity { return result; } + @NotNull(message="criterion satisfaction's start date not specified") public Date getStartDate() { return startDate != null ? new Date(startDate.getTime()) : null; } @@ -133,6 +193,7 @@ public class CriterionSatisfaction extends BaseEntity { return Interval.range(startDate, finishDate); } + @NotNull(message="criterion satisfaction's criterion not specified") public Criterion getCriterion() { return criterion; } @@ -141,6 +202,7 @@ public class CriterionSatisfaction extends BaseEntity { this.criterion = criterion; } + @NotNull(message="criterion satisfaction's resource not specified") public Resource getResource() { return resource; } diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionType.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionType.java index b61e070d5..7a6003a83 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionType.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionType.java @@ -284,6 +284,20 @@ public class CriterionType extends BaseEntity implements return criterions.size(); } + public Criterion getCriterion(String criterionName) + throws InstanceNotFoundException { + + for (Criterion c : criterions) { + if (c.getName().trim().equalsIgnoreCase(criterionName)) { + return c; + } + } + + throw new InstanceNotFoundException(name + "::" + criterionName, + Criterion.class.getName()); + + } + @AssertTrue(message="criterion names must be unique inside a criterion " + "type") public boolean checkConstraintNonRepeatedCriterionNames() { diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Machine.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Machine.java index 3689e9c7e..d0654df5f 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Machine.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Machine.java @@ -43,10 +43,17 @@ public class Machine extends Resource { configurationUnits.remove(unit); } - public static Machine create(String code, String name, String description) { - Machine machine = new Machine(code, name, description); + public static Machine createUnvalidated(String code, String name, String description) { + + Machine machine = new Machine(); + + machine.code = code; + machine.name = name; + machine.description = description; machine.setNewObject(true); + return machine; + } protected Machine() { @@ -63,7 +70,7 @@ public class Machine extends Resource { return create(new Machine()); } - @NotEmpty + @NotEmpty(message="machine code not specified") public String getCode() { return code; } @@ -72,7 +79,7 @@ public class Machine extends Resource { this.code = code; } - @NotEmpty + @NotEmpty(message="machine name not specified") public String getName() { return name; } diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Resource.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Resource.java index a94eb1cbc..7521b2b9e 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Resource.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Resource.java @@ -700,6 +700,13 @@ public abstract class Resource extends BaseEntity{ return sum; } + public void addUnvalidatedSatisfaction(CriterionSatisfaction + criterionSatisfaction) { + + criterionSatisfactions.add(criterionSatisfaction); + + } + public void addSatisfactions(Set addlist) throws ValidationException { //Create a newList with new Satisfactions and the old satisfactions Set newList = new HashSet(addlist); diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Worker.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Worker.java index af6d12d2f..fbf81b8e7 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Worker.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Worker.java @@ -46,6 +46,20 @@ public class Worker extends Resource { return worker; } + public static Worker createUnvalidated(String firstName, String surname, + String nif) { + + Worker worker = new Worker(); + + worker.firstName = firstName; + worker.surname = surname; + worker.nif = nif; + worker.setNewObject(true); + + return worker; + + } + private String firstName; private String surname; @@ -74,7 +88,7 @@ public class Worker extends Resource { return getNif() + " :: " + getDescription(); } - @NotEmpty + @NotEmpty(message="worker's first name not specified") public String getFirstName() { return firstName; } @@ -83,7 +97,7 @@ public class Worker extends Resource { this.firstName = firstName; } - @NotEmpty + @NotEmpty(message="worker's surname not specified") public String getSurname() { return surname; } @@ -96,7 +110,7 @@ public class Worker extends Resource { return firstName + " " + surname; } - @NotEmpty + @NotEmpty(message="worker's NIF not specified") public String getNif() { return nif; } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/ConstraintViolationDTO.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/ConstraintViolationDTO.java index 21c20f495..2be59df5f 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/ConstraintViolationDTO.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/ConstraintViolationDTO.java @@ -33,13 +33,13 @@ public class ConstraintViolationDTO { public String fieldName; @XmlAttribute - public String mesage; + public String message; public ConstraintViolationDTO() {} - public ConstraintViolationDTO(String fieldName, String mesage) { + public ConstraintViolationDTO(String fieldName, String message) { this.fieldName = fieldName; - this.mesage = mesage; + this.message = message; } } 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 c844833fb..1ea323ea5 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 @@ -20,6 +20,7 @@ package org.navalplanner.ws.common.api; +import java.util.ArrayList; import java.util.List; import javax.xml.bind.annotation.XmlAttribute; @@ -41,11 +42,24 @@ public class InstanceConstraintViolationsDTO { public InstanceConstraintViolationsDTO() {} public InstanceConstraintViolationsDTO(String instanceId, - List constraintViolations) { + List constraintViolations) { this.instanceId = instanceId; this.constraintViolations = constraintViolations; } + public static InstanceConstraintViolationsDTO create(String instanceId, + String message) { + + List constraintViolations = + new ArrayList(); + + constraintViolations.add(new ConstraintViolationDTO(null, message)); + + return new InstanceConstraintViolationsDTO(instanceId, + constraintViolations); + + } + } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/DateConverter.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/DateConverter.java new file mode 100644 index 000000000..109878d25 --- /dev/null +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/DateConverter.java @@ -0,0 +1,91 @@ +/* + * This file is part of ###PROJECT_NAME### + * + * 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.Calendar; +import java.util.Date; + +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeConstants; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; + +/** + * A converter from java.util.Date to/from + * javax.xml.datatype.XMLGregorianCalendar. + * + * @author Fernando Bellas Permuy + */ +public class DateConverter { + + private DateConverter() {} + + /** + * It converts a Date to a XMLGregorianCalendar + * representing a xsd:date XML type.

+ * + * If the date passed as a parameter is null, it also returns + * null. + */ + public final static XMLGregorianCalendar toXMLGregrorianCalendar( + Date date) { + + if (date == null) { + return null; + } + + Calendar dateAsCalendar = Calendar.getInstance(); + dateAsCalendar.setTime(date); + XMLGregorianCalendar dateAsXMLGregorianCalendar = null; + + try { + dateAsXMLGregorianCalendar = + DatatypeFactory.newInstance().newXMLGregorianCalendarDate( + dateAsCalendar.get(Calendar.YEAR), + dateAsCalendar.get(Calendar.MONTH), + dateAsCalendar.get(Calendar.DAY_OF_MONTH), + DatatypeConstants.FIELD_UNDEFINED); + } catch (DatatypeConfigurationException e) { + throw new RuntimeException(e); + } + + return dateAsXMLGregorianCalendar; + + } + + /** + * It converts a XMLGregorianCalendar representing a + * xsd:date XML type to a Date.

+ * + * If the date passed as a parameter is null, it also returns + * null. + */ + public final static Date toDate(XMLGregorianCalendar date) { + + if (date == null) { + return null; + } else { + return date.toGregorianCalendar().getTime(); + } + + } + +} diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/api/CriterionSatisfactionDTO.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/api/CriterionSatisfactionDTO.java new file mode 100644 index 000000000..1ae9b064f --- /dev/null +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/api/CriterionSatisfactionDTO.java @@ -0,0 +1,64 @@ +/* + * This file is part of ###PROJECT_NAME### + * + * 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.resources.api; + +import java.util.Date; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.datatype.XMLGregorianCalendar; + +import org.navalplanner.ws.common.impl.DateConverter; + +/** + * DTO for CriterionSatisfaction entity. + * + * @author Fernando Bellas Permuy + */ +public class CriterionSatisfactionDTO { + + @XmlAttribute(name="criterion-type-name") + public String criterionTypeName; + + @XmlAttribute(name="criterion-name") + public String criterionName; + + @XmlAttribute(name="start-date") + @XmlSchemaType(name="date") + public XMLGregorianCalendar startDate; + + @XmlAttribute(name="finish-date") + @XmlSchemaType(name="date") + public XMLGregorianCalendar finishDate; + + public CriterionSatisfactionDTO() {} + + public CriterionSatisfactionDTO(String criterionTypeName, + String criterionName, Date startDate, Date finishDate) { + + this.criterionTypeName = criterionTypeName; + this.criterionName = criterionName; + this.startDate = DateConverter.toXMLGregrorianCalendar(startDate); + this.finishDate = DateConverter.toXMLGregrorianCalendar(finishDate); + + } + +} diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/api/IResourceService.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/api/IResourceService.java index f610e0637..4608a4c7f 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/api/IResourceService.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/api/IResourceService.java @@ -23,7 +23,13 @@ package org.navalplanner.ws.resources.api; import org.navalplanner.ws.common.api.InstanceConstraintViolationsListDTO; /** - * Service for managing resources. + * Service for managing resources.

+ * + * NOTE: When a resource can not be imported because one of its criterion + * satisfactions uses an incorrect criterion type name or criterion name, no + * other validations on such a resource are executed (because the corresponding + * criterion satisfaction can not be constructed, and in consequence, the + * resource itself can not be constructed). * * @author Fernando Bellas Permuy */ diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/api/ResourceDTO.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/api/ResourceDTO.java index e4136c219..599e4f499 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/api/ResourceDTO.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/api/ResourceDTO.java @@ -20,6 +20,12 @@ package org.navalplanner.ws.resources.api; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; + /** * DTO for Resource entity. * @@ -27,6 +33,11 @@ package org.navalplanner.ws.resources.api; */ public abstract class ResourceDTO { + @XmlElementWrapper(name="criterion-satisfaction-list") + @XmlElement(name="criterion-satisfaction") + public List criterionSatisfactions = + new ArrayList(); + public abstract String getUserProvidedId(); } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/api/ResourceListDTO.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/api/ResourceListDTO.java index e0435c5d6..7b01cbfa3 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/api/ResourceListDTO.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/api/ResourceListDTO.java @@ -39,11 +39,11 @@ public class ResourceListDTO { @XmlElement(name = "worker", type = WorkerDTO.class), @XmlElement(name = "machine", type = MachineDTO.class) }) - public List resources = new ArrayList(); + public List resources = new ArrayList(); public ResourceListDTO() {} - public ResourceListDTO(List resources) { + public ResourceListDTO(List resources) { this.resources = resources; } 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 fbc758348..f8f1d534d 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 @@ -22,9 +22,15 @@ package org.navalplanner.ws.resources.impl; import static org.navalplanner.web.I18nHelper._; +import java.util.List; + +import org.navalplanner.business.common.exceptions.CreateUnvalidatedException; +import org.navalplanner.business.resources.entities.CriterionSatisfaction; 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.resources.api.CriterionSatisfactionDTO; import org.navalplanner.ws.resources.api.MachineDTO; import org.navalplanner.ws.resources.api.ResourceDTO; import org.navalplanner.ws.resources.api.WorkerDTO; @@ -38,28 +44,67 @@ public class ResourceConverter { private ResourceConverter() {} - public final static Resource toEntity(ResourceDTO resourceDTO) { + public final static Resource toEntity(ResourceDTO resourceDTO) + throws CreateUnvalidatedException { + + Resource resource; if (resourceDTO instanceof MachineDTO) { - return toEntity((MachineDTO) resourceDTO); + resource = createResourceWithBasicData((MachineDTO) resourceDTO); } else if (resourceDTO instanceof WorkerDTO) { - return toEntity((WorkerDTO) resourceDTO); + resource = createResourceWithBasicData((WorkerDTO) resourceDTO); } else { throw new RuntimeException( _("Service does not manages resource of type: {0}", resourceDTO.getClass().getName())); } + addCriterionSatisfactions(resource, + resourceDTO.criterionSatisfactions); + + return resource; + } - public final static Machine toEntity(MachineDTO machineDTO) { - return Machine.create(machineDTO.code,machineDTO.name, + private final static Machine createResourceWithBasicData( + MachineDTO machineDTO) { + return Machine.createUnvalidated(machineDTO.code,machineDTO.name, machineDTO.description); } - public final static Worker toEntity(WorkerDTO workerDTO) { - return Worker.create(workerDTO.firstName, workerDTO.surname, + private final static Worker createResourceWithBasicData( + WorkerDTO workerDTO) { + return Worker.createUnvalidated(workerDTO.firstName, workerDTO.surname, workerDTO.nif); } + private static void addCriterionSatisfactions(Resource resource, + List criterionSatisfactions) + throws CreateUnvalidatedException { + + for (CriterionSatisfactionDTO criterionSatisfactionDTO : + criterionSatisfactions) { + + CriterionSatisfaction criterionSatisfaction = + toEntity(criterionSatisfactionDTO, resource); + + resource.addUnvalidatedSatisfaction(criterionSatisfaction); + + } + + } + + private static CriterionSatisfaction toEntity( + CriterionSatisfactionDTO criterionSatisfactionDTO, Resource resource) + throws CreateUnvalidatedException { + + return CriterionSatisfaction.createUnvalidated( + criterionSatisfactionDTO.criterionTypeName, + criterionSatisfactionDTO.criterionName, + resource, + DateConverter.toDate(criterionSatisfactionDTO.startDate), + DateConverter.toDate(criterionSatisfactionDTO.finishDate)); + + } + } 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 b2e7c4fb6..d66d10d04 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 @@ -28,6 +28,7 @@ import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; +import org.navalplanner.business.common.exceptions.CreateUnvalidatedException; import org.navalplanner.business.common.exceptions.ValidationException; import org.navalplanner.business.resources.daos.IResourceDAO; import org.navalplanner.business.resources.entities.Resource; @@ -66,30 +67,47 @@ public class ResourceServiceREST implements IResourceService { new ArrayList(); int instanceNumber = 1; + /* Process resources. */ for (ResourceDTO resourceDTO : resources.resources) { - Resource resource = ResourceConverter.toEntity(resourceDTO); InstanceConstraintViolationsDTO instanceConstraintViolationsDTO = null; + Resource resource = null; + /* Convert DTO to entity. */ try { - - /* - * See CriterionServiceREST::addCriterionTypes for a - * justification of the explicit use of BaseEntity::validate. - * - */ - resource.validate(); - resourceDAO.save(resource); - - } catch (ValidationException e) { + resource = ResourceConverter.toEntity(resourceDTO); + } catch (CreateUnvalidatedException e) { instanceConstraintViolationsDTO = - ConstraintViolationConverter.toDTO( + InstanceConstraintViolationsDTO.create( Util.generateInstanceId(instanceNumber, resourceDTO.getUserProvidedId()), - e.getInvalidValues()); + e.getMessage()); } + /* Validate resource. */ + if (resource != null) { + try { + + /* + * See CriterionServiceREST::addCriterionTypes for a + * justification of the explicit use of + * BaseEntity::validate. + * + */ + resource.validate(); + resourceDAO.save(resource); + + } catch (ValidationException e) { + instanceConstraintViolationsDTO = + ConstraintViolationConverter.toDTO( + Util.generateInstanceId(instanceNumber, + resourceDTO.getUserProvidedId()), + e.getInvalidValues()); + } + } + + /* Add constraint violations (if any). */ if (instanceConstraintViolationsDTO != null) { instanceConstraintViolationsList.add( instanceConstraintViolationsDTO); 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 2db604572..14f5f1159 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 @@ -21,26 +21,38 @@ package org.navalplanner.web.test.ws.resources.api; 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.test.WebappGlobalNames.WEBAPP_SPRING_CONFIG_TEST_FILE; import java.util.ArrayList; +import java.util.Calendar; import java.util.List; import java.util.UUID; import org.junit.Test; import org.junit.runner.RunWith; +import org.navalplanner.business.common.IAdHocTransactionService; +import org.navalplanner.business.common.IOnTransaction; import org.navalplanner.business.common.exceptions.InstanceNotFoundException; +import org.navalplanner.business.resources.daos.ICriterionTypeDAO; import org.navalplanner.business.resources.daos.IMachineDAO; 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; +import org.navalplanner.business.resources.entities.Machine; +import org.navalplanner.business.resources.entities.Resource; import org.navalplanner.ws.common.api.InstanceConstraintViolationsDTO; +import org.navalplanner.ws.resources.api.CriterionSatisfactionDTO; 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.test.annotation.NotTransactional; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.transaction.annotation.Transactional; @@ -65,6 +77,12 @@ public class ResourceServiceTest { @Autowired private IWorkerDAO workerDAO; + @Autowired + private ICriterionTypeDAO criterionTypeDAO; + + @Autowired + private IAdHocTransactionService transactionService; + @Test public void testAddResourcesWithBasicContraintViolations() throws InstanceNotFoundException { @@ -99,6 +117,162 @@ public class ResourceServiceTest { } + @Test + @NotTransactional + public void testAddResourceWithCriterionSatisfactions() + throws InstanceNotFoundException { + + /* Create a criterion type. */ + CriterionType ct = createCriterionType(); + + /* Create a resource DTO. */ + MachineDTO machineDTO = new MachineDTO(ct.getName(), "name", "desc"); + machineDTO.criterionSatisfactions.add( + new CriterionSatisfactionDTO(ct.getName(), "c1", + Calendar.getInstance().getTime(), null)); + machineDTO.criterionSatisfactions.add( + new CriterionSatisfactionDTO(ct.getName(), "c2", + Calendar.getInstance().getTime(), null)); + + /* Test. */ + List resources = new ArrayList(); + resources.add(machineDTO); + + List instanceConstraintViolationsList = + resourceService.addResources(new ResourceListDTO(resources)). + instanceConstraintViolationsList; + + assertTrue(instanceConstraintViolationsList.isEmpty()); + + Machine machine = findUniqueMachineByCode(machineDTO.code); + assertTrue(machine.getCriterionSatisfactions().size() == 2); + + for (CriterionSatisfaction cs : machine.getCriterionSatisfactions()) { + if (!(cs.getCriterion().getName().equals("c1") || + cs.getCriterion().getName().equals("c2"))) { + fail("Criterion not expected"); + } + } + + } + + @Test + @NotTransactional + public void testAddResourceWithCriterionSatisfactionsWithIncorrectNames() { + + /* Create a criterion type. */ + CriterionType ct = createCriterionType(); + + /* Create resource DTOs. */ + MachineDTO m1 = new MachineDTO(getUniqueName(), "name", "desc"); + m1.criterionSatisfactions.add( + new CriterionSatisfactionDTO("", "X", // Missing criterion type. + Calendar.getInstance().getTime(), null)); + MachineDTO m2 = new MachineDTO(getUniqueName(), "name", "desc"); + m2.criterionSatisfactions.add( + new CriterionSatisfactionDTO(ct.getName(), // Missing criterion. + null, Calendar.getInstance().getTime(), null)); + MachineDTO m3 = new MachineDTO(getUniqueName(), "name", "desc"); + m3.criterionSatisfactions.add( + new CriterionSatisfactionDTO( + ct.getName() + 'X', // Non-existent criterion type. + "c1", Calendar.getInstance().getTime(), null)); + MachineDTO m4 = new MachineDTO(getUniqueName(), "name", "desc"); + m4.criterionSatisfactions.add( + new CriterionSatisfactionDTO( + ct.getName(), + "c1" + 'X', // Criterion name is not of ct's type. + Calendar.getInstance().getTime(), null)); + + /* Test. */ + List machines = new ArrayList(); + machines.add(m1); + machines.add(m2); + machines.add(m3); + machines.add(m4); + + List instanceConstraintViolationsList = + resourceService.addResources(new ResourceListDTO(machines)). + instanceConstraintViolationsList; + + assertTrue(instanceConstraintViolationsList.size() == machines.size()); + + for (InstanceConstraintViolationsDTO i : + instanceConstraintViolationsList) { + assertTrue(i.constraintViolations.size() == 1); + } + + for (MachineDTO m : machines) { + try { + findUniqueMachineByCode(m.code); + fail("InstanceNotFoundException expected"); + } catch (InstanceNotFoundException e) { + } + } + + } + + private CriterionType createCriterionType() { + + IOnTransaction createCriterionType = + new IOnTransaction() { + + @Override + public CriterionType execute() { + + CriterionType ct = CriterionType.create(getUniqueName(), + "desc"); + Criterion c1 = Criterion.create("c1", ct); + Criterion c2 = Criterion.create("c2", ct); + ct.getCriterions().add(c1); + ct.getCriterions().add(c2); + criterionTypeDAO.save(ct); + + return ct; + + } + }; + + return transactionService.runOnTransaction(createCriterionType); + + } + + private Machine findUniqueMachineByCode(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(); + } + + return resource; + + } + private String getUniqueName() { return UUID.randomUUID().toString(); } diff --git a/scripts/rest-clients/resources-sample.xml b/scripts/rest-clients/resources-sample.xml index 58627359a..aaa157b54 100644 --- a/scripts/rest-clients/resources-sample.xml +++ b/scripts/rest-clients/resources-sample.xml @@ -10,7 +10,20 @@ - + + + + + +