/* * This file is part of LibrePlan * * Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e * Desenvolvemento Tecnolóxico de Galicia * Copyright (C) 2010-2011 Igalia, S.L. * * 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.libreplan.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; import static org.libreplan.business.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_FILE; import static org.libreplan.web.WebappGlobalNames.WEBAPP_SPRING_CONFIG_FILE; import static org.libreplan.web.WebappGlobalNames.WEBAPP_SPRING_SECURITY_CONFIG_FILE; import static org.libreplan.web.test.WebappGlobalNames.WEBAPP_SPRING_CONFIG_TEST_FILE; import static org.libreplan.web.test.WebappGlobalNames.WEBAPP_SPRING_SECURITY_CONFIG_TEST_FILE; import static org.libreplan.web.test.ws.common.Util.assertNoConstraintViolations; import static org.libreplan.web.test.ws.common.Util.assertOneConstraintViolation; import static org.libreplan.web.test.ws.common.Util.assertOneConstraintViolationPerInstance; import static org.libreplan.web.test.ws.common.Util.assertOneRecoverableError; import static org.libreplan.web.test.ws.common.Util.getUniqueName; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.List; 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; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.libreplan.business.calendars.daos.IBaseCalendarDAO; import org.libreplan.business.calendars.entities.BaseCalendar; import org.libreplan.business.calendars.entities.ResourceCalendar; import org.libreplan.business.common.IAdHocTransactionService; import org.libreplan.business.common.IOnTransaction; import org.libreplan.business.common.daos.IConfigurationDAO; import org.libreplan.business.common.entities.IConfigurationBootstrap; import org.libreplan.business.common.exceptions.InstanceNotFoundException; import org.libreplan.business.costcategories.daos.ICostCategoryDAO; import org.libreplan.business.costcategories.entities.CostCategory; import org.libreplan.business.resources.daos.ICriterionTypeDAO; import org.libreplan.business.resources.daos.IMachineDAO; import org.libreplan.business.resources.daos.IResourceDAO; import org.libreplan.business.resources.daos.IWorkerDAO; import org.libreplan.business.resources.entities.Criterion; import org.libreplan.business.resources.entities.CriterionSatisfaction; import org.libreplan.business.resources.entities.CriterionType; import org.libreplan.business.resources.entities.Machine; import org.libreplan.business.resources.entities.Resource; import org.libreplan.business.resources.entities.ResourceEnum; import org.libreplan.business.resources.entities.Worker; import org.libreplan.ws.common.api.InstanceConstraintViolationsDTO; import org.libreplan.ws.resources.api.CriterionSatisfactionDTO; import org.libreplan.ws.resources.api.IResourceService; import org.libreplan.ws.resources.api.MachineDTO; import org.libreplan.ws.resources.api.ResourceCalendarDTO; import org.libreplan.ws.resources.api.ResourceDTO; import org.libreplan.ws.resources.api.ResourceListDTO; import org.libreplan.ws.resources.api.ResourcesCostCategoryAssignmentDTO; import org.libreplan.ws.resources.api.WorkerDTO; import org.libreplan.ws.resources.impl.ResourceConverter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.transaction.annotation.Transactional; /** * Tests for <code>IResourceService</code>. * * @author Fernando Bellas Permuy <fbellas@udc.es> */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { BUSINESS_SPRING_CONFIG_FILE, WEBAPP_SPRING_CONFIG_FILE, WEBAPP_SPRING_CONFIG_TEST_FILE, WEBAPP_SPRING_SECURITY_CONFIG_FILE, WEBAPP_SPRING_SECURITY_CONFIG_TEST_FILE }) public class ResourceServiceTest { @Autowired private IResourceService resourceService; @Autowired private IResourceDAO resourceDAO; @Autowired private IMachineDAO machineDAO; @Autowired private IWorkerDAO workerDAO; @Autowired private ICriterionTypeDAO criterionTypeDAO; @Autowired private IConfigurationDAO configurationDAO; @Autowired private IBaseCalendarDAO baseCalendarDAO; @Autowired private ICostCategoryDAO costCategoryDAO; @Autowired private IConfigurationBootstrap configurationBootstrap; @Autowired private IAdHocTransactionService transactionService; @Before public void loadConfiguration() { IOnTransaction<Void> load = new IOnTransaction<Void>() { @Override public Void execute() { configurationBootstrap.loadRequiredData(); return null; } }; transactionService.runOnAnotherTransaction(load); } @Test @Transactional public void testAddResourcesWithBasicContraintViolations() { /* Create resource DTOs. */ MachineDTO m1 = new MachineDTO("name", "desc"); MachineDTO m2 = new MachineDTO(" ", null, ""); // Missing code and name // (description is // optional). WorkerDTO w1 = new WorkerDTO(getUniqueName(), "w1-surname", "w1-nif"); WorkerDTO w2 = new WorkerDTO(null, "", null, ""); // Missing code, first // name, surname, and // nif. /* Test. */ List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList = resourceService.addResources( createResourceListDTO(m1, m2, w1, w2)). instanceConstraintViolationsList; 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). constraintViolations.toString(), instanceConstraintViolationsList.get(1). constraintViolations.size() == 4); // w2 constraint violations. assertTrue(resourceDAO.existsByCode(m1.code)); assertTrue(resourceDAO.existsByCode(w1.code)); } @Test @Transactional public void testAddWorkerWithExistingFirstNameSurnameAndNif() { /* Create a worker. */ Worker w1 = Worker.createUnvalidated(getUniqueName(), getUniqueName(), "surname", "nif"); saveResource(w1); /* * Create a worker DTO with the same first name, surname, and ID as * the previous one. */ WorkerDTO w2 = new WorkerDTO(w1.getFirstName(), w1.getSurname(), w1.getNif()); /* Test. */ assertOneConstraintViolation( resourceService.addResources(createResourceListDTO(w2))); assertFalse(resourceDAO.existsByCode(w2.code)); } @Test @Transactional public void testAddResourceWithCriterionSatisfactions() { /* Create a criterion type. */ CriterionType ct = createCriterionType(ResourceEnum.MACHINE); /* Create a resource DTO. */ MachineDTO m1 = new MachineDTO("name", "desc"); CriterionSatisfactionDTO cs1m1 = new CriterionSatisfactionDTO( ' ' + ct.getName().toUpperCase() + // Upper case and blank ' ', " C1 ", // spaces intentionally // added (OK). getDate(2001, 1, 1), getDate(2001, 2, 1)); m1.criterionSatisfactions.add(cs1m1); m1.criterionSatisfactions.add( new CriterionSatisfactionDTO(ct.getName(), "c2", getDate(2001, 1, 1), null)); MachineDTO m2 = new MachineDTO("name", "desc"); m2.criterionSatisfactions.add( new CriterionSatisfactionDTO(cs1m1.code, ct.getName(), "c1", getDate(2001, 1, 1), null)); // Repeated criterion satisfaction // code (used by another machine). m2.criterionSatisfactions.add( new CriterionSatisfactionDTO(null, ct.getName(), "c2", getDate(2001, 1, 1), null)); // Missing criterion satisfaction // code.(autogenerated code) MachineDTO m3 = new MachineDTO("name", "desc"); CriterionSatisfactionDTO cs1m3 = new CriterionSatisfactionDTO(ct.getName(), "c1", getDate(2001, 1, 1), getDate(2001, 2, 1)); m3.criterionSatisfactions.add(cs1m3); m3.criterionSatisfactions.add( new CriterionSatisfactionDTO( cs1m3.code, // Repeated criterion satisfaction code in this // machine. ct.getName(), "c2", getDate(2001, 1, 1), null)); /* Test. */ List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList = resourceService.addResources(createResourceListDTO(m1, m2, m3)). instanceConstraintViolationsList; assertTrue( instanceConstraintViolationsList.toString(), instanceConstraintViolationsList.size() == 2); assertTrue( instanceConstraintViolationsList.get(0). constraintViolations.toString(), instanceConstraintViolationsList.get(0). constraintViolations .size() == 1); // m2 constraint violations. assertTrue( instanceConstraintViolationsList.get(1). constraintViolations.toString(), instanceConstraintViolationsList.get(1). constraintViolations.size() == 1); // m3 constraint violations. assertFalse(resourceDAO.existsByCode(m2.code)); assertFalse(resourceDAO.existsByCode(m3.code)); Machine machine = machineDAO.findExistingEntityByCode(m1.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"); } } assertFalse(resourceDAO.existsByCode(m2.code)); } @Test @Transactional public void testAddResourceWithCriterionSatisfactionWithoutStartDate() { /* Create a criterion type. */ CriterionType ct = createCriterionType(ResourceEnum.MACHINE); /* Create a machine DTO. */ MachineDTO machineDTO = new MachineDTO("name", "desc"); machineDTO.criterionSatisfactions.add( new CriterionSatisfactionDTO(ct.getName() , "c1", null, getDate(2001, 1, 1))); // Missing start date. /* Test. */ assertOneConstraintViolation( resourceService.addResources(createResourceListDTO(machineDTO))); assertFalse(resourceDAO.existsByCode(machineDTO.code)); } @Test @Transactional public void testAddResourceWithCriterionSatisfactionWithNegativeInterval() { /* Create a criterion type. */ CriterionType ct = createCriterionType(ResourceEnum.MACHINE); /* Create a machine DTO. */ MachineDTO machineDTO = new MachineDTO("name", "desc"); machineDTO.criterionSatisfactions.add( new CriterionSatisfactionDTO(ct.getName() , "c1", getDate(2000, 2, 1), getDate(2000, 1, 1))); /* Test. */ assertOneConstraintViolation( resourceService.addResources(createResourceListDTO(machineDTO))); assertFalse(resourceDAO.existsByCode(machineDTO.code)); } @Test @Transactional public void testAddResourceWithOverlappingCriterionSatisfactionsAllowed() { /* Create a criterion type. */ CriterionType ct = createCriterionType(ResourceEnum.MACHINE); /* * Create a machine DTO. OK, because * ct.isAllowSimultaneousCriterionsPerResource() is true. */ MachineDTO machineDTO = createMachineDTOWithTwoCriterionSatisfactions( "machine", ct.getName(), "c1", getDate(2000, 1, 1), getDate(2000, 2, 1), "c2", getDate(2000, 1, 15), getDate(2000, 2, 1)); /* Test. */ assertNoConstraintViolations( resourceService.addResources(createResourceListDTO(machineDTO))); assertTrue(resourceDAO.existsByCode(machineDTO.code)); } @Test @Transactional public void testAddResourceWithOverlappingCriterionSatisfactions() { /* Create criterion types. */ CriterionType ct1 = createCriterionType(ResourceEnum.MACHINE); CriterionType ct2 = createCriterionType(ResourceEnum.MACHINE, false); /* * Create resource DTOs. Each resource contains one criterion * satisfaction overlapping. * */ MachineDTO m1 = createMachineDTOWithTwoCriterionSatisfactions( "m1", ct1.getName(), // Interval overlapping in "c1". "c1", getDate(2000, 1, 1), getDate(2000, 2, 1), "c1", getDate(2000, 1, 15), getDate(2000, 2, 1)); MachineDTO m2 = createMachineDTOWithTwoCriterionSatisfactions( "m2", ct2.getName(), // Overlapping because "ct2" does not allow // simultaneous criterion satisfactions in // intervals that overlap. "c1", getDate(2000, 1, 1), getDate(2000, 2, 1), "c2", getDate(2000, 1, 15), getDate(2000, 2, 1)); /* 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", resourceDAO.existsByCode(((MachineDTO) r).code)); } } @Test @Transactional public void testAddResourcesWithCriterionSatisfactionsWithIncorrectCriterionType() { /* Create two criterion types. */ CriterionType machineCt = createCriterionType(ResourceEnum.MACHINE); CriterionType workerCt = createCriterionType(ResourceEnum.WORKER); /* Create resource DTOs. */ MachineDTO machineDTO = new MachineDTO("name", "desc"); machineDTO.criterionSatisfactions.add( new CriterionSatisfactionDTO(workerCt.getName() , "c1", getDate(2001, 1, 1), null)); // Incorrect type. WorkerDTO workerDTO = new WorkerDTO(getUniqueName(), "surname", getUniqueName()); workerDTO.criterionSatisfactions.add( new CriterionSatisfactionDTO(machineCt.getName() , "c1", getDate(2001, 1, 1), null)); // Incorrect type. /* Test. */ assertOneConstraintViolation( resourceService.addResources(createResourceListDTO(machineDTO))); assertFalse( resourceDAO.existsByCode(machineDTO.code)); assertOneConstraintViolation( resourceService.addResources(createResourceListDTO(workerDTO))); assertFalse(resourceDAO.existsByCode(workerDTO.code)); } @Test @Transactional public void testAddResourcesWithCriterionSatisfactionsWithMissingNames() { /* Create a criterion type. */ CriterionType ct = createCriterionType(); /* Create machines DTOs. */ MachineDTO m1 = new MachineDTO("m1", "desc"); m1.criterionSatisfactions.add( new CriterionSatisfactionDTO("", "X", // Missing criterion type. getDate(2001, 1, 1), null)); MachineDTO m2 = new MachineDTO("m2", "desc"); m2.criterionSatisfactions.add( new CriterionSatisfactionDTO(ct.getName(), // Missing criterion. null, getDate(2001, 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", resourceDAO.existsByCode(((MachineDTO) r).code)); } } @Test @Transactional public void testAddResourceWithCriterionSatisfactionsWithNonExistentCriterionType() { /* Create a machine DTO. */ MachineDTO machineDTO = new MachineDTO("name", "desc"); machineDTO.criterionSatisfactions.add( new CriterionSatisfactionDTO(getUniqueName() , "c1", getDate(2000, 1, 1), null)); /* Test. */ assertOneRecoverableError( resourceService.addResources(createResourceListDTO(machineDTO))); assertFalse(resourceDAO.existsByCode(machineDTO.code)); } @Test @Transactional public void testAddResourceWithCriterionSatisfactionsWithNonExistentCriterion() { /* Create a criterion type. */ CriterionType ct = createCriterionType(); /* Create a machine DTO. */ MachineDTO machineDTO = new MachineDTO("name", "desc"); machineDTO.criterionSatisfactions.add( new CriterionSatisfactionDTO(ct.getName(), getUniqueName(), getDate(2000, 1, 1), null)); /* Test. */ assertOneRecoverableError( resourceService.addResources(createResourceListDTO(machineDTO))); assertFalse(resourceDAO.existsByCode(machineDTO.code)); } @Test @Transactional public void testAddResourceWithDefaultCalendar() { /* Create a machine DTO. */ MachineDTO machineDTO = new MachineDTO("name", "desc"); /* Test. */ assertNoConstraintViolations(resourceService. addResources(createResourceListDTO(machineDTO))); Machine machine = machineDAO.findExistingEntityByCode(machineDTO.code); assertEquals(getDefaultCalendar().getId(), machine.getCalendar().getParent().getId()); } @Test @Transactional public void testAddResourceWithSpecificCalendar() { /* Create a resource calendar DTO. */ BaseCalendar baseCalendar = createBaseCalendar(); ResourceCalendar resourceCalendar = baseCalendar .newDerivedResourceCalendar(); ResourceCalendarDTO resourceCalendarDTO = ResourceConverter .toDTO(resourceCalendar); /* Create a machine DTO. */ MachineDTO machineDTO = new MachineDTO("name", "desc"); machineDTO.calendar = resourceCalendarDTO; /* Test. */ assertNoConstraintViolations(resourceService .addResources(createResourceListDTO(machineDTO))); Machine machine = machineDAO.findExistingEntityByCode(machineDTO.code); assertEquals(baseCalendar.getId(), machine.getCalendar().getParent() .getId()); } @Test @Transactional public void testAddResourceWithNonExistentCalendar() { /* Create invalid calendar */ ResourceCalendarDTO calendarDTO = new ResourceCalendarDTO("", "ParentNoExist", null, null, null, null); /* Create a machine DTO. */ MachineDTO machineDTO = new MachineDTO("name", "desc"); machineDTO.calendar = calendarDTO; /* Test. */ assertOneRecoverableError(resourceService .addResources(createResourceListDTO(machineDTO))); assertFalse(resourceDAO.existsByCode(machineDTO.code)); } @Test @Transactional public void testAddResourceWithCostAssignments() { /* Create a CostCategory. */ CostCategory costCategory = createCostCategory(); /* Create resource DTOs. */ MachineDTO m1 = new MachineDTO("name", "desc"); ResourcesCostCategoryAssignmentDTO a1m1 = new ResourcesCostCategoryAssignmentDTO( ' ' + costCategory.getName().toUpperCase() + ' ', getDate(2001, 1, 1), null); m1.resourcesCostCategoryAssignments.add(a1m1); m1.resourcesCostCategoryAssignments .add(new ResourcesCostCategoryAssignmentDTO(costCategory .getName(), getDate(2000, 1, 1), getDate(2000, 4, 1))); MachineDTO m2 = new MachineDTO("name", "desc"); m2.resourcesCostCategoryAssignments .add(new ResourcesCostCategoryAssignmentDTO(a1m1.code, costCategory.getName().toUpperCase(), getDate(2001, 1, 1), null)); // Repeated assignment code // (used by another machine). m2.resourcesCostCategoryAssignments .add(new ResourcesCostCategoryAssignmentDTO(null, costCategory .getName().toUpperCase(), getDate(2000, 1, 1), getDate( 2000, 4, 1))); // Missing // assignment code (autogenerated code). MachineDTO m3 = new MachineDTO("name", "desc"); ResourcesCostCategoryAssignmentDTO a1m3 = new ResourcesCostCategoryAssignmentDTO( costCategory.getName(), getDate(2001, 1, 1), null); m3.resourcesCostCategoryAssignments.add(a1m3); m3.resourcesCostCategoryAssignments .add(new ResourcesCostCategoryAssignmentDTO(a1m3.code, // Repeated // assignment // code // in // this // machine. costCategory.getName(), getDate(2000, 1, 1), getDate( 2000, 4, 1))); /* Test. */ List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList = resourceService .addResources(createResourceListDTO(m1, m2, m3)).instanceConstraintViolationsList; assertTrue(instanceConstraintViolationsList.toString(), instanceConstraintViolationsList.size() == 2); assertTrue(instanceConstraintViolationsList.get(0).constraintViolations .toString(), instanceConstraintViolationsList.get(0).constraintViolations .size() == 1); // m2 constraint violations. assertTrue(instanceConstraintViolationsList.get(1).constraintViolations .toString(), instanceConstraintViolationsList.get(1).constraintViolations .size() == 1); // m3 constraint violations. assertTrue(resourceDAO.existsByCode(m1.code)); assertFalse(resourceDAO.existsByCode(m2.code)); } @Test @Transactional public void testAddResourcesWithCostAssignmentWithMissingCostCategoryName() { /* Create a resource DTO. */ MachineDTO machineDTO = new MachineDTO("name", "desc"); machineDTO.resourcesCostCategoryAssignments .add(new ResourcesCostCategoryAssignmentDTO("", null, getDate( 2000, 1, 1), null)); /* Test. */ assertOneConstraintViolation(resourceService .addResources(createResourceListDTO(machineDTO))); assertFalse(resourceDAO.existsByCode(machineDTO.code)); } @Test @Transactional public void testAddResourcesWithCostAssignmentWithNonExistentCostCategory() { /* Create a resource DTO. */ MachineDTO machineDTO = new MachineDTO("name", "desc"); machineDTO.resourcesCostCategoryAssignments .add(new ResourcesCostCategoryAssignmentDTO(getUniqueName(), getDate(2000, 1, 1), null)); /* Test. */ assertOneRecoverableError(resourceService .addResources(createResourceListDTO(machineDTO))); assertFalse(resourceDAO.existsByCode(machineDTO.code)); } @Test @Transactional public void testAddResourceWithCostAssignmentWithoutStartDate() { /* Create a CostCategory. */ CostCategory costCategory = createCostCategory(); /* Create a resource DTO. */ MachineDTO machineDTO = new MachineDTO("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(resourceDAO.existsByCode(machineDTO.code)); } @Test @Transactional public void testAddResourceWithCostAssignmentWithNegativeInterval() { /* Create a CostCategory. */ CostCategory costCategory = createCostCategory(); /* Create a resource DTO. */ MachineDTO machineDTO = new MachineDTO("name", "desc"); machineDTO.resourcesCostCategoryAssignments .add(new ResourcesCostCategoryAssignmentDTO(costCategory .getName(), getDate(2000, 2, 1), getDate(2000, 1, 1))); /* Test. */ assertOneConstraintViolation(resourceService .addResources(createResourceListDTO(machineDTO))); assertFalse(resourceDAO.existsByCode(machineDTO.code)); } @Test @Transactional 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", resourceDAO .existsByCode(((MachineDTO) r).code)); } } @Test @Transactional public void testUpdateResources() throws InstanceNotFoundException { CriterionType ctMachine = createCriterionType(ResourceEnum.MACHINE); CriterionType ctWorker = createCriterionType(ResourceEnum.WORKER); CostCategory costCategory = createCostCategory(); /* Create a machine DTO. */ MachineDTO m1 = new MachineDTO("name", "desc"); CriterionSatisfactionDTO m1s1 = new CriterionSatisfactionDTO( ctMachine .getName(), "c1", getDate(2000, 1, 1), getDate(2000, 2, 1)); m1.criterionSatisfactions.add(m1s1); ResourcesCostCategoryAssignmentDTO m1a1 = new ResourcesCostCategoryAssignmentDTO( costCategory.getName(), getDate(2000, 1, 1), getDate(2000, 2, 1)); m1.resourcesCostCategoryAssignments.add(m1a1); /* Create a worker DTO. */ String nif = getUniqueName(); WorkerDTO w1 = new WorkerDTO(getUniqueName(), "surname", nif); CriterionSatisfactionDTO w1s1 = new CriterionSatisfactionDTO( ctWorker .getName(), "c1", getDate(2000, 1, 1), getDate(2000, 2, 1)); w1.criterionSatisfactions.add(w1s1); ResourcesCostCategoryAssignmentDTO w1a1 = new ResourcesCostCategoryAssignmentDTO( costCategory.getName(), getDate(2000, 1, 1), getDate(2000, 2, 1)); w1.resourcesCostCategoryAssignments.add(w1a1); /* Add resources. */ assertNoConstraintViolations(resourceService .addResources(createResourceListDTO(m1, w1))); /* * Build DTOs for making the following update: + m1: update name, m1s1's * start date, and add a new cost category assignment. + w1: update * surname, w1a1's start date, and add a new criterion satisfaction. */ MachineDTO m1Updated = new MachineDTO(m1.code, "name" + "UPDATED", null); CriterionSatisfactionDTO m1s1Updated = new CriterionSatisfactionDTO( m1s1.code, null, null, getDate(2000, 1, 2), null); m1Updated.criterionSatisfactions.add(m1s1Updated); ResourcesCostCategoryAssignmentDTO m1a2 = new ResourcesCostCategoryAssignmentDTO( costCategory.getName(), getDate(2000, 3, 1), getDate(2000, 4, 1)); m1Updated.resourcesCostCategoryAssignments.add(m1a2); WorkerDTO w1Updated = new WorkerDTO(w1.code, null, "surname" + "UPDATED", null); CriterionSatisfactionDTO w1s2 = new CriterionSatisfactionDTO( ctWorker .getName(), "c1", getDate(2000, 3, 1), getDate(2000, 4, 1)); w1Updated.criterionSatisfactions.add(w1s2); ResourcesCostCategoryAssignmentDTO w1a1Updated = new ResourcesCostCategoryAssignmentDTO( w1a1.code, null, getDate(2000, 2, 1), null); w1Updated.resourcesCostCategoryAssignments.add(w1a1Updated); /* Update resources and test. */ assertNoConstraintViolations(resourceService .addResources(createResourceListDTO(m1Updated, w1Updated))); /* Test machine update. */ Machine m1Entity = machineDAO.findByCode(m1.code); assertEquals(m1Updated.name, m1Entity.getName()); // Modified. assertEquals(m1.description, m1Entity.getDescription()); //Not modified. assertTrue(datesEquals( // Modified. m1s1Updated.startDate, m1Entity.getCriterionSatisfactionByCode(m1s1.code).getStartDate())); assertTrue(datesEquals( // Not modified. m1s1.endDate, m1Entity.getCriterionSatisfactionByCode(m1s1.code).getEndDate())); m1Entity.getResourcesCostCategoryAssignmentByCode(m1a2.code); // New. /* Test worker update. */ Worker w1Entity = workerDAO.findByCode(w1.code); assertEquals(w1Updated.surname, w1Entity.getSurname()); // Modified. assertEquals(w1.firstName, w1Entity.getFirstName()); // Not modified. w1Entity.getCriterionSatisfactionByCode(w1s2.code); // New. assertTrue(datesEquals( // Modified. w1a1Updated.startDate, w1Entity.getResourcesCostCategoryAssignmentByCode(w1a1.code). getInitDate())); assertTrue(datesEquals( // Not modified. w1a1.endDate, w1Entity.getResourcesCostCategoryAssignmentByCode(w1a1.code). getEndDate())); } private CriterionType createCriterionType() { return createCriterionType(ResourceEnum.WORKER, true); } private CriterionType createCriterionType(final ResourceEnum resourceType) { return createCriterionType(resourceType, true); } private CriterionType createCriterionType(final ResourceEnum resourceType, final boolean allowSimultaneousCriterionsPerResource) { IOnTransaction<CriterionType> createCriterionType = new IOnTransaction<CriterionType>() { @Override public CriterionType execute() { CriterionType ct = CriterionType.create(getUniqueName(), "desc"); ct.setAllowSimultaneousCriterionsPerResource( allowSimultaneousCriterionsPerResource); ct.setResource(resourceType); 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.runOnAnotherTransaction(createCriterionType); } private void saveResource(final Resource resource) { IOnTransaction<Void> save = new IOnTransaction<Void>() { @Override public Void execute() { resourceDAO.save(resource); return null; } }; transactionService.runOnAnotherTransaction(save); } private BaseCalendar getDefaultCalendar() { IOnTransaction<BaseCalendar> find = new IOnTransaction<BaseCalendar>() { @Override public BaseCalendar execute() { return configurationDAO.getConfiguration().getDefaultCalendar(); } }; return transactionService.runOnAnotherTransaction(find); } private BaseCalendar createBaseCalendar() { IOnTransaction<BaseCalendar> create = new IOnTransaction<BaseCalendar>() { @Override public BaseCalendar execute() { BaseCalendar baseCalendar = BaseCalendar.createBasicCalendar(); baseCalendar.setName(getUniqueName()); baseCalendarDAO.save(baseCalendar); return baseCalendar; } }; return transactionService.runOnAnotherTransaction(create); } private ResourceListDTO createResourceListDTO(ResourceDTO... resources) { List<ResourceDTO> resourceList = new ArrayList<ResourceDTO>(); for (ResourceDTO r : resources) { resourceList.add(r); } return new ResourceListDTO(resourceList); } private CostCategory createCostCategory() { IOnTransaction<CostCategory> create = new IOnTransaction<CostCategory>() { @Override public CostCategory execute() { CostCategory costCategory = CostCategory.create(getUniqueName()); costCategoryDAO.save(costCategory); return costCategory; } }; return transactionService.runOnAnotherTransaction(create); } private MachineDTO createMachineDTOWithTwoCriterionSatisfactions( String machineName, String criterionTypeName, String criterionName1, XMLGregorianCalendar startDate1, XMLGregorianCalendar endDate1, String criterionName2, XMLGregorianCalendar startDate2, XMLGregorianCalendar endDate2) { MachineDTO machineDTO = new MachineDTO(machineName, "desc"); machineDTO.criterionSatisfactions.add( new CriterionSatisfactionDTO(criterionTypeName, criterionName1, startDate1, endDate1)); machineDTO.criterionSatisfactions.add( new CriterionSatisfactionDTO(criterionTypeName, criterionName2, startDate2, endDate2)); return machineDTO; } private MachineDTO createMachineDTOWithTwoCostsAssignments( String machineName, String costCategoryName, XMLGregorianCalendar startDate1, XMLGregorianCalendar endDate1, XMLGregorianCalendar startDate2, XMLGregorianCalendar endDate2) { MachineDTO machineDTO = new MachineDTO(machineName, "desc"); machineDTO.resourcesCostCategoryAssignments.add( new ResourcesCostCategoryAssignmentDTO( costCategoryName, startDate1, endDate1)); machineDTO.resourcesCostCategoryAssignments.add( new ResourcesCostCategoryAssignmentDTO( costCategoryName, startDate2, endDate2)); return machineDTO; } 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); } } private boolean datesEquals(XMLGregorianCalendar date1, Date date2) { GregorianCalendar date2AsGC = new GregorianCalendar(); date2AsGC.setTime(date2); return datesEquals(date1.toGregorianCalendar(), date2AsGC); } private boolean datesEquals(XMLGregorianCalendar date1, LocalDate date2) { GregorianCalendar date2AsGC = new GregorianCalendar( date2.getYear(), date2.getMonthOfYear()-1, date2.getDayOfMonth()); return datesEquals(date1.toGregorianCalendar(), date2AsGC); } public boolean datesEquals(GregorianCalendar date1, GregorianCalendar date2) { return date1.get(Calendar.YEAR) == date2.get(Calendar.YEAR) && date1.get(Calendar.MONTH) == date2.get(Calendar.MONTH) && date1.get(Calendar.DAY_OF_MONTH) == date2.get(Calendar.DAY_OF_MONTH); } }