// Copyright © 2015 HSL <https://www.hsl.fi> // This program is dual-licensed under the EUPL v1.2 and AGPLv3 licenses. package fi.hsl.parkandride.back; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import fi.hsl.parkandride.core.domain.*; import org.joda.time.DateTime; import org.junit.Before; import org.junit.Test; import javax.inject.Inject; import java.util.List; import java.util.Map; import static com.google.common.collect.Lists.newArrayList; import static fi.hsl.parkandride.core.domain.CapacityType.BICYCLE; import static fi.hsl.parkandride.core.domain.CapacityType.CAR; import static fi.hsl.parkandride.core.domain.CapacityType.ELECTRIC_CAR; import static fi.hsl.parkandride.core.domain.FacilityStatus.EXCEPTIONAL_SITUATION; import static fi.hsl.parkandride.core.domain.FacilityStatus.INACTIVE; import static fi.hsl.parkandride.core.domain.FacilityStatus.TEMPORARILY_CLOSED; import static fi.hsl.parkandride.core.domain.Usage.PARK_AND_RIDE; import static fi.hsl.parkandride.test.DateTimeTestUtils.withDate; import static org.assertj.core.api.Assertions.assertThat; public class FacilityHistoryDaoTest extends AbstractDaoTest { @Inject FacilityHistoryDao facilityHistoryDao; @Inject FacilityDao facilityDao; @Inject Dummies dummies; private Facility facility; final DateTime firstDate = new DateTime().minusDays(10); final DateTime secondDate = firstDate.plusDays(1); final DateTime thirdDate = firstDate.plusDays(2); final DateTime fourthDate = firstDate.plusDays(3); @Before public void initialize() { final Long dummyOperator = dummies.createDummyOperator(); facility = FacilityDaoTest.createFacility(dummyOperator, new FacilityContacts(dummies.createDummyContact(), dummies.createDummyContact())); } @Test public void facility_status_history_is_saved() { // First date final long facilityId = withDate(firstDate, () -> { long facId = facilityDao.insertFacility(facility); assertThat(facilityHistoryDao.getStatusHistory(facId)).hasSize(1); return facId; }); final Facility fac = facilityDao.getFacility(facilityId); // Second date withDate(secondDate, () -> { fac.status = FacilityStatus.INACTIVE; facilityDao.updateFacility(facilityId, fac); assertThat(facilityHistoryDao.getStatusHistory(facilityId)).hasSize(2); }); // Third date // This shouldn't create more entries since state did not change withDate(thirdDate, () -> { facilityDao.updateFacility(facilityId, fac); assertThat(facilityHistoryDao.getStatusHistory(facilityId)).hasSize(2); }); // Fourth date // But this should since the description changed final MultilingualString newStatus = new MultilingualString(FacilityDaoTest.STATUS_DESCRIPTION.fi); newStatus.sv = "Inte i bruk"; withDate(fourthDate, () -> { fac.statusDescription = newStatus; facilityDao.updateFacility(facilityId, fac); }); final FacilityStatusHistory first = new FacilityStatusHistory(facilityId, firstDate, secondDate, EXCEPTIONAL_SITUATION, FacilityDaoTest.STATUS_DESCRIPTION); final FacilityStatusHistory second = new FacilityStatusHistory(facilityId, secondDate, fourthDate, INACTIVE, FacilityDaoTest.STATUS_DESCRIPTION); final FacilityStatusHistory third = new FacilityStatusHistory(facilityId, fourthDate, null, INACTIVE, newStatus); // Get all of history final List<FacilityStatusHistory> history = facilityHistoryDao.getStatusHistory(facilityId); assertThat(history).containsExactly(first, second, third); // All included final List<FacilityStatusHistory> historyBetween = facilityHistoryDao.getStatusHistory(facilityId, firstDate.toLocalDate(), fourthDate.toLocalDate()); assertThat(historyBetween).containsExactly(first, second, third); // Only second overlaps final List<FacilityStatusHistory> historyAt = facilityHistoryDao.getStatusHistory(facilityId, thirdDate.toLocalDate(), thirdDate.toLocalDate()); assertThat(historyAt).containsExactly(second); } @Test public void facility_capacity_history_is_saved() { // First date final long facilityId = withDate(firstDate, () -> { facility.unavailableCapacities = newArrayList(new UnavailableCapacity( CAR, PARK_AND_RIDE, 1 )); long facId = facilityDao.insertFacility(facility); assertThat(facilityHistoryDao.getCapacityHistory(facId)).hasSize(1); return facId; }); final Facility fac = facilityDao.getFacility(facilityId); final Map<CapacityType, Integer> original = ImmutableMap.copyOf(fac.builtCapacity); final List<UnavailableCapacity> unavailable = ImmutableList.copyOf(fac.unavailableCapacities); // Second date // We change a value final Map<CapacityType, Integer> modifiedCapacity = withDate(secondDate, () -> { fac.builtCapacity.put(CAR, 49); facilityDao.updateFacility(facilityId, fac); assertThat(facilityHistoryDao.getCapacityHistory(facilityId)).hasSize(2); return ImmutableMap.copyOf(fac.builtCapacity); }); // Third date // Nothing saved, since nothing changes withDate(thirdDate, () -> { fac.status = INACTIVE; facilityDao.updateFacility(facilityId, fac); assertThat(facilityHistoryDao.getCapacityHistory(facilityId)).hasSize(2); }); // Fourth date // We add an entry to unavailable capacities final List<UnavailableCapacity> modified = withDate(fourthDate, () -> { fac.unavailableCapacities.add(new UnavailableCapacity( ELECTRIC_CAR, PARK_AND_RIDE, 5 )); facilityDao.updateFacility(facilityId, fac); return ImmutableList.copyOf(fac.unavailableCapacities); }); final FacilityCapacityHistory first = new FacilityCapacityHistory(facilityId, firstDate, secondDate, original, unavailable); final FacilityCapacityHistory second = new FacilityCapacityHistory(facilityId, secondDate, fourthDate, modifiedCapacity, unavailable); final FacilityCapacityHistory third = new FacilityCapacityHistory(facilityId, fourthDate, null, modifiedCapacity, modified); // Get all of history final List<FacilityCapacityHistory> history = facilityHistoryDao.getCapacityHistory(facilityId); assertThat(history).containsExactly(first, second, third); // All included final List<FacilityCapacityHistory> historyBetween = facilityHistoryDao.getCapacityHistory(facilityId, firstDate.toLocalDate(), fourthDate.toLocalDate()); assertThat(historyBetween).containsExactly(first, second, third); // Only second overlaps final List<FacilityCapacityHistory> historyAt = facilityHistoryDao.getCapacityHistory(facilityId, thirdDate.toLocalDate(), thirdDate.toLocalDate()); assertThat(historyAt).containsExactly(second); } @Test(expected = IllegalStateException.class) public void ensuresCapacityHistoryLinearity() { final Facility fac = withDate(secondDate, () -> facilityDao.getFacility(facilityDao.insertFacility(facility))); withDate(firstDate, () -> { fac.unavailableCapacities = newArrayList(new UnavailableCapacity(BICYCLE, PARK_AND_RIDE, 5)); facilityDao.updateFacility(fac.id, fac); }); } @Test(expected = IllegalStateException.class) public void ensuresStatusHistoryLinearity() { final Facility fac = withDate(secondDate, () -> facilityDao.getFacility(facilityDao.insertFacility(facility))); withDate(firstDate, () -> { fac.status = TEMPORARILY_CLOSED; facilityDao.updateFacility(fac.id, fac); }); } }