From 71461a5092c4d6a4c30dff9efe0677f4ef84b220 Mon Sep 17 00:00:00 2001 From: Diego Pino Garcia Date: Mon, 31 Jan 2011 00:43:49 +0100 Subject: [PATCH] [Bug 827] Fix bug do appropriative allocation if required based on days constraints Allocate element at correct position if day constraints required an appropriative allocation Reschedule elements affected by an allocation to avoid dependencies violations FEA: ItEr69S04BugFixing --- .../LimitingResourceQueueModel.java | 87 ++++++++++--------- 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourceQueueModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourceQueueModel.java index 7d0710d26..3bf802d24 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourceQueueModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourceQueueModel.java @@ -30,7 +30,6 @@ import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -438,35 +437,41 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel { queuesState .getPotentiallyAffectedByInsertion(externalQueueElement), requirements.getElement(), allocation); - result.addAll(moved); - result.addAll(scheduleUnscheduledElementsIfNeeded(allocation)); + result.addAll(rescheduleAffectedElementsToSatisfyDependencies(allocation, moved)); return result; } - private Collection scheduleUnscheduledElementsIfNeeded( - AllocationSpec allocation) { + /** + * After an allocation dependencies might be broken, this method unschedules + * elements affected by an allocation and reschedule them again in + * topological order, so dependencies are satisfied + * + * If the allocation was appropriative it also allocates those elements that + * might be unscheduled before due to the appropriative allocation + * + * @param allocation + * @param moved + * @return + */ + private Collection rescheduleAffectedElementsToSatisfyDependencies( + AllocationSpec allocation, List moved) { List result = new ArrayList(); + List toReschedule = new ArrayList(); - if (allocation.isAppropriative()) { - checkAllocationIsAppropriative(false); - - // Assign all unscheduled elements - List unscheduled = allocation.getUnscheduledElements(); - for (LimitingResourceQueueElement each: unscheduled) { - result.addAll(assignLimitingResourceQueueElement(each)); - } - - // Only for those originally unscheduled elements, unschedule and - // schedule them again to force dependencies are satisfied - for (LimitingResourceQueueElement each: unscheduled) { - unschedule(each); - assignLimitingResourceQueueElement(each); - } - - checkAllocationIsAppropriative(true); + checkAllocationIsAppropriative(false); + for (LimitingResourceQueueElement each: moved) { + toReschedule.add(unschedule(each)); } + if (allocation.isAppropriative()) { + toReschedule.addAll(allocation.getUnscheduledElements()); + } + for (LimitingResourceQueueElement each: queuesState.inTopologicalOrder(toReschedule)) { + result.addAll(assignLimitingResourceQueueElement(each)); + } + checkAllocationIsAppropriative(true); + return result; } @@ -652,7 +657,7 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel { if (allocation != null) { if (checkAllocationIsAppropriative() && requirements.isAppropiativeAllocation(allocation)) { - doAppropriativeAllocation(requirements, allocation); + return doAppropriativeAllocation(requirements, allocation); } return allocation; } @@ -687,10 +692,9 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel { LimitingResourceQueue queue = queuesState.getQueueFor(element .getResource()); - List unscheduled = unscheduleElementsFor( - queue, requirements); + List unscheduled = new ArrayList(); + allocation = unscheduleElementsFor(queue, requirements, unscheduled); allocation.setUnscheduledElements(queuesState.inTopologicalOrder(unscheduled)); - return allocation; } @@ -800,8 +804,7 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel { List moved = shift( queuesState.getPotentiallyAffectedByInsertion(element), requirements.getElement(), allocation); - result.addAll(moved); - result.addAll(scheduleUnscheduledElementsIfNeeded(allocation)); + result.addAll(rescheduleAffectedElementsToSatisfyDependencies(allocation, moved)); return result; } @@ -1079,9 +1082,10 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel { unschedule(element); } - // Unschedule elements in queue since allocationTime - List toSchedule = new ArrayList( - unscheduleElementsFor(queue, requirements)); + // Unschedule elements in queue since allocationTime and put them in + // toSchedule + List toSchedule = new ArrayList(); + unscheduleElementsFor(queue, requirements, toSchedule); result.addAll(assignLimitingResourceQueueElementToQueueAt(element, queue, allocationTime, getEndsAfterBecauseOfGantt(element))); @@ -1106,31 +1110,29 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel { * @param requirements * @return */ - private List unscheduleElementsFor( - LimitingResourceQueue queue, InsertionRequirements requirements) { - - List result = new ArrayList(); - + private AllocationSpec unscheduleElementsFor( + LimitingResourceQueue queue, InsertionRequirements requirements, + List result) { DateAndHour allocationTime = requirements.getEarliestPossibleStart(); List gapsWithQueueElements = queuesState .getGapsWithQueueElementsOnQueueSince(queue, allocationTime); - unscheduleElementsFor(gapsWithQueueElements, requirements, result); - return result; + + return unscheduleElementsFor(gapsWithQueueElements, requirements, result); } - private void unscheduleElementsFor(List gaps, + private AllocationSpec unscheduleElementsFor(List gaps, InsertionRequirements requirements, List result) { if (gaps.isEmpty()) { - return; + return null; } GapOnQueueWithQueueElement first = gaps.get(0); GapOnQueue gapOnQueue = first.getGapOnQueue(); if (gapOnQueue != null) { AllocationSpec allocation = requirements.guessValidity(gapOnQueue); if (allocation.isValid()) { - return; + return allocation; } } result.add(unschedule(first.getQueueElement())); @@ -1138,10 +1140,9 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel { gaps.set(1, GapOnQueueWithQueueElement.coalesce(first, gaps.get(1))); } gaps.remove(0); - unscheduleElementsFor(gaps, requirements, result); + return unscheduleElementsFor(gaps, requirements, result); } - @SuppressWarnings("unchecked") public LimitingResourceQueueElement getFirstElementFrom(LimitingResourceQueue queue, DateAndHour allocationTime) { final List elements = new ArrayList(queue.getLimitingResourceQueueElements());