ItEr40S20CUImportacionRecursosProductivosItEr39S23: Added support for importing resources containing criterion satisfactions.

Added support for importing resources containing criterion satisfactions. Complex validations are not implemented yet.
This commit is contained in:
Fernando Bellas Permuy 2009-12-23 09:22:51 +01:00 committed by Javier Moran Rua
parent a01c1fa5b3
commit ed5c0976d2
18 changed files with 651 additions and 36 deletions

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
package org.navalplanner.business.common;
/**
* String utility methods.
*
* @author Fernando Bellas Permuy <fbellas@udc.es>
*/
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("");
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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 <fbellas@udc.es>
*/
@SuppressWarnings("serial")
public class CreateUnvalidatedException extends Exception {
public CreateUnvalidatedException(String message) {
super(message);
}
}

View file

@ -20,6 +20,8 @@
package org.navalplanner.business.resources.entities; package org.navalplanner.business.resources.entities;
import static org.navalplanner.business.i18n.I18nHelper._;
import java.util.Comparator; import java.util.Comparator;
import java.util.Date; import java.util.Date;
@ -27,9 +29,15 @@ import org.apache.commons.lang.Validate;
import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder.ToStringBuilder;
import org.hibernate.validator.NotNull; import org.hibernate.validator.NotNull;
import org.navalplanner.business.common.BaseEntity; 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 <br /> * Declares a interval of time in which the criterion is satisfied <br />
* @author Óscar González Fernández <ogonzalez@igalia.com> * @author Óscar González Fernández <ogonzalez@igalia.com>
* @author Fernando Bellas Permuy <fbellas@udc.es>
*/ */
public class CriterionSatisfaction extends BaseEntity { public class CriterionSatisfaction extends BaseEntity {
@ -67,6 +75,58 @@ public class CriterionSatisfaction extends BaseEntity {
return criterionSatisfaction; 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! * Constructor for hibernate. Do not use!
*/ */
@ -92,7 +152,6 @@ public class CriterionSatisfaction extends BaseEntity {
} }
} }
@NotNull
private Date startDate; private Date startDate;
private Date finishDate; private Date finishDate;
@ -117,6 +176,7 @@ public class CriterionSatisfaction extends BaseEntity {
return result; return result;
} }
@NotNull(message="criterion satisfaction's start date not specified")
public Date getStartDate() { public Date getStartDate() {
return startDate != null ? new Date(startDate.getTime()) : null; return startDate != null ? new Date(startDate.getTime()) : null;
} }
@ -133,6 +193,7 @@ public class CriterionSatisfaction extends BaseEntity {
return Interval.range(startDate, finishDate); return Interval.range(startDate, finishDate);
} }
@NotNull(message="criterion satisfaction's criterion not specified")
public Criterion getCriterion() { public Criterion getCriterion() {
return criterion; return criterion;
} }
@ -141,6 +202,7 @@ public class CriterionSatisfaction extends BaseEntity {
this.criterion = criterion; this.criterion = criterion;
} }
@NotNull(message="criterion satisfaction's resource not specified")
public Resource getResource() { public Resource getResource() {
return resource; return resource;
} }

View file

