Respect dependency constraints for manual allocation

Manual allocation, either appropriative and non-appropriative, didn't
respect dependency constraints. Now manual allocation respects
dependencies in the same manner as automatic allocation

FEA: ItEr65OTS04CorreccionsRecursosLimitantes
This commit is contained in:
Diego Pino Garcia 2010-12-16 12:02:13 +01:00
parent c3f78fcc8f
commit a2f359013e
4 changed files with 131 additions and 51 deletions

View file

@ -25,6 +25,7 @@ import static org.navalplanner.business.workingday.EffortDuration.zero;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
@ -65,6 +66,16 @@ public class Gap implements Comparable<Gap> {
return result;
}
public static List<GapOnQueue> onQueue(
LimitingResourceQueue queue, DateAndHour startTime,
DateAndHour endTime) {
Gap gap = (endTime == null || endTime.compareTo(startTime) <= 0) ? Gap
.untilEnd(queue.getResource(), startTime) : Gap.create(
queue.getResource(), startTime, endTime);
return GapOnQueue.onQueue(queue, Collections.singleton(gap));
}
private final LimitingResourceQueue originQueue;
private final Gap gap;
@ -93,7 +104,11 @@ public class Gap implements Comparable<Gap> {
public static Gap untilEnd(LimitingResourceQueueElement current,
DateAndHour startInclusive) {
return new Gap(current.getResource(), startInclusive, null);
return untilEnd(current.getResource(), startInclusive);
}
private static Gap untilEnd(Resource resource, DateAndHour startInclusive) {
return new Gap(resource, startInclusive, null);
}
private DateAndHour startTime;

View file

@ -21,6 +21,7 @@
package org.navalplanner.web.limitingresources;
import java.util.List;
import java.util.Set;
import org.navalplanner.business.orders.entities.Order;
import org.navalplanner.business.planner.entities.DayAssignment;
@ -55,7 +56,7 @@ import org.zkoss.ganttz.util.Interval;
*/
public interface ILimitingResourceQueueModel {
boolean nonAppropriativeAllocation(
List<LimitingResourceQueueElement> nonAppropriativeAllocation(
LimitingResourceQueueElement element, LimitingResourceQueue queue, DateAndHour time);
/**
@ -127,7 +128,8 @@ public interface ILimitingResourceQueueModel {
* @param queue
* @param allocationTime
*/
void appropriativeAllocation(LimitingResourceQueueElement element, LimitingResourceQueue queue,
Set<LimitingResourceQueueElement> appropriativeAllocation(
LimitingResourceQueueElement element, LimitingResourceQueue queue,
DateAndHour allocationTime);
void unschedule(LimitingResourceQueueElement element);

View file

@ -415,6 +415,7 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
@Override
public List<LimitingResourceQueueElement> assignLimitingResourceQueueElement(
LimitingResourceQueueElement externalQueueElement) {
InsertionRequirements requirements = queuesState
.getRequirementsFor(externalQueueElement);
AllocationSpec allocationDone = insertAtGap(requirements);
@ -612,19 +613,46 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
return Collections.singletonList(each);
}
private void applyAllocation(AllocationSpec allocationStillNotDone) {
private void applyAllocation(final AllocationSpec allocationStillNotDone) {
applyAllocation(allocationStillNotDone, new IDayAssignmentBehaviour() {
@Override
public void allocateDayAssigments() {
ResourceAllocation<?> resourceAllocation = getResourceAllocation(allocationStillNotDone);
Resource resource = getResource(allocationStillNotDone);
List<DayAssignment> assignments = allocationStillNotDone.getAssignmentsFor(
resourceAllocation, resource);
resourceAllocation.allocateLimitingDayAssignments(assignments);
}
private ResourceAllocation<?> getResourceAllocation(AllocationSpec allocation) {
return allocation.getElement().getResourceAllocation();
}
private Resource getResource(AllocationSpec allocation) {
return allocation.getQueue().getResource();
}
});
}
private void applyAllocation(AllocationSpec allocationStillNotDone,
IDayAssignmentBehaviour allocationBehaviour) {
// Do day allocation
allocationBehaviour.allocateDayAssigments();
LimitingResourceQueueElement element = allocationStillNotDone
.getElement();
.getElement();
LimitingResourceQueue queue = allocationStillNotDone.getQueue();
Resource resource = queue.getResource();
ResourceAllocation<?> resourceAllocation = element.getResourceAllocation();
List<DayAssignment> assignments = allocationStillNotDone
.getAssignmentsFor(resourceAllocation, resource);
resourceAllocation
.allocateLimitingDayAssignments(assignments);
// Update start and end time of task
updateStartAndEndTimes(element, allocationStillNotDone
.getStartInclusive(), allocationStillNotDone
.getEndExclusive());
// Add to queue and mark as modified
addLimitingResourceQueueElementIfNeeded(queue, element);
markAsModified(element);
}
@ -635,43 +663,64 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
.getEarliestEndDateBecauseOfGantt()));
}
private boolean assignLimitingResourceQueueElementToQueueAt(
LimitingResourceQueueElement element, LimitingResourceQueue queue,
DateAndHour startTime, DateAndHour endsAfter) {
private List<LimitingResourceQueueElement> assignLimitingResourceQueueElementToQueueAt(
final LimitingResourceQueueElement element,
final LimitingResourceQueue queue, final DateAndHour startTime,
final DateAndHour endsAfter) {
// Allocate day assignments and adjust start and end times for element
List<DayAssignment> dayAssignments = LimitingResourceAllocator
.generateDayAssignments(element.getResourceAllocation(), queue
.getResource(), startTime, endsAfter);
element.getResourceAllocation().allocateLimitingDayAssignments(
dayAssignments);
DateAndHour endTime = endFor(dayAssignments);
// the assignments can be generated after the required start
startTime = DateAndHour.max(startTime, startFor(dayAssignments));
if (sameDay(startTime, endTime)) {
endTime = new DateAndHour(endTime.getDate(), startTime.getHour() + endTime.getHour());
// Check if allocation is possible
InsertionRequirements requirements = queuesState
.getRequirementsFor(element);
List<GapOnQueue> gapOnQueue = GapOnQueue.onQueue(queue, startTime,
endsAfter);
AllocationSpec allocation = requirements.guessValidity(gapOnQueue
.iterator().next());
if (!allocation.isValid()) {
return Collections.emptyList();
}
updateStartAndEndTimes(element, startTime, endTime);
// Add element to queue
addLimitingResourceQueueElementIfNeeded(queue, element);
markAsModified(element);
return true;
// Do allocation
applyAllocation(allocation, new IDayAssignmentBehaviour() {
@Override
public void allocateDayAssigments() {
List<DayAssignment> assignments = LimitingResourceAllocator
.generateDayAssignments(
element.getResourceAllocation(),
queue.getResource(), startTime, endsAfter);
element.getResourceAllocation().allocateLimitingDayAssignments(
assignments);
}
});
assert allocation.isValid();
// Move other tasks to respect dependency constraints
List<LimitingResourceQueueElement> result = new ArrayList<LimitingResourceQueueElement>();
result.add(requirements.getElement());
List<LimitingResourceQueueElement> moved = shift(
queuesState.getPotentiallyAffectedByInsertion(element),
requirements.getElement(), allocation);
// Return all moved tasks (including the allocated one)
result.addAll(moved);
return result;
}
private DateAndHour endFor(List<DayAssignment> dayAssignments) {
DayAssignment last = dayAssignments.get(dayAssignments.size() - 1);
return new DateAndHour(last.getDay(), 0);
}
/**
*
* Describes how day assignments are going to be generated for an allocation
*
* @author Diego Pino García<dpino@igalia.com>
*
*/
private interface IDayAssignmentBehaviour {
private DateAndHour startFor(List<DayAssignment> dayAssignments) {
return new DateAndHour(dayAssignments
.get(0).getDay(), 0);
}
void allocateDayAssigments();
private boolean sameDay(DateAndHour startTime, DateAndHour endTime) {
return startTime.getDate().equals(endTime.getDate());
}
private void markAsModified(LimitingResourceQueueElement element) {
@ -890,7 +939,7 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
}
@Override
public boolean nonAppropriativeAllocation(
public List<LimitingResourceQueueElement> nonAppropriativeAllocation(
LimitingResourceQueueElement element,
LimitingResourceQueue queue,
DateAndHour startTime) {
@ -918,9 +967,11 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
@Override
public void appropriativeAllocation(LimitingResourceQueueElement _element, LimitingResourceQueue _queue,
public Set<LimitingResourceQueueElement> appropriativeAllocation(LimitingResourceQueueElement _element, LimitingResourceQueue _queue,
DateAndHour allocationTime) {
Set<LimitingResourceQueueElement> result = new HashSet<LimitingResourceQueueElement>();
LimitingResourceQueue queue = queuesState.getEquivalent(_queue);
LimitingResourceQueueElement element = queuesState.getEquivalent(_element);
@ -938,8 +989,9 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
final LocalDate startDate = gap.getStartTime().getDate();
if (startDate.equals(allocationTime.getDate())) {
assignLimitingResourceQueueElementToQueueAt(element, queue,
allocationTime, getEndsAfterBecauseOfGantt(element));
result.addAll(assignLimitingResourceQueueElementToQueueAt(
element, queue, allocationTime,
getEndsAfterBecauseOfGantt(element)));
break;
} else {
LimitingResourceQueueElement elementAtTime = getFirstElementFrom(
@ -954,10 +1006,11 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
for (LimitingResourceQueueElement each: unscheduledElements) {
gap = LimitingResourceAllocator.getFirstValidGap(queue, each);
assignLimitingResourceQueueElementToQueueAt(each, queue, gap
.getStartTime(), getEndsAfterBecauseOfGantt(element));
result.addAll(assignLimitingResourceQueueElementToQueueAt(each, queue, gap
.getStartTime(), getEndsAfterBecauseOfGantt(element)));
}
return result;
}
@SuppressWarnings("unchecked")

View file

@ -22,10 +22,12 @@ package org.navalplanner.web.limitingresources;
import static org.navalplanner.web.I18nHelper._;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.Validate;
import org.joda.time.LocalDate;
@ -278,15 +280,23 @@ public class ManualAllocationController extends GenericForwardComposer {
private void nonAppropriativeAllocation(LimitingResourceQueueElement element, LimitingResourceQueue queue, DateAndHour time) {
Validate.notNull(time);
getLimitingResourceQueueModel()
List<LimitingResourceQueueElement> inserted = getLimitingResourceQueueModel()
.nonAppropriativeAllocation(element, queue, time);
limitingResourcesPanel.appendQueueElementToQueue(element);
refreshQueues(inserted);
}
private void appropriativeAllocation(LimitingResourceQueueElement element, LimitingResourceQueue queue, DateAndHour time) {
Validate.notNull(time);
getLimitingResourceQueueModel().appropriativeAllocation(element, queue, time);
limitingResourcesPanel.refreshQueue(queue);
Set<LimitingResourceQueueElement> inserted = getLimitingResourceQueueModel()
.appropriativeAllocation(element, queue, time);
refreshQueues(inserted);
}
private void refreshQueues(Collection<LimitingResourceQueueElement> movedElements) {
for (LimitingResourceQueueElement each : movedElements) {
limitingResourcesPanel.removeDependencyComponentsFor(each);
limitingResourcesPanel.refreshQueue(each.getLimitingResourceQueue());
}
}
private DateAndHour getSelectedAllocationTime() {