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 extends ResourceDTO> resources = new ArrayList();
public ResourceListDTO() {}
- public ResourceListDTO(List resources) {
+ public ResourceListDTO(List extends ResourceDTO> 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 @@
-
+
+
+
+
+
+