ItEr59S08CUAsignacionRecursosLimitantesItEr58S10: Handle outcoming dependencies to already assigned elements

This commit is contained in:
Óscar González Fernández 2010-06-07 01:47:48 +02:00
parent cd0cfc04b6
commit 5f3d6fe72d
5 changed files with 136 additions and 35 deletions

View file

@ -38,10 +38,8 @@ import org.navalplanner.business.resources.entities.LimitingResourceQueue;
import org.navalplanner.business.resources.entities.Resource;
/**
*
* Entity which represents an element in the queue which represents
* the limiting resources.
*
* Entity which represents an element in the queue which represents the limiting
* resources.
* @author Diego Pino Garcia <dpino@igalia.com>
* @author Javier Moran Rua <jmoran@igalia.com>
*/
@ -61,11 +59,9 @@ public class LimitingResourceQueueElement extends BaseEntity {
private long creationTimestamp;
private Set<LimitingResourceQueueDependency> dependenciesAsOrigin =
new HashSet<LimitingResourceQueueDependency>();
private Set<LimitingResourceQueueDependency> dependenciesAsOrigin = new HashSet<LimitingResourceQueueDependency>();
private Set<LimitingResourceQueueDependency> dependenciesAsDestiny =
new HashSet<LimitingResourceQueueDependency>();
private Set<LimitingResourceQueueDependency> dependenciesAsDestiny = new HashSet<LimitingResourceQueueDependency>();
public static LimitingResourceQueueElement create() {
return create(new LimitingResourceQueueElement());
@ -91,7 +87,8 @@ public class LimitingResourceQueueElement extends BaseEntity {
return limitingResourceQueue;
}
public void setLimitingResourceQueue(LimitingResourceQueue limitingResourceQueue) {
public void setLimitingResourceQueue(
LimitingResourceQueue limitingResourceQueue) {
this.limitingResourceQueue = limitingResourceQueue;
}
@ -175,9 +172,10 @@ public class LimitingResourceQueueElement extends BaseEntity {
} else if (d.getHasAsDestiny().equals(this)) {
dependenciesAsDestiny.add(d);
} else {
throw new IllegalArgumentException("It cannot be added a dependency" +
" in which the current queue element is neither origin" +
" not desinty");
throw new IllegalArgumentException(
"It cannot be added a dependency"
+ " in which the current queue element is neither origin"
+ " not desinty");
}
}

View file

@ -60,26 +60,22 @@ public interface ILimitingResourceQueueModel {
/**
* Assigns a {@link LimitingResourceQueueElement} to its corresponding
* {@link LimitingResourceQueue}
*
* There is one and only one queue for every limiting resource. An element
* is assigned to its queue searching by element.resource.
*
* Allocation within the queue is done by finding the first gap in the queue
* that fits the initial intented hours assigned to
* element.resourceallocation.
*
* The method also generates {@link DayAssignment} once the allocation is
* done
*
* Returns true if the process was successful. The only case were an
* allocation cannot be done is if there's not any queue that can hold the
* element (only for a generic allocation, there's not any queue that
* matches the criteria of the element)
*
* {@link LimitingResourceQueue} There is one and only one queue for every
* limiting resource. An element is assigned to its queue searching by
* element.resource. Allocation within the queue is done by finding the
* first gap in the queue that fits the initial intented hours assigned to
* element.resourceallocation. The method also generates
* {@link DayAssignment} once the allocation is done Returns the inserted
* queue elements. More than one can be inserted because inserting
* <code>element</code> can imply to move its sucessors.<br />
* The only case were an allocation cannot be done is if there's not any
* queue that can hold the element (only for a generic allocation, there's
* not any queue that matches the criteria of the element). In this case an
* empty list is returned
* @param element
*/
boolean assignLimitingResourceQueueElement(LimitingResourceQueueElement element);
List<LimitingResourceQueueElement> assignLimitingResourceQueueElement(
LimitingResourceQueueElement element);
ZoomLevel calculateInitialZoomLevel();

View file

@ -390,9 +390,22 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
}
@Override
public boolean assignLimitingResourceQueueElement(
public List<LimitingResourceQueueElement> assignLimitingResourceQueueElement(
LimitingResourceQueueElement externalQueueElement) {
GapRequirements requirements = queuesState.getRequirementsFor(externalQueueElement);
List<LimitingResourceQueueElement> result = new ArrayList<LimitingResourceQueueElement>();
for (LimitingResourceQueueElement each : queuesState
.getInsertionsToBeDoneFor(externalQueueElement)) {
GapRequirements requirements = queuesState.getRequirementsFor(each);
boolean inserted = insert(requirements);
if (!inserted) {
break;
}
result.add(requirements.getElement());
}
return result;
}
private boolean insert(GapRequirements requirements) {
List<GapOnQueue> potentiallyValidGapsFor = queuesState
.getPotentiallyValidGapsFor(requirements);
boolean generic = requirements.getElement().isGeneric();

View file

@ -406,10 +406,16 @@ public class LimitingResourcesController extends GenericForwardComposer {
LimitingResourceQueueElementDTO dto) {
LimitingResourceQueueElement element = dto.getOriginal();
if (limitingResourceQueueModel
.assignLimitingResourceQueueElement(element)) {
List<LimitingResourceQueueElement> inserted = limitingResourceQueueModel
.assignLimitingResourceQueueElement(element);
if (!inserted.isEmpty()) {
Util.reloadBindings(gridUnassignedLimitingResourceQueueElements);
limitingResourcesPanel.appendQueueElementToQueue(element);
for (LimitingResourceQueueElement each : inserted) {
// FIXME visually wrong if an element jumps from a queue to
// another
limitingResourcesPanel.refreshQueue(each
.getLimitingResourceQueue());
}
} else {
showErrorMessage(_("Cannot allocate selected element. There is not any queue " +
"that matches resource allocation criteria at any interval of time"));

View file

@ -23,13 +23,16 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.Validate;
import org.jgrapht.DirectedGraph;
import org.jgrapht.alg.CycleDetector;
import org.jgrapht.graph.SimpleDirectedGraph;
import org.jgrapht.traverse.TopologicalOrderIterator;
import org.navalplanner.business.common.BaseEntity;
import org.navalplanner.business.planner.entities.GenericResourceAllocation;
import org.navalplanner.business.planner.entities.ResourceAllocation;
@ -119,6 +122,8 @@ public class QueuesState {
LimitingResourceQueueDependency dependency) {
LimitingResourceQueueElement origin = dependency.getHasAsOrigin();
LimitingResourceQueueElement destination = dependency.getHasAsDestiny();
result.addVertex(origin);
result.addVertex(destination);
result.addEdge(origin, destination, dependency);
}
@ -242,4 +247,87 @@ public class QueuesState {
return result;
}
/**
* @param externalQueueElement
* the queue element to insert
* @return the list of elements that must be reinserted due to the insertion
* of <code>externalQueueElement</code>
*/
public List<LimitingResourceQueueElement> getInsertionsToBeDoneFor(
LimitingResourceQueueElement externalQueueElement) {
LimitingResourceQueueElement queueElement = getEquivalent(externalQueueElement);
DirectedGraph<LimitingResourceQueueElement, LimitingResourceQueueDependency> subGraph = buildOutgoingGraphFor(queueElement);
CycleDetector<LimitingResourceQueueElement, LimitingResourceQueueDependency> cycleDetector = cycleDetector(subGraph);
if (cycleDetector.detectCycles()) {
throw new IllegalStateException("subgraph has cycles");
}
List<LimitingResourceQueueElement> result = new ArrayList<LimitingResourceQueueElement>();
result.add(queueElement);
result.addAll(getElementsOrderedTopologically(subGraph));
unassignFromQueues(result);
return result;
}
private DirectedGraph<LimitingResourceQueueElement, LimitingResourceQueueDependency> buildOutgoingGraphFor(
LimitingResourceQueueElement queueElement) {
SimpleDirectedGraph<LimitingResourceQueueElement, LimitingResourceQueueDependency> result = instantiateDirectedGraph();
buildOutgoingGraphFor(result, queueElement);
return result;
}
private void buildOutgoingGraphFor(
DirectedGraph<LimitingResourceQueueElement, LimitingResourceQueueDependency> result,
LimitingResourceQueueElement element) {
Set<LimitingResourceQueueDependency> outgoingEdgesOf = graph
.outgoingEdgesOf(element);
for (LimitingResourceQueueDependency each : outgoingEdgesOf) {
addDependency(result, each);
buildOutgoingGraphFor(result, each.getHasAsDestiny());
}
}
private CycleDetector<LimitingResourceQueueElement, LimitingResourceQueueDependency> cycleDetector(
DirectedGraph<LimitingResourceQueueElement, LimitingResourceQueueDependency> subGraph) {
return new CycleDetector<LimitingResourceQueueElement, LimitingResourceQueueDependency>(
subGraph);
}
private List<LimitingResourceQueueElement> getElementsOrderedTopologically(
DirectedGraph<LimitingResourceQueueElement, LimitingResourceQueueDependency> subGraph) {
return onlyAssigned(toList(topologicalIterator(subGraph)));
}
private TopologicalOrderIterator<LimitingResourceQueueElement, LimitingResourceQueueDependency> topologicalIterator(
DirectedGraph<LimitingResourceQueueElement, LimitingResourceQueueDependency> subGraph) {
return new TopologicalOrderIterator<LimitingResourceQueueElement, LimitingResourceQueueDependency>(
subGraph);
}
private static <T> List<T> toList(final Iterator<T> iterator) {
List<T> result = new ArrayList<T>();
while (iterator.hasNext()) {
result.add(iterator.next());
}
return result;
}
private List<LimitingResourceQueueElement> onlyAssigned(
List<LimitingResourceQueueElement> list) {
List<LimitingResourceQueueElement> result = new ArrayList<LimitingResourceQueueElement>();
for (LimitingResourceQueueElement each : list) {
if (!each.isDetached()) {
result.add(each);
}
}
return result;
}
private void unassignFromQueues(List<LimitingResourceQueueElement> result) {
for (LimitingResourceQueueElement each : result) {
if (!each.isDetached()) {
unassingFromQueue(each);
}
}
}
}