/*
* 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-2012 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.business.test.resources.daos;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertThat;
import static org.libreplan.business.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_FILE;
import static org.libreplan.business.test.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_TEST_FILE;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import org.hibernate.SessionFactory;
import org.joda.time.LocalDate;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.libreplan.business.IDataBootstrap;
import org.libreplan.business.calendars.entities.ResourceCalendar;
import org.libreplan.business.common.IAdHocTransactionService;
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
import org.libreplan.business.common.exceptions.ValidationException;
import org.libreplan.business.resources.daos.ICriterionDAO;
import org.libreplan.business.resources.daos.ICriterionTypeDAO;
import org.libreplan.business.resources.daos.IResourceDAO;
import org.libreplan.business.resources.daos.IResourcesSearcher;
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.Interval;
import org.libreplan.business.resources.entities.Resource;
import org.libreplan.business.resources.entities.Worker;
import org.libreplan.business.users.daos.IUserDAO;
import org.libreplan.business.users.entities.User;
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;
/**
* Test cases for {@link ResourceDAOTest}.
*
* @author Manuel Rego Casasnovas <mrego@igalia.com>
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { BUSINESS_SPRING_CONFIG_FILE, BUSINESS_SPRING_CONFIG_TEST_FILE })
public class ResourceDAOTest {
@Autowired
private IResourceDAO resourceDAO;
@Autowired
private ICriterionDAO criterionDAO;
@Autowired
private IResourcesSearcher resourcesSearcher;
@Autowired
private IAdHocTransactionService transactionService;
@Autowired
private SessionFactory sessionFactory;
@Autowired
private ICriterionTypeDAO criterionTypeDAO;
@Autowired
private IUserDAO userDAO;
@javax.annotation.Resource
private IDataBootstrap configurationBootstrap;
@Before
public void loadRequiredData() {
configurationBootstrap.loadRequiredData();
}
@Test
@Transactional
public void saveResourceWithCalendar() throws InstanceNotFoundException {
Resource resource = givenValidWorker();
ResourceCalendar resourceCalendar = givenValidResourceCalendar();
resource.setCalendar(resourceCalendar);
resourceDAO.save(resource);
resourceDAO.flush();
sessionFactory.getCurrentSession().evict(resource);
Resource foundResource = resourceDAO.find(resource.getId());
assertNotSame(resource, foundResource);
assertNotNull(foundResource.getCalendar());
assertThat(foundResource.getCalendar().getId(), equalTo(resourceCalendar.getId()));
}
private ResourceCalendar givenValidResourceCalendar() {
ResourceCalendar resourceCalendar = ResourceCalendar.create();
resourceCalendar.setName("Calendar");
return resourceCalendar;
}
public static Worker givenValidWorker() {
Worker worker = Worker.create();
worker.setFirstName("First name");
worker.setSurname("Surname");
worker.setNif("NIF" + UUID.randomUUID().toString());
return worker;
}
@Test
@Transactional
public void testResourceIsRelatedWithAllCriterions() {
Collection<Criterion> criterions = createCriterions();
createAndSaveResourceSatisfyingAllCriterions(criterions);
List<Resource> result = resourcesSearcher.searchBoth().byCriteria(criterions).execute();
assertNotNull(result);
assertEquals(1, result.size());
}
@Test
public void theHierarchyOfCriterionsIsConsidered() {
final Criterion[] parentCriteron = { null };
Resource worker = transactionService.runOnTransaction(() -> {
Worker result = givenValidWorker();
CriterionType type = createCriterionType("testType");
Criterion parent = createCriterion("parent", type);
parentCriteron[0] = parent;
Criterion child = createCriterion("child", type);
child.setParent(parent);
addSatisfactionsOn(result, Interval.from(new LocalDate(1970, 1, 1)), child);
return result;
});
final Criterion parent = transactionService.runOnReadOnlyTransaction(() ->
criterionDAO.findExistingEntity(parentCriteron[0].getId()));
List<Resource> resources = transactionService.runOnReadOnlyTransaction(() ->
resourcesSearcher.searchBoth().byCriteria(Collections.singleton(parent)).execute());
assertThat(resources.size(), equalTo(1));
Resource resource = resources.get(0);
assertThat(resource.getId(), equalTo(worker.getId()));
}
private Collection<Criterion> createCriterions() {
List<Criterion> result = new ArrayList<>();
CriterionType type = createCriterionType("criterionTypeTest");
result.add(createCriterion("criterion1", type));
result.add(createCriterion("criterion2", type));
return result;
}
private CriterionType createCriterionType(String name) {
CriterionType result = CriterionType.create(name, "");
criterionTypeDAO.save(result);
return result;
}
private Criterion createCriterion(String name) {
return createCriterion(name, createCriterionType(UUID.randomUUID().toString()));
}
private Criterion createCriterion(String name, CriterionType type) {
Criterion result = Criterion.create(name, type);
criterionDAO.save(result);
return result;
}
private Worker createAndSaveResourceSatisfyingAllCriterions(final Collection<Criterion> criterions) {
Worker result = givenValidWorker();
Interval interval = Interval.range(new LocalDate(1970, 1, 1), null);
addSatisfactionsOn(result, interval, criterions.toArray(new Criterion[criterions.size()]));
return result;
}
private void addSatisfactionsOn(Worker worker, Interval interval, final Criterion... criterions) {
Set<CriterionSatisfaction> satisfactions = new HashSet<>();
for (Criterion each : criterions) {
satisfactions.add(CriterionSatisfaction.create(each, worker, interval));
}
worker.addSatisfactions(satisfactions);
resourceDAO.save(worker);
}
@Test
@Transactional
public void testResourceIsNotRelatedWithAllCriterions() {
Collection<Criterion> criterions = createCriterions();
createAndSaveResourceSatisfyingAllCriterions(criterions);
// Modify criterions collection
criterions.add(createCriterion("criterion3"));
List<Resource> result = resourcesSearcher.searchBoth().byCriteria(criterions).execute();
assertNotNull(result);
assertThat(result.size(), not(equalTo(1)));
}
private User givenStoredUser() {
return transactionService.runOnAnotherTransaction(() -> {
User user = User.create("login" + UUID.randomUUID(), "password", "");
userDAO.save(user);
user.dontPoseAsTransientObjectAnymore();
return user;
});
}
@Test(expected = ValidationException.class)
@Transactional
public void testWorkerBoundToUserAlreadyBound() {
final User user = givenStoredUser();
transactionService.runOnAnotherTransaction(() -> {
Worker worker1 = givenValidWorker();
worker1.setUser(user);
resourceDAO.save(worker1);
return null;
});
transactionService.runOnAnotherTransaction(() -> {
Worker worker2 = givenValidWorker();
worker2.setUser(user);
resourceDAO.save(worker2);
return null;
});
}
}