diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/planner/limiting/entities/GapRequirements.java b/navalplanner-business/src/main/java/org/navalplanner/business/planner/limiting/entities/GapRequirements.java
index cb1207795..6b6f20bab 100644
--- a/navalplanner-business/src/main/java/org/navalplanner/business/planner/limiting/entities/GapRequirements.java
+++ b/navalplanner-business/src/main/java/org/navalplanner/business/planner/limiting/entities/GapRequirements.java
@@ -60,11 +60,15 @@ public class GapRequirements {
this.earliestPossibleEnd = earliestPossibleEnd;
}
- public AllocationOnGap guessValidity(Gap gap) {
+ public boolean isPotentiallyValid(Gap gap) {
DateAndHour gapEnd = gap.getEndTime();
- if (gapEnd != null
- && (earliestPossibleStart.compareTo(gapEnd) >= 0 || earliestPossibleEnd
- .isAfter(gapEnd))) {
+ return gapEnd == null
+ || (earliestPossibleStart.isBefore(gapEnd) && !earliestPossibleEnd
+ .isAfter(gapEnd));
+ }
+
+ public AllocationOnGap guessValidity(Gap gap) {
+ if (!isPotentiallyValid(gap)) {
return AllocationOnGap.invalidOn(gap);
}
DateAndHour realStart = DateAndHour.Max(earliestPossibleStart, gap
@@ -171,4 +175,8 @@ public class GapRequirements {
return result;
}
+ public LimitingResourceQueueElement getElement() {
+ return element;
+ }
+
}
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/GapsMergeSort.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/GapsMergeSort.java
new file mode 100644
index 000000000..749761b42
--- /dev/null
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/GapsMergeSort.java
@@ -0,0 +1,127 @@
+/*
+ * This file is part of NavalPlan
+ *
+ * Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
+ * Desenvolvemento Tecnolóxico de Galicia
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+package org.navalplanner.web.limitingresources;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.collections.comparators.BooleanComparator;
+import org.navalplanner.business.planner.limiting.entities.Gap.GapOnQueue;
+
+
+/**
+ * Utility class for doing a merge sort of several ordered list of Gaps
+ * @author Óscar González Fernández
+ */
+public class GapsMergeSort {
+
+ private GapsMergeSort() {
+ }
+
+ private static class CurrentGap implements Comparable {
+
+ static List convert(
+ Collection extends Iterator> iterators) {
+ List result = new ArrayList();
+ for (Iterator iterator : iterators) {
+ result.add(new CurrentGap(iterator));
+ }
+ return result;
+ }
+
+ private Iterator iterator;
+
+ private GapOnQueue current;
+
+ private CurrentGap(Iterator iterator) {
+ this.iterator = iterator;
+ }
+
+ public GapOnQueue consume() {
+ GapOnQueue result = getCurrent();
+ current = null;
+ return result;
+ }
+
+ boolean hasFinished() {
+ return current == null && !iterator.hasNext();
+ }
+
+ private GapOnQueue getCurrent() {
+ if (hasFinished()) {
+ throw new IllegalStateException("already finished");
+ }
+ if (current != null) {
+ return current;
+ }
+ return current = iterator.next();
+ }
+
+ /**
+ * Ordering by hasFinished and the gap. An already finished is
+ * considered bigger than a not finished
+ */
+ @Override
+ public int compareTo(CurrentGap other) {
+ int finishComparison = BooleanComparator.getFalseFirstComparator()
+ .compare(hasFinished(), other.hasFinished());
+ if (finishComparison != 0) {
+ return finishComparison;
+ } else if (hasFinished()) {
+ assert other.hasFinished();
+ return 0;
+ } else {
+ assert !hasFinished() && !other.hasFinished();
+ return getCurrent().getGap().compareTo(
+ other.getCurrent().getGap());
+ }
+ }
+ }
+
+ public static List sort(
+ List> orderedListsOfGaps) {
+ if (orderedListsOfGaps.size() == 1) {
+ return orderedListsOfGaps.get(0);
+ }
+ List result = new ArrayList();
+ List currentGaps = CurrentGap.convert(iteratorsFor(orderedListsOfGaps));
+ CurrentGap min = null;
+ do {
+ min = Collections.min(currentGaps);
+ if (!min.hasFinished()) {
+ result.add(min.consume());
+ }
+ } while (!min.hasFinished());
+ return result;
+ }
+
+ private static List> iteratorsFor(
+ List> orderedListsOfGaps) {
+ List> result = new ArrayList>();
+ for (List each : orderedListsOfGaps) {
+ result.add(each.iterator());
+ }
+ return result;
+ }
+
+}
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/QueuesState.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/QueuesState.java
index 5357fd27c..3618b01af 100644
--- a/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/QueuesState.java
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/QueuesState.java
@@ -32,7 +32,9 @@ import org.navalplanner.business.common.BaseEntity;
import org.navalplanner.business.planner.entities.GenericResourceAllocation;
import org.navalplanner.business.planner.entities.ResourceAllocation;
import org.navalplanner.business.planner.entities.SpecificResourceAllocation;
+import org.navalplanner.business.planner.limiting.entities.GapRequirements;
import org.navalplanner.business.planner.limiting.entities.LimitingResourceQueueElement;
+import org.navalplanner.business.planner.limiting.entities.Gap.GapOnQueue;
import org.navalplanner.business.resources.entities.Criterion;
import org.navalplanner.business.resources.entities.CriterionCompounder;
import org.navalplanner.business.resources.entities.ICriterion;
@@ -154,6 +156,33 @@ public class QueuesState {
throw new RuntimeException("unexpected type of: " + resourceAllocation);
}
+ public GapRequirements getRequirementsFor(
+ LimitingResourceQueueElement element) {
+ return GapRequirements.forElement(getEquivalent(element));
+ }
+
+ /**
+ * @return all the gaps that could potentially fit element
+ * ordered by start date
+ */
+ public List getPotentiallyValidGapsFor(
+ GapRequirements requirements) {
+ List assignableQueues = getAssignableQueues(requirements
+ .getElement());
+ List> allGaps = gapsFor(assignableQueues, requirements);
+ return GapsMergeSort.sort(allGaps);
+ }
+
+ private List> gapsFor(
+ List assignableQueues,
+ GapRequirements requirements) {
+ List> result = new ArrayList>();
+ for (LimitingResourceQueue each : assignableQueues) {
+ result.add(each.getGapsPotentiallyValidFor(requirements));
+ }
+ return result;
+ }
+
private List findQueuesMatchingCriteria(
Set criteria) {
List result = new ArrayList();