@ -284,6 +284,20 @@ public class CriterionType extends BaseEntity implements
return criterions.size(); 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 " + @AssertTrue(message="criterion names must be unique inside a criterion " +
"type") "type")
public boolean checkConstraintNonRepeatedCriterionNames() { public boolean checkConstraintNonRepeatedCriterionNames() {

View file

@ -43,10 +43,17 @@ public class Machine extends Resource {
configurationUnits.remove(unit); configurationUnits.remove(unit);
} }
public static Machine create(String code, String name, String description) { public static Machine createUnvalidated(String code, String name, String description) {
Machine machine = new Machine(code, name, description);
Machine machine = new Machine();
machine.code = code;
machine.name = name;
machine.description = description;
machine.setNewObject(true); machine.setNewObject(true);
return machine; return machine;
} }
protected Machine() { protected Machine() {
@ -63,7 +70,7 @@ public class Machine extends Resource {
return create(new Machine()); return create(new Machine());
} }
@NotEmpty @NotEmpty(message="machine code not specified")
public String getCode() { public String getCode() {
return code; return code;
} }
@ -72,7 +79,7 @@ public class Machine extends Resource {
this.code = code; this.code = code;
} }
@NotEmpty @NotEmpty(message="machine name not specified")
public String getName() { public String getName() {
return name; return name;
} }

View file

@ -700,6 +700,13 @@ public abstract class Resource extends BaseEntity{
return sum; return sum;
} }
public void addUnvalidatedSatisfaction(CriterionSatisfaction
criterionSatisfaction) {
criterionSatisfactions.add(criterionSatisfaction);
}
public void addSatisfactions(Set<CriterionSatisfaction> addlist) throws ValidationException { public void addSatisfactions(Set<CriterionSatisfaction> addlist) throws ValidationException {
//Create a newList with new Satisfactions and the old satisfactions //Create a newList with new Satisfactions and the old satisfactions
Set<CriterionSatisfaction> newList = new HashSet<CriterionSatisfaction>(addlist); Set<CriterionSatisfaction> newList = new HashSet<CriterionSatisfaction>(addlist);

View file

@ -46,6 +46,20 @@ public class Worker extends Resource {
return worker; 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 firstName;
private String surname; private String surname;
@ -74,7 +88,7 @@ public class Worker extends Resource {
return getNif() + " :: " + getDescription(); return getNif() + " :: " + getDescription();
} }
@NotEmpty @NotEmpty(message="worker's first name not specified")
public String getFirstName() { public String getFirstName() {
return firstName; return firstName;
} }
@ -83,7 +97,7 @@ public class Worker extends Resource {
this.firstName = firstName; this.firstName = firstName;
} }
@NotEmpty @NotEmpty(message="worker's surname not specified")
public String getSurname() { public String getSurname() {
return surname; return surname;
} }
@ -96,7 +110,7 @@ public class Worker extends Resource {
return firstName + " " + surname; return firstName + " " + surname;
} }
@NotEmpty @NotEmpty(message="worker's NIF not specified")
public String getNif() { public String getNif() {
return nif; return nif;
} }

View file

@ -33,13 +33,13 @@ public class ConstraintViolationDTO {
public String fieldName; public String fieldName;
@XmlAttribute @XmlAttribute
public String mesage; public String message;
public ConstraintViolationDTO() {} public ConstraintViolationDTO() {}
public ConstraintViolationDTO(String fieldName, String mesage) { public ConstraintViolationDTO(String fieldName, String message) {
this.fieldName = fieldName; this.fieldName = fieldName;
this.mesage = mesage; this.message = message;
} }
} }

View file

@ -20,6 +20,7 @@
package org.navalplanner.ws.common.api; package org.navalplanner.ws.common.api;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlAttribute;
@ -41,11 +42,24 @@ public class InstanceConstraintViolationsDTO {
public InstanceConstraintViolationsDTO() {} public InstanceConstraintViolationsDTO() {}
public InstanceConstraintViolationsDTO(String instanceId, public InstanceConstraintViolationsDTO(String instanceId,
List<ConstraintViolationDTO> constraintViolations) { List<ConstraintViolationDTO> constraintViolations) {
this.instanceId = instanceId; this.instanceId = instanceId;
this.constraintViolations = constraintViolations; this.constraintViolations = constraintViolations;
} }
public static InstanceConstraintViolationsDTO create(String instanceId,
String message) {
List<ConstraintViolationDTO> constraintViolations =
new ArrayList<ConstraintViolationDTO>();
constraintViolations.add(new ConstraintViolationDTO(null, message));
return new InstanceConstraintViolationsDTO(instanceId,
constraintViolations);
}
} }

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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 <code>java.util.Date</code> to/from
* <code>javax.xml.datatype.XMLGregorianCalendar</code>.
*
* @author Fernando Bellas Permuy <fbellas@udc.es>
*/
public class DateConverter {
private DateConverter() {}
/**
* It converts a <code>Date</code> to a <code>XMLGregorianCalendar</code>
* representing a <code>xsd:date</code> XML type. <br/><br/>
*
* If the date passed as a parameter is <code>null</code>, it also returns
* <code>null</code>.
*/
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 <code>XMLGregorianCalendar</code> representing a
* <code>xsd:date</code> XML type to a <code>Date</code>.<br/><br/>
*
* If the date passed as a parameter is <code>null</code>, it also returns
* <code>null</code>.
*/
public final static Date toDate(XMLGregorianCalendar date) {
if (date == null) {
return null;
} else {
return date.toGregorianCalendar().getTime();
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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 <code>CriterionSatisfaction</code> entity.
*
* @author Fernando Bellas Permuy <fbellas@udc.es>
*/
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);
}
}

