From cbe70505c8ea5bb1acf9aff1415302260a1444a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=93scar=20Gonz=C3=A1lez=20Fern=C3=A1ndez?= Date: Sun, 6 Jun 2010 17:31:45 +0200 Subject: [PATCH] ItEr59S08CUAsignacionRecursosLimitantesItEr58S10: Add method for getting all the gaps that could potentially satisfy some requirements --- .../limiting/entities/GapRequirements.java | 16 ++- .../web/limitingresources/GapsMergeSort.java | 127 ++++++++++++++++++ .../web/limitingresources/QueuesState.java | 29 ++++ 3 files changed, 168 insertions(+), 4 deletions(-) create mode 100644 navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/GapsMergeSort.java 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> 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();