diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/common/Registry.java b/navalplanner-business/src/main/java/org/navalplanner/business/common/Registry.java index ccffb5fef..0be1975d7 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/common/Registry.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/common/Registry.java @@ -23,6 +23,7 @@ package org.navalplanner.business.common; import org.navalplanner.business.advance.daos.IAdvanceTypeDAO; import org.navalplanner.business.calendars.daos.IBaseCalendarDAO; import org.navalplanner.business.common.daos.IConfigurationDAO; +import org.navalplanner.business.costcategories.daos.ICostCategoryDAO; import org.navalplanner.business.costcategories.daos.ITypeOfWorkHoursDAO; import org.navalplanner.business.externalcompanies.daos.IExternalCompanyDAO; import org.navalplanner.business.labels.daos.ILabelDAO; @@ -107,7 +108,7 @@ public class Registry { @Autowired private IWorkerDAO workerDAO; - + @Autowired private IWorkReportLineDAO workReportLineDAO; @@ -120,6 +121,9 @@ public class Registry { @Autowired private IHoursGroupDAO hoursGroupDAO; + @Autowired + private ICostCategoryDAO costCategoryDAO; + private Registry() { } @@ -206,4 +210,8 @@ public class Registry { return getInstance().hoursGroupDAO; } + public static ICostCategoryDAO getCostCategoryDAO() { + return getInstance().costCategoryDAO; + } + } diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/daos/CostCategoryDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/daos/CostCategoryDAO.java index 3a9f6dc9d..b9ba22f10 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/daos/CostCategoryDAO.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/daos/CostCategoryDAO.java @@ -28,6 +28,7 @@ import org.hibernate.Criteria; import org.hibernate.criterion.Restrictions; import org.joda.time.LocalDate; import org.navalplanner.business.common.daos.GenericDAOHibernate; +import org.navalplanner.business.common.exceptions.InstanceNotFoundException; import org.navalplanner.business.costcategories.entities.CostCategory; import org.navalplanner.business.costcategories.entities.HourCost; import org.navalplanner.business.costcategories.entities.ResourcesCostCategoryAssignment; @@ -39,6 +40,7 @@ import org.springframework.transaction.annotation.Transactional; /** * @author Jacobo Aragunde Perez + * @author Fernando Bellas Permuy */ @Repository @Scope(BeanDefinition.SCOPE_SINGLETON) @@ -56,6 +58,21 @@ public class CostCategoryDAO extends GenericDAOHibernate return list; } + @Override + public CostCategory findUniqueByName(String name) + throws InstanceNotFoundException { + Criteria c = getSession().createCriteria(CostCategory.class). + add(Restrictions.eq("name", name).ignoreCase()); + CostCategory costCategory = (CostCategory) c.uniqueResult(); + + if (costCategory == null) { + throw new InstanceNotFoundException(name, + CostCategory.class.getName()); + } else { + return costCategory; + } + } + @Transactional(readOnly = true) public static BigDecimal getPriceByResourceDateAndHourType( Resource resource, diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/daos/ICostCategoryDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/daos/ICostCategoryDAO.java index aad493536..aae6e98d3 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/daos/ICostCategoryDAO.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/daos/ICostCategoryDAO.java @@ -23,13 +23,17 @@ package org.navalplanner.business.costcategories.daos; import java.util.List; import org.navalplanner.business.common.daos.IGenericDAO; +import org.navalplanner.business.common.exceptions.InstanceNotFoundException; import org.navalplanner.business.costcategories.entities.CostCategory; /** * @author Jacobo Aragunde Perez + * @author Fernando Bellas Permuy */ public interface ICostCategoryDAO extends IGenericDAO { List findActive(); + CostCategory findUniqueByName(String name) throws InstanceNotFoundException; + } diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/entities/ResourcesCostCategoryAssignment.java b/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/entities/ResourcesCostCategoryAssignment.java index 611ae0c3b..8f1765ea9 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/entities/ResourcesCostCategoryAssignment.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/entities/ResourcesCostCategoryAssignment.java @@ -20,26 +20,30 @@ package org.navalplanner.business.costcategories.entities; +import static org.navalplanner.business.i18n.I18nHelper._; + +import org.apache.commons.lang.StringUtils; import org.hibernate.validator.AssertTrue; import org.hibernate.validator.NotNull; import org.joda.time.LocalDate; import org.navalplanner.business.common.BaseEntity; +import org.navalplanner.business.common.Registry; +import org.navalplanner.business.common.exceptions.CreateUnvalidatedException; +import org.navalplanner.business.common.exceptions.InstanceNotFoundException; import org.navalplanner.business.resources.entities.Resource; /** * @author Jacobo Aragunde Perez + * @author Fernando Bellas Permuy */ public class ResourcesCostCategoryAssignment extends BaseEntity { - @NotNull private LocalDate initDate; private LocalDate endDate; - @NotNull private CostCategory costCategory; - @NotNull private Resource resource; // Default constructor, needed by Hibernate @@ -51,6 +55,39 @@ public class ResourcesCostCategoryAssignment extends BaseEntity { return (ResourcesCostCategoryAssignment) create(new ResourcesCostCategoryAssignment()); } + public static ResourcesCostCategoryAssignment createUnvalidated( + String costCategoryName, Resource resource, LocalDate initDate, + LocalDate endDate) throws CreateUnvalidatedException { + + /* Get CostCategory. */ + if (StringUtils.isBlank(costCategoryName)) { + throw new CreateUnvalidatedException( + _("cost category name not specified")); + } + + CostCategory costCategory = null; + try { + costCategory = Registry.getCostCategoryDAO().findUniqueByName( + StringUtils.trim(costCategoryName)); + } catch (InstanceNotFoundException e) { + throw new CreateUnvalidatedException( + _("{0}: cost category does not exist", costCategoryName)); + } + + /* Create instance of ResourcesCostCategoryAssignment. */ + ResourcesCostCategoryAssignment assignment = + create(new ResourcesCostCategoryAssignment()); + + assignment.initDate = initDate; + assignment.endDate = endDate; + assignment.costCategory = costCategory; + assignment.resource = resource; + + return assignment; + + } + + @NotNull(message="cost assignment's start date not specified") public LocalDate getInitDate() { return initDate; } @@ -67,6 +104,7 @@ public class ResourcesCostCategoryAssignment extends BaseEntity { this.endDate = endDate; } + @NotNull(message="cost assignment's category not specified") public CostCategory getCostCategory() { return costCategory; } @@ -75,6 +113,7 @@ public class ResourcesCostCategoryAssignment extends BaseEntity { this.costCategory = category; } + @NotNull(message="cost assignment's resource not specified") public Resource getResource() { return resource; } @@ -90,12 +129,25 @@ public class ResourcesCostCategoryAssignment extends BaseEntity { } } - @AssertTrue(message="The end date cannot be before the init date") - public boolean checkPositiveTimeInterval() { + @AssertTrue(message="cost assignment with end date less than start date") + public boolean checkConstraintPositiveTimeInterval() { + + /* Check if it makes sense to check the constraint .*/ + if (!isInitDateSpecified()) { + return true; + } + + /* Check the constraint. */ if (endDate == null) { return true; } + return (endDate.isAfter(initDate) || initDate.equals(endDate)); + + } + + public boolean isInitDateSpecified() { + return initDate != null; } } diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/CriterionTypeDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/CriterionTypeDAO.java index 04f1b61b6..1ad2b38ca 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/CriterionTypeDAO.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/CriterionTypeDAO.java @@ -67,7 +67,7 @@ public class CriterionTypeDAO extends GenericDAOHibernate Criteria c = getSession().createCriteria(CriterionType.class); - c.add(Restrictions.eq("name", name)); + c.add(Restrictions.eq("name", name).ignoreCase()); CriterionType criterionType = (CriterionType) c.uniqueResult(); 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 c4f500b9d..64344904a 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 @@ -116,8 +116,8 @@ public class CriterionSatisfaction extends BaseEntity { /* Create instance of CriterionSatisfaction. */ CriterionSatisfaction criterionSatisfaction = - new CriterionSatisfaction(); - criterionSatisfaction.setNewObject(true); + create(new CriterionSatisfaction()); + criterionSatisfaction.criterion = criterion; criterionSatisfaction.resource = resource; criterionSatisfaction.startDate = startDate; 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 3c649b7fa..0f865126c 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 @@ -23,6 +23,7 @@ package org.navalplanner.business.resources.entities; import java.util.HashSet; import java.util.Set; +import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.EqualsBuilder; import org.hibernate.validator.AssertTrue; import org.hibernate.validator.NotEmpty; @@ -318,6 +319,12 @@ public class CriterionType extends BaseEntity implements @AssertTrue(message="criterion type name is already being used") public boolean checkConstraintUniqueCriterionTypeName() { + /* Check if it makes sense to check the constraint .*/ + if (!isNameSpecified()) { + return true; + } + + /* Check the constraint. */ ICriterionTypeDAO criterionTypeDAO = Registry.getCriterionTypeDAO(); if (isNewObject()) { @@ -365,4 +372,8 @@ public class CriterionType extends BaseEntity implements } + private boolean isNameSpecified() { + return !StringUtils.isBlank(name); + } + } 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 62a222954..8f4d7d09a 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 @@ -5,6 +5,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.Set; +import org.apache.commons.lang.StringUtils; import org.hibernate.validator.AssertTrue; import org.hibernate.validator.NotEmpty; import org.hibernate.validator.Valid; @@ -43,14 +44,14 @@ public class Machine extends Resource { configurationUnits.remove(unit); } - public static Machine createUnvalidated(String code, String name, String description) { + public static Machine createUnvalidated(String code, String name, + String description) { - Machine machine = new Machine(); + Machine machine = create(new Machine()); machine.code = code; machine.name = name; machine.description = description; - machine.setNewObject(true); return machine; @@ -108,6 +109,13 @@ public class Machine extends Resource { @AssertTrue(message="machine code has to be unique. It is already used") public boolean checkConstraintUniqueCode() { + + /* Check if it makes sense to check the constraint .*/ + if (!isCodeSpecified()) { + return true; + } + + /* Check the constraint. */ boolean result; if (isNewObject()) { result = !existsMachineWithTheCode(); @@ -115,6 +123,11 @@ public class Machine extends Resource { result = isIfExistsTheExistentMachineThisOne(); } return result; + + } + + private boolean isCodeSpecified() { + return !StringUtils.isBlank(code); } private boolean existsMachineWithTheCode() { 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 0e18ce012..4d5b3cd23 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 @@ -51,14 +51,6 @@ import org.navalplanner.business.common.exceptions.ValidationException; import org.navalplanner.business.costcategories.entities.ResourcesCostCategoryAssignment; import org.navalplanner.business.planner.entities.DayAssignment; -// FIXME: Alternatively, Resource can be modeled with the style: -// Resource.getParent() & Resource.getChilds(). This way, Resource does not -// depend on ResourceGroup. However, such an option allows combinations not -// semantically correct (e.g. a simple resource, such as Worker, could be the -// child another simple resource, general methods like getChilds() do not make -// sense for simple entities, etc.). In consequence, I prefer the modeling -// option shown below. - /** * This class acts as the base class for all resources. * @author Fernando Bellas Permuy @@ -822,8 +814,26 @@ public abstract class Resource extends BaseEntity{ assignment.setResource(null); } - @AssertFalse(message="Two assignments overlap in time") - public boolean checkAssignmentsOverlap() { + @AssertFalse(message="Some cost category assignments overlap in time") + public boolean checkConstraintAssignmentsOverlap() { + + /* + * Check if time intervals in cost assignments are correct in isolation. + * If not, it does not make sense to check assignment overlapping. + */ + for (ResourcesCostCategoryAssignment i : + getResourcesCostCategoryAssignments()) { + + if (!(i.isInitDateSpecified() && + i.checkConstraintPositiveTimeInterval())) { + return false; + } + + } + + /* + * Check assignment overlapping. + */ List assignmentsList = new ArrayList(); assignmentsList.addAll(getResourcesCostCategoryAssignments()); @@ -832,11 +842,6 @@ public abstract class Resource extends BaseEntity{ LocalDate endDate = assignmentsList.get(i).getEndDate(); for(int j=i+1; j=0 && - listElement.getEndDate().compareTo(endDate)<=0) || - (listElement.getInitDate().compareTo(initDate)>=0 && - listElement.getInitDate().compareTo(endDate)<=0))) { + ((listElement.getEndDate().compareTo(initDate)>=0 && // (1) listElement.getEndDate() inside [initDate, endDate] + listElement.getEndDate().compareTo(endDate)<=0) || + (listElement.getInitDate().compareTo(initDate)>=0 && // (2) listElement.getInitDate() inside [initDate, endDate] + listElement.getInitDate().compareTo(endDate)<=0) || + (listElement.getInitDate().compareTo(initDate)<=0 && // (3) [listElement.getInitDate(), listElement.getEndDate()] + listElement.getEndDate().compareTo(endDate)>=0))) { // contains [initDate, endDate] return true; } } } return false; + } public boolean isVirtual() { return false; } - @AssertTrue(message="there are criterion satisfactions referring to " + + @AssertTrue(message="there exist criterion satisfactions referring to " + "criterion types not applicable to this resource") public boolean checkConstraintCriterionSatisfactionsWithCorrectType() { 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 02958898c..aca6bd991 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 @@ -50,12 +50,11 @@ public class Worker extends Resource { public static Worker createUnvalidated(String firstName, String surname, String nif) { - Worker worker = new Worker(); + Worker worker = create(new Worker()); worker.firstName = firstName; worker.surname = surname; worker.nif = nif; - worker.setNewObject(true); return worker; @@ -131,14 +130,16 @@ public class Worker extends Resource { @AssertTrue(message = "Worker with the same first name, surname and nif previously existed") public boolean checkConstraintUniqueFirstName() { - if (!firstLevelValidationsPassed()) { - return true; - } - + /* Check if it makes sense to check the constraint .*/ if (this instanceof VirtualWorker) { return true; } + if (!areFirstNameSurnameNifSpecified()) { + return true; + } + + /* Check the constraint. */ List list = Registry.getWorkerDAO() .findByFirstNameSecondNameAndNifAnotherTransaction(firstName, surname, nif); @@ -155,7 +156,7 @@ public class Worker extends Resource { } - private boolean firstLevelValidationsPassed() { + private boolean areFirstNameSurnameNifSpecified() { return !StringUtils.isBlank(firstName) && !StringUtils.isBlank(surname) && diff --git a/navalplanner-business/src/main/resources/org/navalplanner/business/orders/entities/Orders.hbm.xml b/navalplanner-business/src/main/resources/org/navalplanner/business/orders/entities/Orders.hbm.xml index 77c0bd054..1ca8c46fb 100644 --- a/navalplanner-business/src/main/resources/org/navalplanner/business/orders/entities/Orders.hbm.xml +++ b/navalplanner-business/src/main/resources/org/navalplanner/business/orders/entities/Orders.hbm.xml @@ -49,7 +49,7 @@ - + @@ -113,7 +113,8 @@ + not-null="true" + class="org.navalplanner.business.orders.entities.OrderLine"/> 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 2be59df5f..95c027ca1 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 @@ -20,6 +20,9 @@ package org.navalplanner.ws.common.api; +import java.io.PrintWriter; +import java.io.StringWriter; + import javax.xml.bind.annotation.XmlAttribute; /** @@ -29,10 +32,13 @@ import javax.xml.bind.annotation.XmlAttribute; */ public class ConstraintViolationDTO { - @XmlAttribute(name="field-name") + public final static String FIELD_NAME_ATTRIBUTE_NAME = "field-name"; + public final static String MESSAGE_ATTRIBUTE_NAME = "message"; + + @XmlAttribute(name=FIELD_NAME_ATTRIBUTE_NAME) public String fieldName; - @XmlAttribute + @XmlAttribute(name=MESSAGE_ATTRIBUTE_NAME) public String message; public ConstraintViolationDTO() {} @@ -42,4 +48,21 @@ public class ConstraintViolationDTO { this.message = message; } + @Override + public String toString() { + + StringWriter stringWriter = new StringWriter(); + PrintWriter printWriter = new PrintWriter(stringWriter); + + if (fieldName != null) { + printWriter.print(FIELD_NAME_ATTRIBUTE_NAME + " = " + fieldName + + " - "); + } + printWriter.println(MESSAGE_ATTRIBUTE_NAME + " = " + message); + printWriter.close(); + + return stringWriter.toString(); + + } + } 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 1ea323ea5..728497806 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,8 @@ package org.navalplanner.ws.common.api; +import java.io.PrintWriter; +import java.io.StringWriter; import java.util.ArrayList; import java.util.List; @@ -33,7 +35,9 @@ import javax.xml.bind.annotation.XmlElement; */ public class InstanceConstraintViolationsDTO { - @XmlAttribute(name="instance-id") + public final static String INSTANCE_ID_ATTRIBUTE_NAME = "instance-id"; + + @XmlAttribute(name=INSTANCE_ID_ATTRIBUTE_NAME) public String instanceId; @XmlElement(name="constraint-violation") @@ -62,4 +66,23 @@ public class InstanceConstraintViolationsDTO { } + @Override + public String toString() { + + StringWriter stringWriter = new StringWriter(); + PrintWriter printWriter = new PrintWriter(stringWriter); + + printWriter.println("** " + INSTANCE_ID_ATTRIBUTE_NAME + " = " + + instanceId + " **"); + + for (ConstraintViolationDTO i : constraintViolations) { + printWriter.println(i); + } + + printWriter.close(); + + return stringWriter.toString(); + + } + } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/InstanceConstraintViolationsListDTO.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/InstanceConstraintViolationsListDTO.java index 73ac3d837..c712714a5 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/InstanceConstraintViolationsListDTO.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/InstanceConstraintViolationsListDTO.java @@ -20,6 +20,8 @@ package org.navalplanner.ws.common.api; +import java.io.PrintWriter; +import java.io.StringWriter; import java.util.List; import javax.xml.bind.annotation.XmlElement; @@ -48,4 +50,25 @@ public class InstanceConstraintViolationsListDTO { } + @Override + public String toString() { + + StringWriter stringWriter = new StringWriter(); + PrintWriter printWriter = new PrintWriter(stringWriter); + + printWriter.println("*** " + this.getClass().getName() + " ***"); + + for (InstanceConstraintViolationsDTO i : + instanceConstraintViolationsList) { + + printWriter.println(i); + + } + + printWriter.close(); + + return stringWriter.toString(); + + } + } 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 index 7ab1299e1..627368fb9 100644 --- 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 @@ -20,14 +20,12 @@ 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; +import org.joda.time.LocalDate; + /** * A converter from java.util.Date to/from * javax.xml.datatype.XMLGregorianCalendar. @@ -38,53 +36,6 @@ 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), - convertMonthFieldFromCalendarToXMLGregorianCalendar( - dateAsCalendar.get(Calendar.MONTH)), - dateAsCalendar.get(Calendar.DAY_OF_MONTH), - DatatypeConstants.FIELD_UNDEFINED); - } catch (DatatypeConfigurationException e) { - throw new RuntimeException(e); - } - - return dateAsXMLGregorianCalendar; - - } - - /** - * Converts from @{link Calendar} month field format to - * @{link XMLGregorianCalendar} format. - * - * It is needed the conversion because - * @{link XMLGregorianCalendar} months go from 1 to 12 while - * @{link Calendar} months go from 0 to 11 - * - */ - private final static int convertMonthFieldFromCalendarToXMLGregorianCalendar(int month) { - return month+1; - } - /** * It converts a XMLGregorianCalendar representing a * xsd:date XML type to a Date.

@@ -102,4 +53,23 @@ public class DateConverter { } + /** + * It converts a XMLGregorianCalendar representing a + * xsd:date XML type to a Joda's LocalDate. + *

+ * + * If the date passed as a parameter is null, it also returns + * null. + */ + public final static LocalDate toLocalDate(XMLGregorianCalendar date) { + + if (date == null) { + return null; + } else { + return new LocalDate(date.getYear(), date.getMonth(), + date.getDay()); + } + + } + } 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 index 1ae9b064f..327f47eff 100644 --- 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 @@ -20,14 +20,10 @@ 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. * @@ -45,19 +41,20 @@ public class CriterionSatisfactionDTO { @XmlSchemaType(name="date") public XMLGregorianCalendar startDate; - @XmlAttribute(name="finish-date") + @XmlAttribute(name="end-date") @XmlSchemaType(name="date") - public XMLGregorianCalendar finishDate; + public XMLGregorianCalendar endDate; public CriterionSatisfactionDTO() {} - public CriterionSatisfactionDTO(String criterionTypeName, - String criterionName, Date startDate, Date finishDate) { + public CriterionSatisfactionDTO( + String criterionTypeName, String criterionName, + XMLGregorianCalendar startDate, XMLGregorianCalendar endDate) { this.criterionTypeName = criterionTypeName; this.criterionName = criterionName; - this.startDate = DateConverter.toXMLGregrorianCalendar(startDate); - this.finishDate = DateConverter.toXMLGregrorianCalendar(finishDate); + this.startDate = startDate; + this.endDate = endDate; } 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 c2fba8c14..35f87180b 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 @@ -42,4 +42,10 @@ public abstract class ResourceDTO { public List criterionSatisfactions = new ArrayList(); + @XmlElementWrapper(name="resources-cost-category-assignment-list") + @XmlElement(name="resources-cost-category-assignment") + public List + resourcesCostCategoryAssignments = + new ArrayList(); + } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/api/ResourcesCostCategoryAssignmentDTO.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/api/ResourcesCostCategoryAssignmentDTO.java new file mode 100644 index 000000000..dc3e063bd --- /dev/null +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/resources/api/ResourcesCostCategoryAssignmentDTO.java @@ -0,0 +1,55 @@ +/* + * 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 javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.datatype.XMLGregorianCalendar; + +/** + * DTO for ResourcesCostCategoryAssignment entity. + * + * @author Fernando Bellas Permuy + */ +public class ResourcesCostCategoryAssignmentDTO { + + @XmlAttribute(name="cost-category-name") + public String costCategoryName; + + @XmlAttribute(name="start-date") + @XmlSchemaType(name="date") + public XMLGregorianCalendar startDate; + + @XmlAttribute(name="end-date") + @XmlSchemaType(name="date") + public XMLGregorianCalendar endDate; + + public ResourcesCostCategoryAssignmentDTO() {} + + public ResourcesCostCategoryAssignmentDTO(String costCategoryName, + XMLGregorianCalendar startDate, XMLGregorianCalendar endDate) { + + this.costCategoryName = costCategoryName; + this.startDate = startDate; + this.endDate = endDate; + + } + +} 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 b0c54e74e..e6fed52fb 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 @@ -28,6 +28,7 @@ import org.apache.commons.lang.StringUtils; import org.navalplanner.business.common.exceptions.CreateUnvalidatedException; import org.navalplanner.business.common.exceptions.InstanceNotFoundException; import org.navalplanner.business.common.exceptions.MultipleInstancesException; +import org.navalplanner.business.costcategories.entities.ResourcesCostCategoryAssignment; import org.navalplanner.business.resources.entities.CriterionSatisfaction; import org.navalplanner.business.resources.entities.Machine; import org.navalplanner.business.resources.entities.Resource; @@ -36,6 +37,7 @@ 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.ResourcesCostCategoryAssignmentDTO; import org.navalplanner.ws.resources.api.WorkerDTO; /** @@ -65,6 +67,8 @@ public class ResourceConverter { addCriterionSatisfactions(resource, resourceDTO.criterionSatisfactions); setResourceCalendar(resource, resourceDTO.calendarName); + addResourcesCostCategoryAssignments(resource, + resourceDTO.resourcesCostCategoryAssignments); return resource; @@ -109,7 +113,7 @@ public class ResourceConverter { StringUtils.trim(criterionSatisfactionDTO.criterionName), resource, DateConverter.toDate(criterionSatisfactionDTO.startDate), - DateConverter.toDate(criterionSatisfactionDTO.finishDate)); + DateConverter.toDate(criterionSatisfactionDTO.endDate)); } @@ -129,4 +133,31 @@ public class ResourceConverter { } + private static void addResourcesCostCategoryAssignments( + Resource resource, List + resourcesCostCategoryAssignments) + throws CreateUnvalidatedException { + + for (ResourcesCostCategoryAssignmentDTO assignmentDTO : + resourcesCostCategoryAssignments) { + + ResourcesCostCategoryAssignment assignment = toEntity(assignmentDTO, + resource); + resource.addResourcesCostCategoryAssignment(assignment); + + } + + } + + private static ResourcesCostCategoryAssignment toEntity( + ResourcesCostCategoryAssignmentDTO assignmentDTO, Resource resource) + throws CreateUnvalidatedException { + + return ResourcesCostCategoryAssignment.createUnvalidated( + assignmentDTO.costCategoryName, resource, + DateConverter.toLocalDate(assignmentDTO.startDate), + DateConverter.toLocalDate(assignmentDTO.endDate)); + + } + } 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 99ef7a5d3..62384f574 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 @@ -29,10 +29,14 @@ 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 javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeConstants; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -43,6 +47,8 @@ import org.navalplanner.business.common.IOnTransaction; import org.navalplanner.business.common.daos.IConfigurationDAO; import org.navalplanner.business.common.entities.IConfigurationBootstrap; import org.navalplanner.business.common.exceptions.InstanceNotFoundException; +import org.navalplanner.business.costcategories.daos.ICostCategoryDAO; +import org.navalplanner.business.costcategories.entities.CostCategory; import org.navalplanner.business.resources.daos.ICriterionTypeDAO; import org.navalplanner.business.resources.daos.IMachineDAO; import org.navalplanner.business.resources.daos.IResourceDAO; @@ -61,6 +67,7 @@ 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.ResourcesCostCategoryAssignmentDTO; import org.navalplanner.ws.resources.api.WorkerDTO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.NotTransactional; @@ -100,6 +107,9 @@ public class ResourceServiceTest { @Autowired private IBaseCalendarDAO baseCalendarDAO; + @Autowired + private ICostCategoryDAO costCategoryDAO; + @Autowired private IConfigurationBootstrap configurationBootstrap; @@ -135,10 +145,18 @@ public class ResourceServiceTest { resourceService.addResources(createResourceListDTO(m1, m2, w1, w2)). instanceConstraintViolationsList; - assertTrue(instanceConstraintViolationsList.size() == 2); - assertTrue(instanceConstraintViolationsList.get(0). + assertTrue( + instanceConstraintViolationsList.toString(), + instanceConstraintViolationsList.size() == 2); + assertTrue( + instanceConstraintViolationsList.get(0). + constraintViolations.toString(), + instanceConstraintViolationsList.get(0). constraintViolations.size() == 2); // m2 constraint violations. - assertTrue(instanceConstraintViolationsList.get(1). + assertTrue( + instanceConstraintViolationsList.get(1). + constraintViolations.toString(), + instanceConstraintViolationsList.get(1). constraintViolations.size() == 3); // w2 constraint violations. machineDAO.findUniqueByCode(m1Code.trim()); assertTrue( @@ -208,10 +226,18 @@ public class ResourceServiceTest { resourceService.addResources(createResourceListDTO(m1, m2, w1, w2)). instanceConstraintViolationsList; - assertTrue(instanceConstraintViolationsList.size() == 2); - assertTrue(instanceConstraintViolationsList.get(0). + assertTrue( + instanceConstraintViolationsList.toString(), + instanceConstraintViolationsList.size() == 2); + assertTrue( + instanceConstraintViolationsList.get(0). + constraintViolations.toString(), + instanceConstraintViolationsList.get(0). constraintViolations.size() == 1); - assertTrue(instanceConstraintViolationsList.get(1). + assertTrue( + instanceConstraintViolationsList.get(1). + constraintViolations.toString(), + instanceConstraintViolationsList.get(1). constraintViolations.size() == 1); machineDAO.findUniqueByCode(m1.code); assertTrue( @@ -232,19 +258,22 @@ public class ResourceServiceTest { MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc"); machineDTO.criterionSatisfactions.add( new CriterionSatisfactionDTO( - ' ' + ct.getName() + ' ', " c1 ", // Blank spaces intentionally - // added (OK). - Calendar.getInstance().getTime(), null)); + ' ' + ct.getName().toUpperCase() + // Upper case and blank + ' ', " C1 ", // spaces intentionally + // added (OK). + getDate(2001, 1, 1), null)); machineDTO.criterionSatisfactions.add( new CriterionSatisfactionDTO(ct.getName(), "c2", - Calendar.getInstance().getTime(), null)); + getDate(2001, 1, 1), null)); /* Test. */ List instanceConstraintViolationsList = resourceService.addResources(createResourceListDTO(machineDTO)). instanceConstraintViolationsList; - assertTrue(instanceConstraintViolationsList.isEmpty()); + assertTrue( + instanceConstraintViolationsList.toString(), + instanceConstraintViolationsList.isEmpty()); Machine machine = findUniqueMachineByCodeInitialized(machineDTO.code); assertTrue(machine.getCriterionSatisfactions().size() == 2); @@ -269,7 +298,7 @@ public class ResourceServiceTest { MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc"); machineDTO.criterionSatisfactions.add( new CriterionSatisfactionDTO(ct.getName() , "c1", - null, Calendar.getInstance().getTime())); // Missing start date. + null, getDate(2001, 1, 1))); // Missing start date. /* Test. */ assertOneConstraintViolation( @@ -281,7 +310,7 @@ public class ResourceServiceTest { @Test @NotTransactional - public void testAddResourceWithCriterionSatisfactionsWithIncorrectType() { + public void testAddResourcesWithCriterionSatisfactionsWithIncorrectType() { /* Create two criterion types. */ CriterionType machineCt = createCriterionType(ResourceEnum.MACHINE); @@ -291,11 +320,11 @@ public class ResourceServiceTest { MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc"); machineDTO.criterionSatisfactions.add( new CriterionSatisfactionDTO(workerCt.getName() , "c1", - Calendar.getInstance().getTime(), null)); // Incorrect type. + getDate(2001, 1, 1), null)); // Incorrect type. WorkerDTO workerDTO = new WorkerDTO(getUniqueName(), "surname", "nif"); workerDTO.criterionSatisfactions.add( new CriterionSatisfactionDTO(machineCt.getName() , "c1", - Calendar.getInstance().getTime(), null)); // Incorrect type. + getDate(2001, 1, 1), null)); // Incorrect type. /* Test. */ assertOneConstraintViolation( @@ -311,53 +340,45 @@ public class ResourceServiceTest { @Test @NotTransactional - public void testAddResourceWithCriterionSatisfactionsWithIncorrectNames() { + public void testAddResourcesWithCriterionSatisfactionsWithIncorrectNames() { /* Create a criterion type. */ CriterionType ct = createCriterionType(); /* Create machines DTOs. */ - MachineDTO m1 = new MachineDTO(getUniqueName(), "name", "desc"); + MachineDTO m1 = new MachineDTO(getUniqueName(), "m1", "desc"); m1.criterionSatisfactions.add( new CriterionSatisfactionDTO("", "X", // Missing criterion type. - Calendar.getInstance().getTime(), null)); - MachineDTO m2 = new MachineDTO(getUniqueName(), "name", "desc"); + getDate(2001, 1, 1), null)); + MachineDTO m2 = new MachineDTO(getUniqueName(), "m2", "desc"); m2.criterionSatisfactions.add( new CriterionSatisfactionDTO(ct.getName(), // Missing criterion. - null, Calendar.getInstance().getTime(), null)); - MachineDTO m3 = new MachineDTO(getUniqueName(), "name", "desc"); + null, getDate(2001, 1, 1), null)); + MachineDTO m3 = new MachineDTO(getUniqueName(), "m3", "desc"); m3.criterionSatisfactions.add( new CriterionSatisfactionDTO( ct.getName() + 'X', // Non-existent criterion type. - "c1", Calendar.getInstance().getTime(), null)); - MachineDTO m4 = new MachineDTO(getUniqueName(), "name", "desc"); + "c1", getDate(2001, 1, 1), null)); + MachineDTO m4 = new MachineDTO(getUniqueName(), "m4", "desc"); m4.criterionSatisfactions.add( new CriterionSatisfactionDTO( ct.getName(), "c1" + 'X', // Criterion name is not of ct's type. - Calendar.getInstance().getTime(), null)); + getDate(2001, 1, 1), null)); /* Test. */ - List machines = new ArrayList(); - machines.add(m1); - machines.add(m2); - machines.add(m3); - machines.add(m4); + ResourceListDTO resourceDTOs = createResourceListDTO(m1, m2, m3, m4); - List instanceConstraintViolationsList = - resourceService.addResources(new ResourceListDTO(machines)). - instanceConstraintViolationsList; + assertOneConstraintViolationPerInstance( + resourceService.addResources(resourceDTOs), + resourceDTOs.resources.size()); - assertTrue(instanceConstraintViolationsList.size() == machines.size()); - - for (InstanceConstraintViolationsDTO i : - instanceConstraintViolationsList) { - assertTrue(i.constraintViolations.size() == 1); - } - - for (MachineDTO m : machines) { + for (ResourceDTO r : resourceDTOs.resources) { + MachineDTO m = (MachineDTO) r; assertFalse( - machineDAO.existsMachineWithCodeInAnotherTransaction(m.code)); + "Machine " + m.name + " not expected", + machineDAO.existsMachineWithCodeInAnotherTransaction( + ((MachineDTO) r).code)); } } @@ -418,6 +439,183 @@ public class ResourceServiceTest { } + @Test + @NotTransactional + public void testAddResourceWithCostAssignments() { + + /* Create a CostCategory. */ + CostCategory costCategory = createCostCategory(); + + /* Create resource DTOs. */ + MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc"); + machineDTO.resourcesCostCategoryAssignments.add( + new ResourcesCostCategoryAssignmentDTO( + ' ' + costCategory.getName().toUpperCase() + ' ', + getDate(2001, 1, 1), null)); + machineDTO.resourcesCostCategoryAssignments.add( + new ResourcesCostCategoryAssignmentDTO( + costCategory.getName(), + getDate(2000, 1, 1), getDate(2000, 4, 1))); + + /* Test. */ + assertNoConstraintViolations( + resourceService.addResources(createResourceListDTO(machineDTO))); + assertTrue(machineDAO.existsMachineWithCodeInAnotherTransaction( + machineDTO.code)); + + } + + @Test + @NotTransactional + public void testAddResourcesWithCostAssignmentWithIncorrectCategoryNames() { + + /* Create a resource DTOs. */ + MachineDTO m1 = new MachineDTO(getUniqueName(), "m1", "desc"); + m1.resourcesCostCategoryAssignments.add( + new ResourcesCostCategoryAssignmentDTO( + null, // Cost category not specified. + getDate(2000, 1, 1), null)); + + MachineDTO m2 = new MachineDTO(getUniqueName(), "m2", "desc"); + m2.resourcesCostCategoryAssignments.add( + new ResourcesCostCategoryAssignmentDTO( + getUniqueName(), // Non-existent cost category. + getDate(2000, 1, 1), null)); + + /* Test. */ + ResourceListDTO resourceDTOs = createResourceListDTO(m1, m2); + + assertOneConstraintViolationPerInstance( + resourceService.addResources(resourceDTOs), + resourceDTOs.resources.size()); + + for (ResourceDTO r : resourceDTOs.resources) { + MachineDTO m = (MachineDTO) r; + assertFalse( + "Machine " + m.name + " not expected", + machineDAO.existsMachineWithCodeInAnotherTransaction(m.code)); + }; + + } + + @Test + @NotTransactional + public void testAddResourceWithCostAssignmentWithoutStartDate() { + + /* Create a CostCategory. */ + CostCategory costCategory = createCostCategory(); + + /* Create a resource DTO. */ + MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc"); + machineDTO.resourcesCostCategoryAssignments.add( + new ResourcesCostCategoryAssignmentDTO( + costCategory.getName(), null, // Start date not specified. + getDate(2000, 1, 1))); + + /* Test. */ + assertOneConstraintViolation( + resourceService.addResources(createResourceListDTO(machineDTO))); + assertFalse(machineDAO.existsMachineWithCodeInAnotherTransaction( + machineDTO.code)); + + } + + @Test + @NotTransactional + public void testAddResourceWithCostAssignmentWithNegativeInterval() { + + /* Create a CostCategory. */ + CostCategory costCategory = createCostCategory(); + + /* Create a resource DTO. */ + MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc"); + machineDTO.resourcesCostCategoryAssignments.add( + new ResourcesCostCategoryAssignmentDTO( + costCategory.getName(), + getDate(2000, 2, 1), getDate(2000, 1, 1))); + + /* Test. */ + assertOneConstraintViolation( + resourceService.addResources(createResourceListDTO(machineDTO))); + assertFalse(machineDAO.existsMachineWithCodeInAnotherTransaction( + machineDTO.code)); + + } + + @Test + @NotTransactional + public void testAddResourcesWithOverlappingInCostAssignments() { + + /* Create a CostCategory. */ + CostCategory costCategory = createCostCategory(); + + /* + * Create a resource DTOs. Each resource contains one cost assignment + * overlapping. + */ + MachineDTO m1 = createMachineDTOWithTwoCostsAssignments( + "m1", costCategory.getName(), + getDate(2000, 1, 1), null, + getDate(2000, 2, 1), null); + + MachineDTO m2 = createMachineDTOWithTwoCostsAssignments( + "m2", costCategory.getName(), + getDate(2000, 2, 1), null, + getDate(2000, 1, 1), getDate(2000, 3, 1)); + + MachineDTO m3 = createMachineDTOWithTwoCostsAssignments( + "m3", costCategory.getName(), + getDate(2000, 2, 1), getDate(2000, 4, 1), + getDate(2000, 3, 1), null); + + MachineDTO m4 = createMachineDTOWithTwoCostsAssignments( + "m4", costCategory.getName(), + getDate(2000, 2, 1), getDate(2000, 5, 1), + getDate(2000, 1, 1), getDate(2000, 3, 1)); + + MachineDTO m5 = createMachineDTOWithTwoCostsAssignments( + "m5", costCategory.getName(), + getDate(2000, 2, 1), getDate(2000, 5, 1), + getDate(2000, 3, 1), getDate(2000, 4, 1)); + + MachineDTO m6 = createMachineDTOWithTwoCostsAssignments( + "m6", costCategory.getName(), + getDate(2000, 2, 1), getDate(2000, 5, 1), + getDate(2000, 4, 1), getDate(2000, 6, 1)); + + MachineDTO m7 = createMachineDTOWithTwoCostsAssignments( + "m7", costCategory.getName(), + getDate(2000, 2, 1), getDate(2000, 5, 1), + getDate(2000, 1, 1), getDate(2000, 2, 1)); + + MachineDTO m8 = createMachineDTOWithTwoCostsAssignments( + "m8", costCategory.getName(), + getDate(2000, 2, 1), getDate(2000, 5, 1), + getDate(2000, 5, 1), getDate(2000, 6, 1)); + + MachineDTO m9 = createMachineDTOWithTwoCostsAssignments( + "m9", costCategory.getName(), + getDate(2000, 2, 1), getDate(2000, 5, 1), + getDate(2000, 2, 1), getDate(2000, 5, 1)); + + /* Test. */ + ResourceListDTO resourceDTOs = createResourceListDTO( + m1, m2, m3, m4, m5, m6, m7, m8, m9); + + assertOneConstraintViolationPerInstance( + resourceService.addResources(resourceDTOs), + resourceDTOs.resources.size()); + + for (ResourceDTO r : resourceDTOs.resources) { + MachineDTO m = (MachineDTO) r; + assertFalse( + "Machine " + m.name + " not expected", + machineDAO.existsMachineWithCodeInAnotherTransaction( + ((MachineDTO) r).code)); + } + + } + private CriterionType createCriterionType() { return createCriterionType(ResourceEnum.RESOURCE); } @@ -501,7 +699,7 @@ public class ResourceServiceTest { } - public BaseCalendar getDefaultCalendar() { + private BaseCalendar getDefaultCalendar() { IOnTransaction find = new IOnTransaction() { @@ -546,11 +744,51 @@ public class ResourceServiceTest { } + private CostCategory createCostCategory() { + + IOnTransaction create = + new IOnTransaction() { + + @Override + public CostCategory execute() { + CostCategory costCategory = + CostCategory.create(getUniqueName()); + costCategoryDAO.save(costCategory); + return costCategory; + } + }; + + return transactionService.runOnTransaction(create); + + } + + private MachineDTO createMachineDTOWithTwoCostsAssignments( + String machineName, String costCategoryName, + XMLGregorianCalendar startDate1, XMLGregorianCalendar endDate1, + XMLGregorianCalendar startDate2, XMLGregorianCalendar endDate2) { + + MachineDTO machineDTO = new MachineDTO(getUniqueName(), machineName, + "desc"); + + machineDTO.resourcesCostCategoryAssignments.add( + new ResourcesCostCategoryAssignmentDTO( + costCategoryName, startDate1, endDate1)); + machineDTO.resourcesCostCategoryAssignments.add( + new ResourcesCostCategoryAssignmentDTO( + costCategoryName, startDate2, endDate2)); + + return machineDTO; + + } + private void assertNoConstraintViolations( InstanceConstraintViolationsListDTO instanceConstraintViolationsListDTO) { - assertTrue(instanceConstraintViolationsListDTO. + assertTrue( + instanceConstraintViolationsListDTO. + instanceConstraintViolationsList.toString(), + instanceConstraintViolationsListDTO. instanceConstraintViolationsList.size() == 0); } @@ -563,9 +801,46 @@ public class ResourceServiceTest { instanceConstraintViolationsListDTO. instanceConstraintViolationsList; - assertTrue(instanceConstraintViolationsList.size() == 1); - assertTrue(instanceConstraintViolationsList.get(0). - constraintViolations.size() == 1); + assertTrue( + instanceConstraintViolationsList.toString(), + instanceConstraintViolationsList.size() == 1); + assertTrue( + instanceConstraintViolationsList.get(0). + constraintViolations.toString(), + instanceConstraintViolationsList.get(0). + constraintViolations.size() == 1); + + } + + private void assertOneConstraintViolationPerInstance( + InstanceConstraintViolationsListDTO + instanceConstraintViolationsListDTO, int numberOfInstances) { + + List instanceConstraintViolationsList = + instanceConstraintViolationsListDTO. + instanceConstraintViolationsList; + + assertTrue( + instanceConstraintViolationsList.toString(), + instanceConstraintViolationsList.size() == numberOfInstances); + + for (InstanceConstraintViolationsDTO i : + instanceConstraintViolationsList) { + assertTrue( + i.constraintViolations.toString(), + i.constraintViolations.size() == 1); + } + + } + + private XMLGregorianCalendar getDate(int year, int month, int day) { + + try { + return DatatypeFactory.newInstance().newXMLGregorianCalendarDate( + year, month, day, DatatypeConstants.FIELD_UNDEFINED); + } catch (DatatypeConfigurationException e) { + throw new RuntimeException(e); + } } diff --git a/scripts/rest-clients/README b/scripts/rest-clients/README index 394b15daa..64adc0dd4 100644 --- a/scripts/rest-clients/README +++ b/scripts/rest-clients/README @@ -22,7 +22,7 @@ * Import resources: - - import-resources.sh resources-sample.xml + - import-resources.sh resources-sample-mini.xml (or resources-sample.xml) (authenticate with wswriter/wswriter) - Check the returned errors are consistent with the comments in diff --git a/scripts/rest-clients/resources-sample-mini.xml b/scripts/rest-clients/resources-sample-mini.xml new file mode 100644 index 000000000..a07fd00d4 --- /dev/null +++ b/scripts/rest-clients/resources-sample-mini.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/rest-clients/resources-sample.xml b/scripts/rest-clients/resources-sample.xml index 11646379f..dba584c89 100644 --- a/scripts/rest-clients/resources-sample.xml +++ b/scripts/rest-clients/resources-sample.xml @@ -1,5 +1,10 @@ + + @@ -17,16 +22,62 @@ criterion-type-name="WORK_RELATIONSHIP" criterion-name="hiredResourceWorkingRelationship" start-date="2009-01-01" - finish-date=""/> + end-date=""/> - + + calendar-name="TestCalendar"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -37,12 +88,12 @@ criterion-type-name="WORK_RELATIONSHIP" criterion-name="hiredResourceWorkingRelationship" start-date="2009-01-01" - finish-date=""/> + end-date=""/> + end-date="2009-12-25"/>
@@ -55,7 +106,7 @@ + end-date="2009-12-25"/> @@ -66,7 +117,7 @@ criterion-type-name="WORK_RELATIONSHIP_XXX" criterion-name="hiredResourceWorkingRelationship" start-date="2009-01-01" - finish-date=""/> + end-date=""/> @@ -77,7 +128,7 @@ criterion-type-name="WORK_RELATIONSHIP" criterion-name="hiredResourceWorkingRelationshipXXX" start-date="2009-01-01" - finish-date=""/> + end-date=""/> @@ -87,7 +138,7 @@ + end-date=""/> @@ -97,7 +148,7 @@ + end-date=""/> @@ -105,8 +156,34 @@ and nif. --> - + + calendar-name="TestCalendar" /> + + + + + + + + + + + +