Add mechanism for being notified of ResourceAllocations for which there are no capacity

FEA: ItEr62S05BugFixing
This commit is contained in:
Óscar González Fernández 2010-10-19 00:27:55 +02:00
parent 56f38d0d9f
commit ca94734770
3 changed files with 68 additions and 13 deletions

View file

@ -46,13 +46,15 @@ import org.navalplanner.business.calendars.entities.BaseCalendar;
import org.navalplanner.business.calendars.entities.CombinedWorkHours;
import org.navalplanner.business.calendars.entities.ICalendar;
import org.navalplanner.business.calendars.entities.SameWorkHoursEveryDay;
import org.navalplanner.business.calendars.entities.ThereAreHoursOnWorkHoursCalculator;
import org.navalplanner.business.calendars.entities.ThereAreHoursOnWorkHoursCalculator.CapacityResult;
import org.navalplanner.business.common.BaseEntity;
import org.navalplanner.business.common.Registry;
import org.navalplanner.business.planner.entities.DerivedAllocationGenerator.IWorkerFinder;
import org.navalplanner.business.planner.entities.allocationalgorithms.UntilFillingHoursAllocator;
import org.navalplanner.business.planner.entities.allocationalgorithms.AllocatorForTaskDurationAndSpecifiedResourcesPerDay;
import org.navalplanner.business.planner.entities.allocationalgorithms.HoursModification;
import org.navalplanner.business.planner.entities.allocationalgorithms.ResourcesPerDayModification;
import org.navalplanner.business.planner.entities.allocationalgorithms.UntilFillingHoursAllocator;
import org.navalplanner.business.planner.limiting.entities.LimitingResourceQueueElement;
import org.navalplanner.business.resources.daos.IResourceDAO;
import org.navalplanner.business.resources.entities.Machine;
@ -220,7 +222,28 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
}
}
public interface INotFulfilledReceiver {
public void cantFulfill(
ResourcesPerDayModification allocationAttempt,
CapacityResult capacityResult);
}
public IntraDayDate untilAllocating(int hoursToAllocate) {
return untilAllocating(hoursToAllocate, doNothing());
}
private static INotFulfilledReceiver doNothing() {
return new INotFulfilledReceiver() {
@Override
public void cantFulfill(
ResourcesPerDayModification allocationAttempt,
CapacityResult capacityResult) {
}
};
}
public IntraDayDate untilAllocating(int hoursToAllocate,
final INotFulfilledReceiver receiver) {
UntilFillingHoursAllocator allocator = new UntilFillingHoursAllocator(
task, allocations) {
@ -240,7 +263,7 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
}
@Override
protected boolean thereAreAvailableHoursFrom(
protected CapacityResult thereAreAvailableHoursFrom(
IntraDayDate start,
ResourcesPerDayModification resourcesPerDayModification,
EffortDuration effortToAllocate) {
@ -250,8 +273,10 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
AvailabilityTimeLine availability = resourcesPerDayModification
.getAvailability();
availability.invalidUntil(start.asExclusiveEnd());
return calendar.thereAreCapacityFor(availability,
resourcesPerDay, effortToAllocate);
return ThereAreHoursOnWorkHoursCalculator
.thereIsAvailableCapacityFor(calendar,
availability, resourcesPerDay,
effortToAllocate);
}
private CombinedWorkHours getCalendar(
@ -262,8 +287,11 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
}
@Override
protected void markUnsatisfied(ResourceAllocation<?> allocation) {
allocation.markAsUnsatisfied();
protected void markUnsatisfied(
ResourcesPerDayModification allocationAttempt,
CapacityResult capacityResult) {
allocationAttempt.getBeingModified().markAsUnsatisfied();
receiver.cantFulfill(allocationAttempt, capacityResult);
}
};

View file

@ -31,6 +31,7 @@ import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.lang.Validate;
import org.navalplanner.business.calendars.entities.ThereAreHoursOnWorkHoursCalculator.CapacityResult;
import org.navalplanner.business.common.ProportionalDistributor;
import org.navalplanner.business.planner.entities.DayAssignment;
import org.navalplanner.business.planner.entities.ResourceAllocation;
@ -142,11 +143,14 @@ public abstract class UntilFillingHoursAllocator {
ResourcesPerDayModification allocation, PartialDay day,
EffortDuration limit);
protected abstract boolean thereAreAvailableHoursFrom(IntraDayDate start,
protected abstract CapacityResult thereAreAvailableHoursFrom(
IntraDayDate start,
ResourcesPerDayModification resourcesPerDayModification,
EffortDuration remainingDuration);
protected abstract void markUnsatisfied(ResourceAllocation<?> beingModified);
protected abstract void markUnsatisfied(
ResourcesPerDayModification allocationAttempt,
CapacityResult capacityResult);
private EffortDuration assignForDay(
ResourcesPerDayModification resourcesPerDayModification,
@ -203,9 +207,6 @@ public abstract class UntilFillingHoursAllocator {
if (unsatisfied.isEmpty()) {
return result;
}
for (ResourcesPerDayModification each : unsatisfied) {
markUnsatisfied(each.getBeingModified());
}
allocations.removeAll(unsatisfied);
} while (!allocations.isEmpty());
return Collections.emptyList();
@ -216,9 +217,12 @@ public abstract class UntilFillingHoursAllocator {
List<EffortPerAllocation> hoursPerAllocations) {
List<ResourcesPerDayModification> cannotSatisfy = new ArrayList<ResourcesPerDayModification>();
for (EffortPerAllocation each : hoursPerAllocations) {
if (!thereAreAvailableHoursFrom(start, each.allocation,
each.duration)) {
CapacityResult capacityResult = thereAreAvailableHoursFrom(
start, each.allocation,
each.duration);
if (!capacityResult.thereIsCapacityAvailable()) {
cannotSatisfy.add(each.allocation);
markUnsatisfied(each.allocation, capacityResult);
}
}
return cannotSatisfy;

View file

@ -21,8 +21,11 @@
package org.navalplanner.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.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.createNiceMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.hamcrest.CoreMatchers.equalTo;
@ -43,8 +46,10 @@ import org.junit.Test;
import org.navalplanner.business.calendars.entities.AvailabilityTimeLine;
import org.navalplanner.business.calendars.entities.BaseCalendar;
import org.navalplanner.business.calendars.entities.ThereAreHoursOnWorkHoursCalculator;
import org.navalplanner.business.calendars.entities.ThereAreHoursOnWorkHoursCalculator.CapacityResult;
import org.navalplanner.business.planner.entities.GenericResourceAllocation;
import org.navalplanner.business.planner.entities.ResourceAllocation;
import org.navalplanner.business.planner.entities.ResourceAllocation.AllocationsSpecified.INotFulfilledReceiver;
import org.navalplanner.business.planner.entities.SpecificResourceAllocation;
import org.navalplanner.business.planner.entities.Task;
import org.navalplanner.business.planner.entities.allocationalgorithms.ResourcesPerDayModification;
@ -139,6 +144,24 @@ public class UntilFillingHoursAllocatorTest {
}
}
@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(49, receiver);
verify(receiver);
}
@Test
public void theResourcesPerDayIsCalculatedCorrectlyIfTheLastDayHasFilledAllHours() {
givenSpecificAllocations(ResourcesPerDay.amount(1));