diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/calendars/daos/BaseCalendarDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/calendars/daos/BaseCalendarDAO.java index 09086c6a8..5a1621763 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/calendars/daos/BaseCalendarDAO.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/calendars/daos/BaseCalendarDAO.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import org.apache.commons.lang.StringUtils; import org.hibernate.Criteria; import org.hibernate.criterion.Restrictions; import org.navalplanner.business.calendars.entities.BaseCalendar; @@ -39,6 +40,7 @@ import org.springframework.transaction.annotation.Transactional; * DAO for {@link BaseCalendar} * * @author Manuel Rego Casasnovas + * @author Fernando Bellas Permuy */ @Repository @Scope(BeanDefinition.SCOPE_SINGLETON) @@ -88,8 +90,13 @@ public class BaseCalendarDAO extends GenericDAOHibernate @Override public List findByName(String name) { + + if (StringUtils.isBlank(name)) { + return new ArrayList(); + } + Criteria c = getSession().createCriteria(BaseCalendar.class); - c.add(Restrictions.eq("name", name)); + c.add(Restrictions.eq("name", name).ignoreCase()); List list = (List) c.list(); removeResourceCalendarInstances(list); diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/common/exceptions/MultipleInstancesException.java b/navalplanner-business/src/main/java/org/navalplanner/business/common/exceptions/MultipleInstancesException.java new file mode 100644 index 000000000..ace4f8dd6 --- /dev/null +++ b/navalplanner-business/src/main/java/org/navalplanner/business/common/exceptions/MultipleInstancesException.java @@ -0,0 +1,37 @@ +/* + * 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 for specifying that there exist multiple persistent instances + * with the same "logic" identifier (e.g. a name). + * + * @author Fernando Bellas Permuy + */ +@SuppressWarnings("serial") +public class MultipleInstancesException extends InstanceException { + + public MultipleInstancesException(String logicId, String className) { + super("Multiple instances with the same logic identifier", + logicId, className); + } + +} 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 82bebfe93..0e18ce012 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 @@ -31,6 +31,7 @@ import java.util.ListIterator; import java.util.Map; import java.util.Set; +import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.Validate; import org.hibernate.validator.AssertFalse; import org.hibernate.validator.AssertTrue; @@ -38,10 +39,14 @@ import org.hibernate.validator.InvalidValue; import org.hibernate.validator.Valid; import org.joda.time.Days; import org.joda.time.LocalDate; +import org.navalplanner.business.calendars.entities.BaseCalendar; import org.navalplanner.business.calendars.entities.IWorkHours; import org.navalplanner.business.calendars.entities.ResourceCalendar; import org.navalplanner.business.calendars.entities.SameWorkHoursEveryDay; import org.navalplanner.business.common.BaseEntity; +import org.navalplanner.business.common.Registry; +import org.navalplanner.business.common.exceptions.InstanceNotFoundException; +import org.navalplanner.business.common.exceptions.MultipleInstancesException; import org.navalplanner.business.common.exceptions.ValidationException; import org.navalplanner.business.costcategories.entities.ResourcesCostCategoryAssignment; import org.navalplanner.business.planner.entities.DayAssignment; @@ -659,6 +664,37 @@ public abstract class Resource extends BaseEntity{ return calendar; } + public void setResourceCalendar(String calendarName) + throws InstanceNotFoundException, MultipleInstancesException { + + ResourceCalendar calendar; + + if (StringUtils.isBlank(calendarName)) { + + calendar = Registry.getConfigurationDAO().getConfiguration(). + getDefaultCalendar().newDerivedResourceCalendar(); + + } else { + + List baseCalendars = Registry.getBaseCalendarDAO(). + findByName(StringUtils.trim(calendarName)); + + if (baseCalendars.isEmpty()) { + throw new InstanceNotFoundException(calendarName, + BaseCalendar.class.getName()); + } if (baseCalendars.size() > 1) { + throw new MultipleInstancesException(calendarName, + BaseCalendar.class.getName()); + } else { + calendar = baseCalendars.get(0).newDerivedResourceCalendar(); + } + + } + + setCalendar(calendar); + + } + public int getAssignedHours(LocalDate localDate) { int sum = 0; for (DayAssignment dayAssignment : getAssignmentsForDay(localDate)) { 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 a14a561aa..c2fba8c14 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 @@ -23,6 +23,7 @@ package org.navalplanner.ws.resources.api; import java.util.ArrayList; import java.util.List; +import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; @@ -33,6 +34,9 @@ import javax.xml.bind.annotation.XmlElementWrapper; */ public abstract class ResourceDTO { + @XmlAttribute(name="calendar-name") + public String calendarName; + @XmlElementWrapper(name="criterion-satisfaction-list") @XmlElement(name="criterion-satisfaction") public List criterionSatisfactions = 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 a6e79468c..b0c54e74e 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 @@ -26,6 +26,8 @@ import java.util.List; import org.apache.commons.lang.StringUtils; import org.navalplanner.business.common.exceptions.CreateUnvalidatedException; +import org.navalplanner.business.common.exceptions.InstanceNotFoundException; +import org.navalplanner.business.common.exceptions.MultipleInstancesException; import org.navalplanner.business.resources.entities.CriterionSatisfaction; import org.navalplanner.business.resources.entities.Machine; import org.navalplanner.business.resources.entities.Resource; @@ -56,12 +58,13 @@ public class ResourceConverter { resource = createResourceWithBasicData((WorkerDTO) resourceDTO); } else { throw new RuntimeException( - _("Service does not manages resource of type: {0}", + _("Service does not manage resource of type: {0}", resourceDTO.getClass().getName())); } addCriterionSatisfactions(resource, resourceDTO.criterionSatisfactions); + setResourceCalendar(resource, resourceDTO.calendarName); return resource; @@ -110,4 +113,20 @@ public class ResourceConverter { } + private static void setResourceCalendar(Resource resource, + String calendarName) throws CreateUnvalidatedException { + + try { + resource.setResourceCalendar(calendarName); + } catch (InstanceNotFoundException e) { + throw new CreateUnvalidatedException( + _("{0}: calendar not found", calendarName)); + } catch (MultipleInstancesException e) { + throw new CreateUnvalidatedException( + _("there exist multiple calendars with name {0}", + calendarName)); + } + + } + } 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 4bc921d57..99ef7a5d3 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 @@ -20,6 +20,7 @@ package org.navalplanner.web.test.ws.resources.api; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -32,10 +33,15 @@ import java.util.Calendar; import java.util.List; import java.util.UUID; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.navalplanner.business.calendars.daos.IBaseCalendarDAO; +import org.navalplanner.business.calendars.entities.BaseCalendar; import org.navalplanner.business.common.IAdHocTransactionService; import org.navalplanner.business.common.IOnTransaction; +import org.navalplanner.business.common.daos.IConfigurationDAO; +import org.navalplanner.business.common.entities.IConfigurationBootstrap; import org.navalplanner.business.common.exceptions.InstanceNotFoundException; import org.navalplanner.business.resources.daos.ICriterionTypeDAO; import org.navalplanner.business.resources.daos.IMachineDAO; @@ -88,9 +94,23 @@ public class ResourceServiceTest { @Autowired private ICriterionTypeDAO criterionTypeDAO; + @Autowired + private IConfigurationDAO configurationDAO; + + @Autowired + private IBaseCalendarDAO baseCalendarDAO; + + @Autowired + private IConfigurationBootstrap configurationBootstrap; + @Autowired private IAdHocTransactionService transactionService; + @Before + public void loadConfiguration() { + configurationBootstrap.loadRequiredData(); + } + @Test public void testAddResourcesWithBasicContraintViolations() throws InstanceNotFoundException { @@ -342,6 +362,62 @@ public class ResourceServiceTest { } + @Test + @NotTransactional + public void testAddResourceWithDefaultCalendar() + throws InstanceNotFoundException { + + /* Create a machine DTO. */ + MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc"); + + /* Test. */ + assertNoConstraintViolations(resourceService. + addResources(createResourceListDTO(machineDTO))); + Machine machine = findUniqueMachineByCodeInitialized(machineDTO.code); + assertEquals(getDefaultCalendar().getId(), + machine.getCalendar().getParent().getId()); + + } + + @Test + @NotTransactional + public void testAddResourceWithSpecificCalendar() + throws InstanceNotFoundException { + + /* Create a base calendar. */ + BaseCalendar baseCalendar = createBaseCalendar(); + + /* Create a machine DTO. */ + MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc"); + machineDTO.calendarName = + ' ' + baseCalendar.getName().toUpperCase() + ' '; + + /* Test. */ + assertNoConstraintViolations(resourceService. + addResources(createResourceListDTO(machineDTO))); + Machine machine = findUniqueMachineByCodeInitialized(machineDTO.code); + assertEquals(baseCalendar.getId(), + machine.getCalendar().getParent().getId()); + + } + + @Test + @NotTransactional + public void testAddResourceWithNonExistentCalendar() + throws InstanceNotFoundException { + + /* Create a machine DTO. */ + MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc"); + machineDTO.calendarName = getUniqueName(); + + /* Test. */ + assertOneConstraintViolation(resourceService. + addResources(createResourceListDTO(machineDTO))); + assertFalse(machineDAO.existsMachineWithCodeInAnotherTransaction( + machineDTO.code)); + + } + private CriterionType createCriterionType() { return createCriterionType(ResourceEnum.RESOURCE); } @@ -398,6 +474,18 @@ public class ResourceServiceTest { } + private Resource initializeResource(Resource resource) { + + for (CriterionSatisfaction cs : resource.getCriterionSatisfactions()) { + cs.getCriterion().getType().getName(); + } + + resource.getCalendar().getParent(); + + return resource; + + } + private void saveResource(final Resource resource) { IOnTransaction save = new IOnTransaction() { @@ -413,13 +501,35 @@ public class ResourceServiceTest { } - private Resource initializeResource(Resource resource) { + public BaseCalendar getDefaultCalendar() { - for (CriterionSatisfaction cs : resource.getCriterionSatisfactions()) { - cs.getCriterion().getType().getName(); - } + IOnTransaction find = new IOnTransaction() { - return resource; + @Override + public BaseCalendar execute() { + return configurationDAO.getConfiguration().getDefaultCalendar(); + } + }; + + return transactionService.runOnTransaction(find); + + } + + private BaseCalendar createBaseCalendar() { + + IOnTransaction create = + new IOnTransaction() { + + @Override + public BaseCalendar execute() { + BaseCalendar baseCalendar = BaseCalendar.create(); + baseCalendar.setName(getUniqueName()); + baseCalendarDAO.save(baseCalendar); + return baseCalendar; + } + }; + + return transactionService.runOnTransaction(create); } @@ -436,6 +546,15 @@ public class ResourceServiceTest { } + private void assertNoConstraintViolations( + InstanceConstraintViolationsListDTO + instanceConstraintViolationsListDTO) { + + assertTrue(instanceConstraintViolationsListDTO. + instanceConstraintViolationsList.size() == 0); + + } + private void assertOneConstraintViolation( InstanceConstraintViolationsListDTO instanceConstraintViolationsListDTO) { diff --git a/scripts/rest-clients/resources-sample.xml b/scripts/rest-clients/resources-sample.xml index 980be3f0a..11646379f 100644 --- a/scripts/rest-clients/resources-sample.xml +++ b/scripts/rest-clients/resources-sample.xml @@ -5,7 +5,7 @@ - + @@ -24,14 +24,18 @@ + + + - + - + - + - + - + - + + + +