ItEr42S12CUImportacionRecursosProductivosItEr41S15: Calendar-specification support for resources being imported.

Resources to be imported can now specify a calendar name. Each resource will have a derived calendar of the specified one. Furthermore, test cases have been implemented for the most common cases (calendar not specified -> use default calendar, calendar specified, and non-existent calendar).
This commit is contained in:
Fernando Bellas Permuy 2010-01-05 20:01:26 +01:00 committed by Javier Moran Rua
parent 1a12344ce5
commit 3f67d4aad5
7 changed files with 246 additions and 16 deletions

View file

@ -24,6 +24,7 @@ import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria; import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions; import org.hibernate.criterion.Restrictions;
import org.navalplanner.business.calendars.entities.BaseCalendar; import org.navalplanner.business.calendars.entities.BaseCalendar;
@ -39,6 +40,7 @@ import org.springframework.transaction.annotation.Transactional;
* DAO for {@link BaseCalendar} * DAO for {@link BaseCalendar}
* *
* @author Manuel Rego Casasnovas <mrego@igalia.com> * @author Manuel Rego Casasnovas <mrego@igalia.com>
* @author Fernando Bellas Permuy <fbellas@udc.es>
*/ */
@Repository @Repository
@Scope(BeanDefinition.SCOPE_SINGLETON) @Scope(BeanDefinition.SCOPE_SINGLETON)
@ -88,8 +90,13 @@ public class BaseCalendarDAO extends GenericDAOHibernate<BaseCalendar, Long>
@Override @Override
public List<BaseCalendar> findByName(String name) { public List<BaseCalendar> findByName(String name) {
if (StringUtils.isBlank(name)) {
return new ArrayList<BaseCalendar>();
}
Criteria c = getSession().createCriteria(BaseCalendar.class); Criteria c = getSession().createCriteria(BaseCalendar.class);
c.add(Restrictions.eq("name", name)); c.add(Restrictions.eq("name", name).ignoreCase());
List<BaseCalendar> list = (List<BaseCalendar>) c.list(); List<BaseCalendar> list = (List<BaseCalendar>) c.list();
removeResourceCalendarInstances(list); removeResourceCalendarInstances(list);

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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 <fbellas@udc.es>
*/
@SuppressWarnings("serial")
public class MultipleInstancesException extends InstanceException {
public MultipleInstancesException(String logicId, String className) {
super("Multiple instances with the same logic identifier",
logicId, className);
}
}

View file

@ -31,6 +31,7 @@ import java.util.ListIterator;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
import org.hibernate.validator.AssertFalse; import org.hibernate.validator.AssertFalse;
import org.hibernate.validator.AssertTrue; import org.hibernate.validator.AssertTrue;
@ -38,10 +39,14 @@ import org.hibernate.validator.InvalidValue;
import org.hibernate.validator.Valid; import org.hibernate.validator.Valid;
import org.joda.time.Days; import org.joda.time.Days;
import org.joda.time.LocalDate; 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.IWorkHours;
import org.navalplanner.business.calendars.entities.ResourceCalendar; import org.navalplanner.business.calendars.entities.ResourceCalendar;
import org.navalplanner.business.calendars.entities.SameWorkHoursEveryDay; import org.navalplanner.business.calendars.entities.SameWorkHoursEveryDay;
import org.navalplanner.business.common.BaseEntity; 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.common.exceptions.ValidationException;
import org.navalplanner.business.costcategories.entities.ResourcesCostCategoryAssignment; import org.navalplanner.business.costcategories.entities.ResourcesCostCategoryAssignment;
import org.navalplanner.business.planner.entities.DayAssignment; import org.navalplanner.business.planner.entities.DayAssignment;
@ -659,6 +664,37 @@ public abstract class Resource extends BaseEntity{
return calendar; return calendar;
} }
public void setResourceCalendar(String calendarName)
throws InstanceNotFoundException, MultipleInstancesException {
ResourceCalendar calendar;
if (StringUtils.isBlank(calendarName)) {
calendar = Registry.getConfigurationDAO().getConfiguration().
getDefaultCalendar().newDerivedResourceCalendar();
} else {
List<BaseCalendar> 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) { public int getAssignedHours(LocalDate localDate) {
int sum = 0; int sum = 0;
for (DayAssignment dayAssignment : getAssignmentsForDay(localDate)) { for (DayAssignment dayAssignment : getAssignmentsForDay(localDate)) {

View file

@ -23,6 +23,7 @@ package org.navalplanner.ws.resources.api;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlElementWrapper;
@ -33,6 +34,9 @@ import javax.xml.bind.annotation.XmlElementWrapper;
*/ */
public abstract class ResourceDTO { public abstract class ResourceDTO {
@XmlAttribute(name="calendar-name")
public String calendarName;
@XmlElementWrapper(name="criterion-satisfaction-list") @XmlElementWrapper(name="criterion-satisfaction-list")
@XmlElement(name="criterion-satisfaction") @XmlElement(name="criterion-satisfaction")
public List<CriterionSatisfactionDTO> criterionSatisfactions = public List<CriterionSatisfactionDTO> criterionSatisfactions =

View file

@ -26,6 +26,8 @@ import java.util.List;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.navalplanner.business.common.exceptions.CreateUnvalidatedException; 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.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;
@ -56,12 +58,13 @@ public class ResourceConverter {
resource = createResourceWithBasicData((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 manage resource of type: {0}",
resourceDTO.getClass().getName())); resourceDTO.getClass().getName()));
} }
addCriterionSatisfactions(resource, addCriterionSatisfactions(resource,
resourceDTO.criterionSatisfactions); resourceDTO.criterionSatisfactions);
setResourceCalendar(resource, resourceDTO.calendarName);
return resource; 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));
}
}
} }

