From ca94734770ae5bf5d333bb8f9e796bb3cc4591e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=93scar=20Gonz=C3=A1lez=20Fern=C3=A1ndez?= Date: Tue, 19 Oct 2010 00:27:55 +0200 Subject: [PATCH] Add mechanism for being notified of ResourceAllocations for which there are no capacity FEA: ItEr62S05BugFixing --- .../planner/entities/ResourceAllocation.java | 40 ++++++++++++++++--- .../UntilFillingHoursAllocator.java | 18 +++++---- .../UntilFillingHoursAllocatorTest.java | 23 +++++++++++ 3 files changed, 68 insertions(+), 13 deletions(-) diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/ResourceAllocation.java b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/ResourceAllocation.java index 2d1d3d5ac..875d908df 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/ResourceAllocation.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/ResourceAllocation.java @@ -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 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 extends } @Override - protected boolean thereAreAvailableHoursFrom( + protected CapacityResult thereAreAvailableHoursFrom( IntraDayDate start, ResourcesPerDayModification resourcesPerDayModification, EffortDuration effortToAllocate) { @@ -250,8 +273,10 @@ public abstract class ResourceAllocation 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 extends } @Override - protected void markUnsatisfied(ResourceAllocation allocation) { - allocation.markAsUnsatisfied(); + protected void markUnsatisfied( + ResourcesPerDayModification allocationAttempt, + CapacityResult capacityResult) { + allocationAttempt.getBeingModified().markAsUnsatisfied(); + receiver.cantFulfill(allocationAttempt, capacityResult); } }; diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/allocationalgorithms/UntilFillingHoursAllocator.java b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/allocationalgorithms/UntilFillingHoursAllocator.java index 84e0158f7..71fd66151 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/allocationalgorithms/UntilFillingHoursAllocator.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/allocationalgorithms/UntilFillingHoursAllocator.java @@ -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 hoursPerAllocations) { List cannotSatisfy = new ArrayList(); 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; diff --git a/navalplanner-business/src/test/java/org/navalplanner/business/test/planner/entities/UntilFillingHoursAllocatorTest.java b/navalplanner-business/src/test/java/org/navalplanner/business/test/planner/entities/UntilFillingHoursAllocatorTest.java index 728962e5f..dc12e070c 100644 --- a/navalplanner-business/src/test/java/org/navalplanner/business/test/planner/entities/UntilFillingHoursAllocatorTest.java +++ b/navalplanner-business/src/test/java/org/navalplanner/business/test/planner/entities/UntilFillingHoursAllocatorTest.java @@ -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));