/*
* 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.business.test.planner.entities;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.getCurrentArguments;
import static org.easymock.EasyMock.isA;
import static org.easymock.EasyMock.verify;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.replay;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.libreplan.business.test.planner.entities.DayAssignmentMatchers.haveHours;
import static org.libreplan.business.workingday.EffortDuration.hours;
import static org.libreplan.business.workingday.EffortDuration.zero;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.easymock.IAnswer;
import org.joda.time.LocalDate;
import org.junit.Test;
import org.libreplan.business.calendars.entities.AvailabilityTimeLine;
import org.libreplan.business.calendars.entities.BaseCalendar;
import org.libreplan.business.calendars.entities.ThereAreHoursOnWorkHoursCalculator;
import org.libreplan.business.calendars.entities.ThereAreHoursOnWorkHoursCalculator.CapacityResult;
import org.libreplan.business.planner.entities.DayAssignment;
import org.libreplan.business.planner.entities.GenericResourceAllocation;
import org.libreplan.business.planner.entities.ResourceAllocation;
import org.libreplan.business.planner.entities.ResourceAllocation.AllocationsSpecified.INotFulfilledReceiver;
import org.libreplan.business.planner.entities.ResourceAllocation.Direction;
import org.libreplan.business.planner.entities.SpecificResourceAllocation;
import org.libreplan.business.planner.entities.Task;
import org.libreplan.business.planner.entities.allocationalgorithms.ResourcesPerDayModification;
import org.libreplan.business.resources.entities.Resource;
import org.libreplan.business.resources.entities.Worker;
import org.libreplan.business.workingday.EffortDuration;
import org.libreplan.business.workingday.IntraDayDate;
import org.libreplan.business.workingday.IntraDayDate.PartialDay;
import org.libreplan.business.workingday.ResourcesPerDay;
public class UntilFillingHoursAllocatorTest {
private List<ResourcesPerDayModification> allocations = new ArrayList<>();
private List<Resource> resources = new ArrayList<>();
private Task task;
private IntraDayDate startDate;
private BaseCalendar taskCalendar;
private Integer initialLengthDaysForTask;
private IntraDayDate endDate;
@Test(expected = IllegalArgumentException.class)
public void allTasksOfAllocationsMustBeNotNull() {
givenAllocationsWithoutTask();
ResourceAllocation.allocating(allocations);
}
@Test(expected = IllegalArgumentException.class)
public void allAllocationsMustBelongToTheSameTask() {
givenAllocationsBelongingToDifferentTasks();
ResourceAllocation.allocating(allocations);
}
@Test(expected = IllegalArgumentException.class)
public void mustReceiveAtLeastOneAllocation() {
ResourceAllocation.allocating(new ArrayList<>());
}
@Test
public void theEndDateIsTheDayAfterAllTheHoursAreAllocatedIfItIsCompletelyFilled() {
givenSpecificAllocations(ResourcesPerDay.amount(2));
IntraDayDate endDate = ResourceAllocation.allocating(allocations).untilAllocating(hours(32));
assertThat(endDate.getDate(), equalTo(startDate.getDate().plusDays(2)));
assertTrue(endDate.isStartOfDay());
}
@Test
public void whenAllocatingUntilEndTheIntendedResourcesPerDayAreUpdated() {
ResourcesPerDay specifiedAmount = ResourcesPerDay.amount(2);
givenSpecificAllocations(specifiedAmount);
ResourceAllocation.allocating(allocations).untilAllocating(hours(32));
ResourcesPerDay intendedResourcesPerDay = allocations.get(0).getBeingModified().getIntendedResourcesPerDay();
assertThat(intendedResourcesPerDay, equalTo(specifiedAmount));
}
@Test
public void theEndDateIsTheSameDayIfItIsNotCompletelyFilled() {
givenSpecificAllocations(ResourcesPerDay.amount(1));
IntraDayDate endDate = ResourceAllocation.allocating(allocations).untilAllocating(hours(31));
assertThat(endDate.getDate(), equalTo(startDate.getDate().plusDays(3)));
assertThat(endDate.getEffortDuration(), equalTo(hours(7)));
}
@Test
public void theResourcesPerDayUsedInfluenceTheEndHourWhenLastDayNotCompletelyFilled() {
givenSpecificAllocations(ResourcesPerDay.amount(2));
IntraDayDate endDate = ResourceAllocation.allocating(allocations).untilAllocating(hours(20));
assertThat(endDate.getDate(), equalTo(startDate.getDate().plusDays(1)));
assertThat(endDate.getEffortDuration(), equalTo(hours(2)));
}
@Test
public void theEndDateIsTheDayAfterIfItIsCompletelyFilled() {
LocalDate start = new LocalDate();
givenStartDate(IntraDayDate.create(start, hours(1)));
givenSpecificAllocations(ResourcesPerDay.amount(1));
IntraDayDate endDate = ResourceAllocation.allocating(allocations).untilAllocating(hours(7));
assertThat(endDate, equalTo(startDate.nextDayAtStart()));
assertThat(endDate.getEffortDuration(), equalTo(hours(0)));
}
@Test
public void allTheRequestedHoursAreAssignedFor() {
givenSpecificAllocations(ResourcesPerDay.amount(2));
ResourceAllocation.allocating(allocations).untilAllocating(hours(32));
ResourceAllocation<?> allocation = allocations.get(0).getBeingModified();
assertThat(allocation.getAssignments(), haveHours(16, 16));
}
@Test
public void theAllocationCanBeDoneFromEnd() {
givenStartDate(IntraDayDate.startOfDay(new LocalDate(2009, 1, 10)));
givenTaskOfDaysLength(10); // so end is day 20
givenSpecificAllocations(ResourcesPerDay.amount(1));
IntraDayDate newStart = ResourceAllocation.allocating(allocations).untilAllocating(Direction.BACKWARD, hours(16));
assertThat(newStart, equalTo(IntraDayDate.startOfDay(new LocalDate(2009, 1, 18))));
}
@Test
public void theAllocationCanBeDoneFromAnEndThatIsInTheMiddleOfTheDay() {
givenStartDate(IntraDayDate.create(new LocalDate(2009, 1, 10), hours(4)));
givenEndDate(IntraDayDate.create(new LocalDate(2009, 1, 19), hours(2)));
givenSpecificAllocations(ResourcesPerDay.amount(1));
IntraDayDate newStart = ResourceAllocation.allocating(allocations).untilAllocating(Direction.BACKWARD, hours(10));
assertThat(newStart, equalTo(IntraDayDate.startOfDay(new LocalDate(2009, 1, 18))));
}
@Test
public void theAllocationCanEndOnTheSameDay() {
givenStartDate(IntraDayDate.create(new LocalDate(2009, 1, 10), hours(4)));
givenEndDate(IntraDayDate.create(new LocalDate(2009, 1, 19), hours(4)));
// 4 hours left for a one resource per day assignment, 8 hours left for two resources per day
givenSpecificAllocations(ResourcesPerDay.amount(2));
IntraDayDate newStart = ResourceAllocation.allocating(allocations).untilAllocating(Direction.BACKWARD, hours(6));
assertThat(newStart, equalTo(IntraDayDate.create(new LocalDate(2009, 1, 19), hours(1))));
}
@Test
public void theAllocationCanBeDoneFromEndAndTheStartDateIsCorrectlyCalculatedIfTheLastDayDoesNotTakeAll() {
givenStartDate(IntraDayDate.startOfDay(new LocalDate(2009, 1, 10)));
givenTaskOfDaysLength(10); // so end is day 20
givenSpecificAllocations(ResourcesPerDay.amount(1));
IntraDayDate newStart = ResourceAllocation.allocating(allocations).untilAllocating(Direction.BACKWARD, hours(14));
assertThat(newStart, equalTo(IntraDayDate.create(new LocalDate(2009, 1, 18), hours(2))));
}
@Test
public void theAllocationCanBeDoneFromTheEndAndResourcesPerDayInfluenceTheEndHour() {
givenStartDate(IntraDayDate.startOfDay(new LocalDate(2009, 1, 10)));
givenTaskOfDaysLength(10); // so end is day 20
givenSpecificAllocations(ResourcesPerDay.amount(2));
IntraDayDate newStart = ResourceAllocation.allocating(allocations).untilAllocating(Direction.BACKWARD, hours(20));
assertThat(newStart, equalTo(IntraDayDate.create(new LocalDate(2009, 1, 18), hours(6))));
}
@Test
public void ifNoAvailableHoursTheAllocationsAreNotSatisfied() {
AvailabilityTimeLine availability = AvailabilityTimeLine.allValid();
availability.invalidUntil(new LocalDate(2010, 11, 13));
availability.invalidFrom(new LocalDate(2010, 11, 15));
givenCalendarWithAvailability(availability, hours(8));
givenSpecificAllocations(ResourcesPerDay.amount(1));
ResourceAllocation.allocating(allocations).untilAllocating(hours(24));
for (ResourcesPerDayModification each : allocations) {
assertTrue(each.getBeingModified().isUnsatisfied());
}
}
@Test
public void ifAvailableHoursTheAllocationsAreSatisfied() {
AvailabilityTimeLine availability = AvailabilityTimeLine.allValid();
availability.invalidUntil(new LocalDate(2010, 11, 13));
availability.invalidFrom(new LocalDate(2010, 11, 15));
givenCalendarWithAvailability(availability, hours(8));
givenSpecificAllocations(ResourcesPerDay.amount(1));
ResourceAllocation.allocating(allocations).untilAllocating(hours(16));
for (ResourcesPerDayModification each : allocations) {
assertTrue(each.getBeingModified().isSatisfied());
}
}
@Test
public void ifNoAllocationsCantBeDoneTheTaskEndIsReturned() {
givenTaskOfDaysLength(10);
AvailabilityTimeLine availability = AvailabilityTimeLine.allValid();
availability.invalidUntil(new LocalDate(2010, 11, 13));
availability.invalidFrom(new LocalDate(2010, 11, 15));
givenCalendarWithAvailability(availability, hours(8));
givenSpecificAllocations(ResourcesPerDay.amount(1));
IntraDayDate end = ResourceAllocation.allocating(allocations).untilAllocating(hours(17));
IntraDayDate expectedEnd = IntraDayDate.startOfDay(task.getIntraDayStartDate().getDate().plusDays(10));
assertThat(end, equalTo(expectedEnd));
}
private void givenTaskOfDaysLength(int days) {
this.initialLengthDaysForTask = days;
}
@Test
public void theAllocationsThatAreNotSatisfiedAreNotified() {
AvailabilityTimeLine availability = AvailabilityTimeLine.allValid();
availability.invalidUntil(new LocalDate(2010, 11, 13));
availability.invalidFrom(new LocalDate(2010, 11, 15));
givenCalendarWithAvailability(availability, hours(8));
givenSpecificAllocations(ResourcesPerDay.amount(1), ResourcesPerDay.amount(2));
INotFulfilledReceiver receiver = createMock(INotFulfilledReceiver.class);
receiver.cantFulfill(isA(ResourcesPerDayModification.class), isA(CapacityResult.class));
expectLastCall().times(2);
replay(receiver);
ResourceAllocation.allocating(allocations).untilAllocating(hours(49), receiver);
verify(receiver);
}
@Test
public void theResourcesPerDayIsCalculatedCorrectlyIfTheLastDayHasFilledAllHours() {
givenSpecificAllocations(ResourcesPerDay.amount(1));
ResourceAllocation.allocating(allocations).untilAllocating(hours(32));
ResourceAllocation<?> allocation = allocations.get(0).getBeingModified();
assertThat(allocation.getResourcesPerDay(), equalTo(ResourcesPerDay.amount(1)));
}
@Test
public void theResourcesPerDayIsCalculatedCorrectlyIfHasEndedInTheMiddleOfTheEnd() {
givenSpecificAllocations(ResourcesPerDay.amount(2));
ResourceAllocation.allocating(allocations).untilAllocating(hours(30));
ResourceAllocation<?> allocation = allocations.get(0).getBeingModified();
assertThat(allocation.getResourcesPerDay(), equalTo(ResourcesPerDay.amount(2)));
}
@Test
public void theResourcesPerDayIsCalculatedCorrectlyIfTheStartIsInTheMiddleOfADay() {
givenStartDate(IntraDayDate.create(new LocalDate(2009, 10, 10), EffortDuration.hours(2)));
givenSpecificAllocations(ResourcesPerDay.amount(1));
ResourceAllocation.allocating(allocations).untilAllocating(hours(8));
ResourceAllocation<?> allocation = allocations.get(0).getBeingModified();
assertThat(allocation.getResourcesPerDay(), equalTo(ResourcesPerDay.amount(1)));
}
@Test
public void theEndDateIsCalculatedCorrectlyIfTheStartIsInTheMiddleOfADayAndEndsTheSameDay() {
givenStartDate(IntraDayDate.create(new LocalDate(2009, 10, 10), EffortDuration.hours(2)));
givenSpecificAllocations(ResourcesPerDay.amount(1));
ResourceAllocation.allocating(allocations).untilAllocating(hours(4));
ResourceAllocation<?> allocation = allocations.get(0).getBeingModified();
assertThat(allocation.getIntraDayEndDate(),
equalTo(IntraDayDate.create(new LocalDate(2009, 10, 10), EffortDuration.hours(6))));
}
@Test
public void theResourcesPerDayAreKeptCorrectlyCalculatedAfterUpdatingTheEndInterval() {
givenTaskOfDaysLength(10);
final ResourcesPerDay oneResourcePerDay = ResourcesPerDay.amount(1);
givenSpecificAllocations(oneResourcePerDay);
ResourceAllocation.allocating(allocations).untilAllocating(hours(30));
SpecificResourceAllocation allocation = (SpecificResourceAllocation) allocations.get(0).getBeingModified();
// hours per day: 8, 8, 8, 6
allocation.onIntervalWithinTask(startDate.getDate(), startDate.getDate().plusDays(1)).allocateHours(6);
// hours per day: 6, 8, 8, 6
assertTrue(allocation.getResourcesPerDay().getAmount().compareTo(oneResourcePerDay.getAmount()) < 0);
allocation.onIntervalWithinTask(startDate.getDate().plusDays(3), startDate.getDate().plusDays(4)).allocateHours(8);
// hours per day: 6, 8, 8, 8
assertThat(allocation.getResourcesPerDay(), equalTo(oneResourcePerDay));
// This last assertion is questionable.
// A solution would be to keep a spec object at ResourceAllocation with the desired parameters from
// the user and then the real values.
// In the meantime doing an effort to keep the original value.
allocation.onIntervalWithinTask(startDate.getDate().plusDays(4), startDate.getDate().plusDays(5)).allocateHours(8);
// hours per day: 6, 8, 8, 8, 8
assertTrue(allocation.getResourcesPerDay().getAmount().compareTo(oneResourcePerDay.getAmount()) < 0);
// hours per day: 6, 8, 8, 8, 10
allocation.onIntervalWithinTask(startDate.getDate().plusDays(4), startDate.getDate().plusDays(5)).allocateHours(10);
assertThat(allocation.getResourcesPerDay(), equalTo(oneResourcePerDay));
}
@Test
public void worksWellForSeveralSpecificAllocations() {
givenSpecificAllocations(ResourcesPerDay.amount(1), ResourcesPerDay.amount(1));
ResourceAllocation.allocating(allocations).untilAllocating(hours(32));
ResourceAllocation<?> first = allocations.get(0).getBeingModified();
ResourceAllocation<?> second = allocations.get(1).getBeingModified();
assertThat(first.getAssignments(), haveHours(8, 8));
assertThat(second.getAssignments(), haveHours(8, 8));
}
@Test
public void theRemainderIsProportionallyDistributed() {
givenSpecificAllocations(ResourcesPerDay.amount(2), ResourcesPerDay.amount(1));
ResourceAllocation.allocating(allocations).untilAllocating(hours(60));
ResourceAllocation<?> first = allocations.get(0).getBeingModified();
ResourceAllocation<?> second = allocations.get(1).getBeingModified();
assertThat(first.getAssignments(), haveHours(16, 16, 8));
assertThat(second.getAssignments(), haveHours(8, 8, 4));
}
@Test
public void withUnequalRatioWorksOk() {
givenSpecificAllocations(ResourcesPerDay.amount(1), ResourcesPerDay.amount(new BigDecimal(0.5)));
ResourceAllocation.allocating(allocations).untilAllocating(hours(36));
ResourceAllocation<?> first = allocations.get(0).getBeingModified();
ResourceAllocation<?> second = allocations.get(1).getBeingModified();
assertThat(first.getAssignments(), haveHours(8, 8, 8));
assertThat(second.getAssignments(), haveHours(4, 4, 4));
}
@Test
public void withGenericAllocationAlsoWorks() {
givenWorkers(1);
givenGenericAllocation(ResourcesPerDay.amount(2));
givenSpecificAllocations(ResourcesPerDay.amount(1), ResourcesPerDay.amount(1));
ResourceAllocation.allocating(allocations).untilAllocating(hours(64));
ResourceAllocation<?> generic = allocations.get(0).getBeingModified();
ResourceAllocation<?> firstSpecific = allocations.get(1).getBeingModified();
ResourceAllocation<?> secondSpecific = allocations.get(2).getBeingModified();
assertThat(generic.getAssignments(), haveHours(16, 16));
assertThat(firstSpecific.getAssignments(), haveHours(8, 8));
assertThat(secondSpecific.getAssignments(), haveHours(8, 8));
}
@Test
public void theResourcesPerDayInfuenceTheEndHourWhenUsingGenericAllocationOnOneWorkerForLastDay() {
givenWorkers(1);
givenGenericAllocation(ResourcesPerDay.amount(2));
IntraDayDate endDate = ResourceAllocation.allocating(allocations).untilAllocating(hours(20));
assertThat(endDate.getDate(), equalTo(startDate.getDate().plusDays(1)));
assertThat(endDate.getEffortDuration(), equalTo(hours(2)));
}
@Test
public void theHoursInLastDayAreDistributedConsideringResourcesPerDay() {
givenWorkers(2);
givenGenericAllocation(ResourcesPerDay.amount(2));
IntraDayDate endDate = ResourceAllocation.allocating(allocations).untilAllocating(hours(26));
assertThat(endDate.getDate(), equalTo(startDate.getDate().plusDays(1)));
assertThat(endDate.getEffortDuration(), equalTo(hours(5)));
Map<Resource, List<DayAssignment>> byResource =
DayAssignment.byResourceAndOrdered(allocations.get(0).getBeingModified().getAssignments());
for (Entry<Resource, List<DayAssignment>> each : byResource.entrySet()) {
List<DayAssignment> assignments = each.getValue();
assertThat(assignments.get(0).getDuration(), equalTo(hours(8)));
assertThat(assignments.get(1).getDuration(), equalTo(hours(5)));
}
}
@Test(expected = IllegalArgumentException.class)
public void withGenericAllocationWithNoResourcesPerDay() {
givenWorkers(1);
givenGenericAllocation(ResourcesPerDay.amount(0));
ResourceAllocation.allocating(allocations).untilAllocating(hours(100));
}
@Test(expected = IllegalArgumentException.class)
public void cannotDoAGenericAllocationWithoutWorkers() {
givenWorkers(0);
givenGenericAllocation(ResourcesPerDay.amount(2));
ResourceAllocation.allocating(allocations).untilAllocating(hours(100));
}
@Test
public void withoutWorkersYouCanDoSpecificAllocation() {
givenWorkers(0);
givenSpecificAllocations(ResourcesPerDay.amount(2));
ResourceAllocation.allocating(allocations).untilAllocating(hours(100));
}
private void givenGenericAllocation(ResourcesPerDay resourcesPerDay) {
createTaskIfNotCreatedYet();
allocations.add(ResourcesPerDayModification.create(
GenericResourceAllocation.create(task), resourcesPerDay, resources));
}
private void givenSpecificAllocations(ResourcesPerDay... specifiedResourcesPerDay) {
createTaskIfNotCreatedYet();
Worker worker = createWorker();
for (ResourcesPerDay resourcesPerDay : specifiedResourcesPerDay) {
SpecificResourceAllocation allocation = createSpecificResourceAllocationFor(task, worker);
allocations.add(ResourcesPerDayModification.create(allocation, resourcesPerDay));
}
}
private Worker createWorker() {
Worker worker = createNiceMock(Worker.class);
GenericResourceAllocationTest.mockZeroLoad(worker);
replay(worker);
return worker;
}
private void givenStartDate(IntraDayDate start) {
this.startDate = start;
}
private void givenEndDate(IntraDayDate end) {
this.endDate = end;
}
private void createTaskIfNotCreatedYet() {
if (task != null) {
return;
}
task = createNiceMock(Task.class);
if (startDate == null) {
startDate = IntraDayDate.startOfDay(new LocalDate(2009, 10, 10));
}
IntraDayDate end = null;
if (this.endDate != null) {
end = endDate;
} else if (initialLengthDaysForTask != null) {
LocalDate startPlusDays = startDate.getDate().plusDays(initialLengthDaysForTask);
end = IntraDayDate.startOfDay(startPlusDays);
}
expect(task.getStartDate()).andReturn(
startDate.toDateTimeAtStartOfDay().toDate()).anyTimes();
if (end != null) {
expect(task.getIntraDayEndDate()).andReturn(end).anyTimes();
}
expect(task.getIntraDayStartDate()).andReturn(startDate).anyTimes();
expect(task.getCriterions()).andReturn(Collections.emptySet()).anyTimes();
expect(task.getFirstDayNotConsolidated()).andReturn(startDate).anyTimes();
if (taskCalendar != null) {
expect(task.getCalendar()).andReturn(taskCalendar).anyTimes();
}
replay(task);
}
private void givenAllocationsWithoutTask() {
allocations.add(ResourcesPerDayModification.create(
createStubAllocationReturning(SpecificResourceAllocation.class, null),
ResourcesPerDay.amount(2)));
allocations.add(ResourcesPerDayModification.create(
createStubAllocationReturning(SpecificResourceAllocation.class, null),
ResourcesPerDay.amount(2)));
}
private void givenAllocationsBelongingToDifferentTasks() {
Task task = createStubTask();
allocations.add(ResourcesPerDayModification.create(
createStubAllocationReturning(SpecificResourceAllocation.class, task),
ResourcesPerDay.amount(2)));
allocations.add(ResourcesPerDayModification.create(
createStubAllocationReturning(SpecificResourceAllocation.class, task),
ResourcesPerDay.amount(2)));
Task other = createStubTask();
allocations.add(ResourcesPerDayModification.create(
createStubAllocationReturning(SpecificResourceAllocation.class, other),
ResourcesPerDay.amount(2)));
}
private Task createStubTask() {
Task task = createNiceMock(Task.class);
replay(task);
return task;
}
private void givenWorkers(int n) {
for (int i = 0; i < n; i++) {
resources.add(createWorker());
}
}
private SpecificResourceAllocation createSpecificResourceAllocationFor(Task task, Resource resource) {
SpecificResourceAllocation result = SpecificResourceAllocation.create(task);
result.setResource(resource);
return result;
}
private <T extends ResourceAllocation<?>> T createStubAllocationReturning(Class<T> allocationClass, Task task) {
T resourceAllocation = createNiceMock(allocationClass);
expect(resourceAllocation.getTask()).andReturn(task).anyTimes();
replay(resourceAllocation);
return resourceAllocation;
}
private BaseCalendar givenCalendarWithAvailability(final AvailabilityTimeLine availability, final EffortDuration workingDay) {
taskCalendar = mockCalendarWithAvailability(availability, workingDay);
return taskCalendar;
}
private BaseCalendar mockCalendarWithAvailability(final AvailabilityTimeLine availability, final EffortDuration workingDay) {
final BaseCalendar result = createNiceMock(BaseCalendar.class);
expect(result.getAvailability()).andReturn(availability).anyTimes();
expect(result.getCapacityOn(isA(PartialDay.class)))
.andAnswer(new IAnswer<EffortDuration>() {
@Override
public EffortDuration answer() throws Throwable {
PartialDay day = (PartialDay) getCurrentArguments()[0];
if (availability.isValid(day.getDate())) {
return day.limitWorkingDay(workingDay);
} else {
return zero();
}
}
})
.anyTimes();
expect(result.asDurationOn(isA(PartialDay.class), isA(ResourcesPerDay.class)))
.andAnswer(new IAnswer<EffortDuration>() {
@Override
public EffortDuration answer() throws Throwable {
PartialDay day = (PartialDay) getCurrentArguments()[0];
ResourcesPerDay resourcesPerDay = (ResourcesPerDay) getCurrentArguments()[1];
if (availability.isValid(day.getDate())) {
return day.limitWorkingDay(resourcesPerDay.asDurationGivenWorkingDayOf(workingDay));
} else {
return zero();
}
}
})
.anyTimes();
expect(result.thereAreCapacityFor(isA(AvailabilityTimeLine.class), isA(ResourcesPerDay.class), isA(EffortDuration.class)))
.andAnswer(new IAnswer<Boolean>() {
@Override
public Boolean answer() throws Throwable {
AvailabilityTimeLine availability = (AvailabilityTimeLine) getCurrentArguments()[0];
ResourcesPerDay resourcesPerDay = (ResourcesPerDay) getCurrentArguments()[1];
EffortDuration effortDuration = (EffortDuration) getCurrentArguments()[2];
return ThereAreHoursOnWorkHoursCalculator.thereIsAvailableCapacityFor(
result, availability, resourcesPerDay, effortDuration).thereIsCapacityAvailable();
}
})
.anyTimes();
replay(result);
return result;
}
}