View file

@ -20,6 +20,7 @@
package org.navalplanner.web.test.ws.resources.api; 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.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
@ -32,10 +33,15 @@ import java.util.Calendar;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; 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.IAdHocTransactionService;
import org.navalplanner.business.common.IOnTransaction; 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.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.resources.daos.ICriterionTypeDAO; import org.navalplanner.business.resources.daos.ICriterionTypeDAO;
import org.navalplanner.business.resources.daos.IMachineDAO; import org.navalplanner.business.resources.daos.IMachineDAO;
@ -88,9 +94,23 @@ public class ResourceServiceTest {
@Autowired @Autowired
private ICriterionTypeDAO criterionTypeDAO; private ICriterionTypeDAO criterionTypeDAO;
@Autowired
private IConfigurationDAO configurationDAO;
@Autowired
private IBaseCalendarDAO baseCalendarDAO;
@Autowired
private IConfigurationBootstrap configurationBootstrap;
@Autowired @Autowired
private IAdHocTransactionService transactionService; private IAdHocTransactionService transactionService;
@Before
public void loadConfiguration() {
configurationBootstrap.loadRequiredData();
}
@Test @Test
public void testAddResourcesWithBasicContraintViolations() public void testAddResourcesWithBasicContraintViolations()
throws InstanceNotFoundException { 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() { private CriterionType createCriterionType() {
return createCriterionType(ResourceEnum.RESOURCE); 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) { private void saveResource(final Resource resource) {
IOnTransaction<Void> save = new IOnTransaction<Void>() { IOnTransaction<Void> save = new IOnTransaction<Void>() {
@ -413,13 +501,35 @@ public class ResourceServiceTest {
} }
private Resource initializeResource(Resource resource) { public BaseCalendar getDefaultCalendar() {
for (CriterionSatisfaction cs : resource.getCriterionSatisfactions()) { IOnTransaction<BaseCalendar> find = new IOnTransaction<BaseCalendar>() {
cs.getCriterion().getType().getName();
}
return resource; @Override
public BaseCalendar execute() {
return configurationDAO.getConfiguration().getDefaultCalendar();
}
};
return transactionService.runOnTransaction(find);
}
private BaseCalendar createBaseCalendar() {
IOnTransaction<BaseCalendar> create =
new IOnTransaction<BaseCalendar>() {
@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( private void assertOneConstraintViolation(
InstanceConstraintViolationsListDTO InstanceConstraintViolationsListDTO
instanceConstraintViolationsListDTO) { instanceConstraintViolationsListDTO) {

View file

@ -5,7 +5,7 @@
<!-- *** Machines *** --> <!-- *** Machines *** -->
<!-- OK --> <!-- OK -->
<machine code=" m1 " name="m1-name" description="m1-desc"/> <machine code="m1" name="m1-name" description="m1-desc"/>
<!-- Missing code and name (description is optional). --> <!-- Missing code and name (description is optional). -->
<machine code="" description=""/> <machine code="" description=""/>
@ -24,14 +24,18 @@
<!-- Another machine is being imported with the same code. --> <!-- Another machine is being imported with the same code. -->
<machine code="m1" name="m3-name" description="m3-desc"/> <machine code="m1" name="m3-name" description="m3-desc"/>
<!-- OK or not OK depending on the existence of "CalendarTest". -->
<machine code="m4" name="m4-name" description="m4-desc"
calendar-name="CalendarTest"/>
<!-- *** 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-list>
<criterion-satisfaction <criterion-satisfaction
criterion-type-name=" WORK_RELATIONSHIP " criterion-type-name="WORK_RELATIONSHIP"
criterion-name=" hiredResourceWorkingRelationship " criterion-name="hiredResourceWorkingRelationship"
start-date="2009-01-01" start-date="2009-01-01"
finish-date=""/> finish-date=""/>
<criterion-satisfaction <criterion-satisfaction
@ -46,7 +50,7 @@
<worker first-name="" nif=""/> <worker first-name="" nif=""/>
<!-- Missing start date in criterion satisfaction. --> <!-- Missing start date in criterion satisfaction. -->
<worker first-name="w2-firstName" surname="w2-surname" nif=" w2-nif "> <worker first-name="w2-firstName" surname="w2-surname" nif="w2-nif">
<criterion-satisfaction-list> <criterion-satisfaction-list>
<criterion-satisfaction <criterion-satisfaction
criterion-type-name="LEAVE" criterion-type-name="LEAVE"
@ -56,7 +60,7 @@
</worker> </worker>
<!-- Non-existent criterion type. --> <!-- Non-existent criterion type. -->
<worker first-name="w3-firstName" surname="w3-surname" nif=" w3-nif "> <worker first-name="w3-firstName" surname="w3-surname" nif="w3-nif">
<criterion-satisfaction-list> <criterion-satisfaction-list>
<criterion-satisfaction <criterion-satisfaction
criterion-type-name="WORK_RELATIONSHIP_XXX" criterion-type-name="WORK_RELATIONSHIP_XXX"
@ -67,7 +71,7 @@
</worker> </worker>
<!-- Non-existent criterion. --> <!-- Non-existent criterion. -->
<worker first-name="w4-firstName" surname="w4-surname" nif=" w4-nif "> <worker first-name="w4-firstName" surname="w4-surname" nif="w4-nif">
<criterion-satisfaction-list> <criterion-satisfaction-list>
<criterion-satisfaction <criterion-satisfaction
criterion-type-name="WORK_RELATIONSHIP" criterion-type-name="WORK_RELATIONSHIP"
@ -78,7 +82,7 @@
</worker> </worker>
<!-- Criterion not specified. --> <!-- Criterion not specified. -->
<worker first-name="w5-firstName" surname="w5-surname" nif=" w5-nif "> <worker first-name="w5-firstName" surname="w5-surname" nif="w5-nif">
<criterion-satisfaction-list> <criterion-satisfaction-list>
<criterion-satisfaction <criterion-satisfaction
criterion-type-name="WORK_RELATIONSHIP" criterion-type-name="WORK_RELATIONSHIP"
@ -88,7 +92,7 @@
</worker> </worker>
<!-- Criterion type not specified. --> <!-- Criterion type not specified. -->
<worker first-name="w6-firstName" surname="w6-surname" nif=" w6-nif "> <worker first-name="w6-firstName" surname="w6-surname" nif="w6-nif">
<criterion-satisfaction-list> <criterion-satisfaction-list>
<criterion-satisfaction <criterion-satisfaction
criterion-name="hiredResourceWorkingRelationship" criterion-name="hiredResourceWorkingRelationship"
@ -101,4 +105,8 @@
and nif. --> and nif. -->
<worker first-name="w1-firstName" surname="w1-surname" nif="w1-nif"/> <worker first-name="w1-firstName" surname="w1-surname" nif="w1-nif"/>
<!-- OK or not OK depending on the existence of "CalendarTest". -->
<worker first-name="w8-firstName" surname="w8-surname" nif="w8-nif"
calendar-name="CalendarTest" />
</resource-list> </resource-list>