View file

@ -23,7 +23,13 @@ package org.navalplanner.ws.resources.api;
import org.navalplanner.ws.common.api.InstanceConstraintViolationsListDTO; import org.navalplanner.ws.common.api.InstanceConstraintViolationsListDTO;
/** /**
* Service for managing resources. * Service for managing resources.<br/><br/>
*
* 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 <fbellas@udc.es> * @author Fernando Bellas Permuy <fbellas@udc.es>
*/ */

View file

@ -20,6 +20,12 @@
package org.navalplanner.ws.resources.api; 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 <code>Resource</code> entity. * DTO for <code>Resource</code> entity.
* *
@ -27,6 +33,11 @@ package org.navalplanner.ws.resources.api;
*/ */
public abstract class ResourceDTO { public abstract class ResourceDTO {
@XmlElementWrapper(name="criterion-satisfaction-list")
@XmlElement(name="criterion-satisfaction")
public List<CriterionSatisfactionDTO> criterionSatisfactions =
new ArrayList<CriterionSatisfactionDTO>();
public abstract String getUserProvidedId(); public abstract String getUserProvidedId();
} }

View file

@ -39,11 +39,11 @@ public class ResourceListDTO {
@XmlElement(name = "worker", type = WorkerDTO.class), @XmlElement(name = "worker", type = WorkerDTO.class),
@XmlElement(name = "machine", type = MachineDTO.class) @XmlElement(name = "machine", type = MachineDTO.class)
}) })
public List<ResourceDTO> resources = new ArrayList<ResourceDTO>(); public List<? extends ResourceDTO> resources = new ArrayList<ResourceDTO>();
public ResourceListDTO() {} public ResourceListDTO() {}
public ResourceListDTO(List<ResourceDTO> resources) { public ResourceListDTO(List<? extends ResourceDTO> resources) {
this.resources = resources; this.resources = resources;
} }

View file

@ -22,9 +22,15 @@ package org.navalplanner.ws.resources.impl;
import static org.navalplanner.web.I18nHelper._; 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.Machine;
import org.navalplanner.business.resources.entities.Resource; import org.navalplanner.business.resources.entities.Resource;
import org.navalplanner.business.resources.entities.Worker; import org.navalplanner.business.resources.entities.Worker;
import org.navalplanner.ws.common.impl.DateConverter;
import org.navalplanner.ws.resources.api.CriterionSatisfactionDTO;
import org.navalplanner.ws.resources.api.MachineDTO; import org.navalplanner.ws.resources.api.MachineDTO;
import org.navalplanner.ws.resources.api.ResourceDTO; import org.navalplanner.ws.resources.api.ResourceDTO;
import org.navalplanner.ws.resources.api.WorkerDTO; import org.navalplanner.ws.resources.api.WorkerDTO;
@ -38,28 +44,67 @@ public class ResourceConverter {
private ResourceConverter() {} private ResourceConverter() {}
public final static Resource toEntity(ResourceDTO resourceDTO) { public final static Resource toEntity(ResourceDTO resourceDTO)
throws CreateUnvalidatedException {
Resource resource;
if (resourceDTO instanceof MachineDTO) { if (resourceDTO instanceof MachineDTO) {
return toEntity((MachineDTO) resourceDTO); resource = createResourceWithBasicData((MachineDTO) resourceDTO);
} else if (resourceDTO instanceof WorkerDTO) { } else if (resourceDTO instanceof WorkerDTO) {
return toEntity((WorkerDTO) resourceDTO); resource = createResourceWithBasicData((WorkerDTO) resourceDTO);
} else { } else {
throw new RuntimeException( throw new RuntimeException(
_("Service does not manages resource of type: {0}", _("Service does not manages resource of type: {0}",
resourceDTO.getClass().getName())); resourceDTO.getClass().getName()));
} }
addCriterionSatisfactions(resource,
resourceDTO.criterionSatisfactions);
return resource;
} }
public final static Machine toEntity(MachineDTO machineDTO) { private final static Machine createResourceWithBasicData(
return Machine.create(machineDTO.code,machineDTO.name, MachineDTO machineDTO) {
return Machine.createUnvalidated(machineDTO.code,machineDTO.name,
machineDTO.description); machineDTO.description);
} }
public final static Worker toEntity(WorkerDTO workerDTO) { private final static Worker createResourceWithBasicData(
return Worker.create(workerDTO.firstName, workerDTO.surname, WorkerDTO workerDTO) {
return Worker.createUnvalidated(workerDTO.firstName, workerDTO.surname,
workerDTO.nif); workerDTO.nif);
} }
private static void addCriterionSatisfactions(Resource resource,
List<CriterionSatisfactionDTO> 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));
}
} }

View file

@ -28,6 +28,7 @@ import javax.ws.rs.POST;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
import org.navalplanner.business.common.exceptions.CreateUnvalidatedException;
import org.navalplanner.business.common.exceptions.ValidationException; import org.navalplanner.business.common.exceptions.ValidationException;
import org.navalplanner.business.resources.daos.IResourceDAO; import org.navalplanner.business.resources.daos.IResourceDAO;
import org.navalplanner.business.resources.entities.Resource; import org.navalplanner.business.resources.entities.Resource;
@ -66,30 +67,47 @@ public class ResourceServiceREST implements IResourceService {
new ArrayList<InstanceConstraintViolationsDTO>(); new ArrayList<InstanceConstraintViolationsDTO>();
int instanceNumber = 1; int instanceNumber = 1;
/* Process resources. */
for (ResourceDTO resourceDTO : resources.resources) { for (ResourceDTO resourceDTO : resources.resources) {
Resource resource = ResourceConverter.toEntity(resourceDTO);
InstanceConstraintViolationsDTO instanceConstraintViolationsDTO = InstanceConstraintViolationsDTO instanceConstraintViolationsDTO =
null; null;
Resource resource = null;
/* Convert DTO to entity. */
try { try {
resource = ResourceConverter.toEntity(resourceDTO);
/* } catch (CreateUnvalidatedException e) {
* See CriterionServiceREST::addCriterionTypes for a
* justification of the explicit use of BaseEntity::validate.
*
*/
resource.validate();
resourceDAO.save(resource);
} catch (ValidationException e) {
instanceConstraintViolationsDTO = instanceConstraintViolationsDTO =
ConstraintViolationConverter.toDTO( InstanceConstraintViolationsDTO.create(
Util.generateInstanceId(instanceNumber, Util.generateInstanceId(instanceNumber,
resourceDTO.getUserProvidedId()), 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) { if (instanceConstraintViolationsDTO != null) {
instanceConstraintViolationsList.add( instanceConstraintViolationsList.add(
instanceConstraintViolationsDTO); instanceConstraintViolationsDTO);

View file

@ -21,26 +21,38 @@
package org.navalplanner.web.test.ws.resources.api; package org.navalplanner.web.test.ws.resources.api;
import static org.junit.Assert.assertTrue; 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.business.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_FILE;
import static org.navalplanner.web.WebappGlobalNames.WEBAPP_SPRING_CONFIG_FILE; import static org.navalplanner.web.WebappGlobalNames.WEBAPP_SPRING_CONFIG_FILE;
import static org.navalplanner.web.test.WebappGlobalNames.WEBAPP_SPRING_CONFIG_TEST_FILE; import static org.navalplanner.web.test.WebappGlobalNames.WEBAPP_SPRING_CONFIG_TEST_FILE;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; 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.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.resources.daos.ICriterionTypeDAO;
import org.navalplanner.business.resources.daos.IMachineDAO; import org.navalplanner.business.resources.daos.IMachineDAO;
import org.navalplanner.business.resources.daos.IWorkerDAO; 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.common.api.InstanceConstraintViolationsDTO;
import org.navalplanner.ws.resources.api.CriterionSatisfactionDTO;
import org.navalplanner.ws.resources.api.IResourceService; import org.navalplanner.ws.resources.api.IResourceService;
import org.navalplanner.ws.resources.api.MachineDTO; import org.navalplanner.ws.resources.api.MachineDTO;
import org.navalplanner.ws.resources.api.ResourceDTO; import org.navalplanner.ws.resources.api.ResourceDTO;
import org.navalplanner.ws.resources.api.ResourceListDTO; import org.navalplanner.ws.resources.api.ResourceListDTO;
import org.navalplanner.ws.resources.api.WorkerDTO; import org.navalplanner.ws.resources.api.WorkerDTO;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.NotTransactional;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -65,6 +77,12 @@ public class ResourceServiceTest {
@Autowired @Autowired
private IWorkerDAO workerDAO; private IWorkerDAO workerDAO;
@Autowired
private ICriterionTypeDAO criterionTypeDAO;
@Autowired
private IAdHocTransactionService transactionService;
@Test @Test
public void testAddResourcesWithBasicContraintViolations() public void testAddResourcesWithBasicContraintViolations()
throws InstanceNotFoundException { 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<ResourceDTO> resources = new ArrayList<ResourceDTO>();
resources.add(machineDTO);
List<InstanceConstraintViolationsDTO> 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<MachineDTO> machines = new ArrayList<MachineDTO>();
machines.add(m1);
machines.add(m2);
machines.add(m3);
machines.add(m4);
List<InstanceConstraintViolationsDTO> 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<CriterionType> createCriterionType =
new IOnTransaction<CriterionType>() {
@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<Machine> find = new IOnTransaction<Machine>() {
@Override
public Machine execute() {
try {
return (Machine) initializeResource(
machineDAO.findUniqueByCode(code));
} catch (InstanceNotFoundException e) {
return null;
}
}
};
Machine machine = transactionService.runOnTransaction(find);
if (machine == null) {
throw new InstanceNotFoundException(code, Machine.class.getName());
} else {
return machine;
}
}
private Resource initializeResource(Resource resource) {
for (CriterionSatisfaction cs : resource.getCriterionSatisfactions()) {
cs.getCriterion().getType().getName();
}
return resource;
}
private String getUniqueName() { private String getUniqueName() {
return UUID.randomUUID().toString(); return UUID.randomUUID().toString();
} }

View file

@ -10,7 +10,20 @@
<!-- *** Workers *** --> <!-- *** Workers *** -->
<!-- OK --> <!-- OK -->
<worker first-name="w1-firstName" surname="w1-surname" nif="w1-nif"/> <worker first-name="w1-firstName" surname="w1-surname" nif="w1-nif">
<criterion-satisfaction-list>
<criterion-satisfaction
criterion-type-name="WORK_RELATIONSHIP"
criterion-name="hiredResourceWorkingRelationship"
start-date="2009-01-01"
finish-date=""/>
<criterion-satisfaction
criterion-type-name="LEAVE"
criterion-name="paternityLeave"
start-date="2009-12-24"
finish-date="2009-12-25"/>
</criterion-satisfaction-list>
</worker>
<!-- Missing first name, surname, and nif. --> <!-- Missing first name, surname, and nif. -->
<worker first-name="" surname="" nif=""/> <worker first-name="" surname="" nif=""/>