diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/DateAndHour.java b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/DateAndHour.java index ff5b37930..393cff5e2 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/DateAndHour.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/DateAndHour.java @@ -1,3 +1,23 @@ +/* + * 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.business.planner.entities; import org.joda.time.LocalDate; @@ -47,7 +67,17 @@ public class DateAndHour implements Comparable { } public static DateAndHour Max(DateAndHour arg0, DateAndHour arg1) { + if (arg0 == null) { + return arg1; + } + if (arg1 == null) { + return arg0; + } return (arg0.compareTo(arg1) > 0) ? arg0 : arg1; } + public boolean isBefore(DateAndHour dateAndHour) { + return (this.compareTo(dateAndHour) < 0); + } + } diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/LimitingResourceQueueElementGap.java b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/LimitingResourceQueueElementGap.java index a10bad800..b74e51ff2 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/LimitingResourceQueueElementGap.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/LimitingResourceQueueElementGap.java @@ -1,3 +1,23 @@ +/* + * 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.business.planner.entities; import org.joda.time.LocalDate; @@ -9,7 +29,7 @@ import org.navalplanner.business.resources.entities.Resource; * @author Diego Pino Garcia * */ -public class LimitingResourceQueueElementGap { +public class LimitingResourceQueueElementGap implements Comparable { private DateAndHour startTime; @@ -19,28 +39,34 @@ public class LimitingResourceQueueElementGap { public LimitingResourceQueueElementGap(Resource resource, DateAndHour startTime, DateAndHour endTime) { - this(resource, startTime.getDate(), startTime.getHour(), endTime.getDate(), endTime.getHour()); + this.startTime = startTime; + this.endTime = endTime; + hoursInGap = calculateHoursInGap(resource, startTime, endTime); } - public LimitingResourceQueueElementGap(Resource resource, LocalDate startDate, + private Integer calculateHoursInGap(Resource resource, DateAndHour startTime, DateAndHour endTime) { + return (endTime == null) ? Integer.MAX_VALUE : calculateHoursInGap( + resource, startTime.getDate(), startTime.getHour(), endTime + .getDate(), endTime.getHour()); + } + + public int getHoursInGap() { + return hoursInGap; + } + + private Integer calculateHoursInGap(Resource resource, LocalDate startDate, int startHour, LocalDate endDate, int endHour) { final ResourceCalendar calendar = resource.getCalendar(); - // Calculate hours in range of dates if (startDate.equals(endDate)) { - hoursInGap = endHour - startHour; + return calendar.getCapacityAt(startDate) - Math.max(startHour, endHour); } else { - int hoursAtStart = calendar.getCapacityAt(startDate) - - startHour; + int hoursAtStart = calendar.getCapacityAt(startDate) - startHour; int hoursInBetween = calendar.getWorkableHours(startDate .plusDays(1), endDate.minusDays(1)); - hoursInGap = hoursAtStart + hoursInBetween + endHour; + return hoursAtStart + hoursInBetween + endHour; } - - // Set start and end time for gap - startTime = new DateAndHour(startDate, startHour); - endTime = new DateAndHour(endDate, endHour); } public static LimitingResourceQueueElementGap create(Resource resource, DateAndHour startTime, @@ -75,8 +101,23 @@ public class LimitingResourceQueueElementGap { } public String toString() { - return startTime.getDate() + " - " + startTime.getHour() + "; " - + endTime.getDate() + " - " + endTime.getHour(); + String result = startTime.getDate() + " - " + startTime.getHour(); + if (endTime != null) { + result += "; " + endTime.getDate() + " - " + endTime.getHour(); + } + return result; + } + + @Override + public int compareTo(LimitingResourceQueueElementGap o) { + if (o == null) { + return 1; + } + return this.getStartTime().compareTo(o.getStartTime()); + } + + public boolean isBefore(LimitingResourceQueueElementGap gap) { + return (compareTo(gap) < 0); } } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/ILimitingResourceQueueModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/ILimitingResourceQueueModel.java index e60e8ab3f..114492aef 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/ILimitingResourceQueueModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/ILimitingResourceQueueModel.java @@ -65,12 +65,17 @@ public interface ILimitingResourceQueueModel { * that fits the initial intented hours assigned to * element.resourceallocation. * - * The method also generates {@link DayAssignment} once ne the allocation is + * 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) + * * @param element */ - void assignLimitingResourceQueueElement(LimitingResourceQueueElement element); + boolean assignLimitingResourceQueueElement(LimitingResourceQueueElement element); ZoomLevel calculateInitialZoomLevel(); 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 67351874e..2163dacd5 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 @@ -25,9 +25,11 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; +import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.SortedSet; @@ -50,6 +52,7 @@ import org.navalplanner.business.planner.daos.ITaskElementDAO; import org.navalplanner.business.planner.entities.DateAndHour; import org.navalplanner.business.planner.entities.DayAssignment; import org.navalplanner.business.planner.entities.Dependency; +import org.navalplanner.business.planner.entities.GenericDayAssignment; import org.navalplanner.business.planner.entities.GenericResourceAllocation; import org.navalplanner.business.planner.entities.LimitingResourceQueueDependency; import org.navalplanner.business.planner.entities.LimitingResourceQueueElement; @@ -61,6 +64,9 @@ import org.navalplanner.business.planner.entities.SpecificResourceAllocation; import org.navalplanner.business.planner.entities.Task; import org.navalplanner.business.planner.entities.TaskElement; import org.navalplanner.business.resources.entities.Criterion; +import org.navalplanner.business.resources.entities.CriterionCompounder; +import org.navalplanner.business.resources.entities.CriterionSatisfaction; +import org.navalplanner.business.resources.entities.ICriterion; import org.navalplanner.business.resources.entities.LimitingResourceQueue; import org.navalplanner.business.resources.entities.Resource; import org.navalplanner.business.users.daos.IOrderAuthorizationDAO; @@ -206,7 +212,7 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel { resourceAllocation = initializeResourceAllocationIfNecessary(resourceAllocation); element.setResourceAllocation(resourceAllocation); initializeTask(resourceAllocation.getTask()); - initializeCalendarIfAny(element.getResource()); + initializeResourceIfAny(element.getResource()); } private void initializeTask(Task task) { @@ -222,13 +228,6 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel { } } - private void initializeCalendarIfAny(Resource resource) { - if (resource != null) { - resource.getName(); - initializeCalendarIfAny(resource.getCalendar()); - } - } - private void initializeCalendarIfAny(BaseCalendar calendar) { if (calendar != null) { Hibernate.initialize(calendar); @@ -276,11 +275,15 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel { private void initializeCriteria(Set criteria) { for (Criterion each: criteria) { - Hibernate.initialize(each); - Hibernate.initialize(each.getType()); + initializeCriterion(each); } } + private void initializeCriterion(Criterion criterion) { + Hibernate.initialize(criterion); + Hibernate.initialize(criterion.getType()); + } + private void loadLimitingResourceQueues() { limitingResourceQueues.clear(); limitingResourceQueues @@ -297,13 +300,25 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel { } private void initializeLimitingResourceQueue(LimitingResourceQueue queue) { - Hibernate.initialize(queue.getResource()); + initializeResourceIfAny(queue.getResource()); for (LimitingResourceQueueElement each : queue .getLimitingResourceQueueElements()) { initializeLimitingResourceQueueElement(each); } } + private void initializeResourceIfAny(Resource resource) { + if (resource != null) { + Hibernate.initialize(resource); + for (CriterionSatisfaction each : resource + .getCriterionSatisfactions()) { + Hibernate.initialize(each); + initializeCriterion(each.getCriterion()); + initializeCalendarIfAny(resource.getCalendar()); + } + } + } + @Override @Transactional(readOnly = true) public Order getOrderByTask(TaskElement task) { @@ -357,19 +372,198 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel { } @Override - public void assignLimitingResourceQueueElement( - final LimitingResourceQueueElement element) { + public boolean assignLimitingResourceQueueElement( + LimitingResourceQueueElement element) { + + LimitingResourceQueue queue = null; + DateAndHour startTime = null; LimitingResourceQueueElement queueElement = retrieveQueueElementFromModel(element); - LimitingResourceQueue queue = retrieveQueueByResourceFromModel(queueElement - .getResource()); + final DateAndHour startDateBecauseOfGantt = getStartTimeBecauseOfGantt(element); - DateAndHour startTime = findStartTimeInQueueForQueueElement(queue, queueElement); - DateAndHour[] startAndEndTime = allocateDayAssignments(queueElement - .getResourceAllocation(), startTime); + final ResourceAllocation resourceAllocation = queueElement.getResourceAllocation(); + if (resourceAllocation instanceof SpecificResourceAllocation) { + // Retrieve queue + queue = retrieveQueueByResourceFromModel(queueElement.getResource()); + // Set start time + final LimitingResourceQueueElementGap firstGap = getFirstValidGap(queue, queueElement); + startTime = firstGap.getStartTime(); + } else if (resourceAllocation instanceof GenericResourceAllocation) { + // Get the first gap for all the queues that can allocate the + // element during a certain interval of time + Map firstGapsForQueues = findFirstGapsInAllQueues( + element, startDateBecauseOfGantt); + // Among those queues, get the earliest gap + LimitingResourceQueueElementGap earliestGap = findEarliestGap(firstGapsForQueues + .keySet()); + if (earliestGap == null) { + return false; + } + // Select queue and start time + queue = firstGapsForQueues.get(earliestGap); + startTime = earliestGap.getStartTime(); + } + + // Generate day assignments and adjust start and end times for element + List dayAssignments = generateDayAssignments(queueElement + .getResourceAllocation(), queue.getResource(), startTime); + DateAndHour[] startAndEndTime = calculateStartAndEndTime(dayAssignments); updateStartAndEndTimes(queueElement, startAndEndTime); + // Add element to queue addLimitingResourceQueueElement(queue, queueElement); markAsModified(queueElement); + return true; + } + + private LimitingResourceQueueElementGap getFirstValidGap(LimitingResourceQueue queue, + LimitingResourceQueueElement element) { + + final Resource resource = queue.getResource(); + final List elements = new LinkedList( + queue.getLimitingResourceQueueElements()); + final int size = elements.size(); + + // Iterate through queue elements + for (int pos = 0; pos <= size; pos++) { + + LimitingResourceQueueElementGap gap = getGapInQueueAtPosition( + resource, elements, element, pos); + + // The queue cannot hold this element (perhaps queue.resource + // doesn't meet element.criteria) + if (gap == null) { + return null; + } + + if (canFitIntoGap(element, gap, resource)) { + return gap; + } + } + return null; + } + + private boolean canFitIntoGap(LimitingResourceQueueElement element, + LimitingResourceQueueElementGap gap, final Resource resource) { + + final boolean canfit = gap.canFit(element); + final ResourceAllocation resourceAllocation = element + .getResourceAllocation(); + + if (resourceAllocation instanceof SpecificResourceAllocation) { + return canfit; + } else if (resourceAllocation instanceof GenericResourceAllocation) { + // Resource must satisfy element.criteria during for the + // period of time the element will be allocated in the + // queue + final GenericResourceAllocation generic = (GenericResourceAllocation) resourceAllocation; + List dayAssignments = generateDayAssignments( + resourceAllocation, resource, gap.getStartTime()); + DateAndHour[] startAndEndTime = calculateStartAndEndTime(dayAssignments); + return canfit + && (satisfiesCriteriaDuringInterval(resource, generic + .getCriterions(), startAndEndTime)); + } + return false; + } + + private boolean satisfiesCriteriaDuringInterval(Resource resource, Set criteria, DateAndHour[] interval) { + final Date startDate = interval[0].getDate().toDateTimeAtStartOfDay().toDate(); + final Date endDate = interval[1].getDate().toDateTimeAtStartOfDay().toDate(); + return satisfiesCriteriaDuringInterval(resource, criteria, startDate, endDate); + } + + private boolean satisfiesCriteriaDuringInterval(Resource resource, Set criteria, Date startDate, Date endDate) { + ICriterion compositedCriterion = CriterionCompounder.buildAnd(criteria) + .getResult(); + return compositedCriterion.isSatisfiedBy(resource, startDate, endDate); + } + + private LimitingResourceQueueElementGap getGapInQueueAtPosition( + Resource resource, List elements, + LimitingResourceQueueElement element, int pos) { + + final int size = elements.size(); + final DateAndHour startTimeBecauseOfGantt = getStartTimeBecauseOfGantt(element); + + if (size > 0) { + + if (pos == size) { + return createLastGap(element, elements.get(size - 1), resource); + } + + LimitingResourceQueueElement current = elements.get(pos); + // First element + if (pos == 0 + && startTimeBecauseOfGantt.getDate().isBefore( + current.getStartDate())) { + return LimitingResourceQueueElementGap.create(resource, + startTimeBecauseOfGantt, current.getStartTime()); + } + + // Rest of elements + if (pos + 1 < size) { + LimitingResourceQueueElement next = elements.get(pos + 1); + if (startTimeBecauseOfGantt.isBefore(current.getEndTime())) { + return LimitingResourceQueueElementGap.create(resource, + current.getEndTime(), next.getStartTime()); + } else { + return LimitingResourceQueueElementGap.create(resource, + DateAndHour.Max(current.getEndTime(), + startTimeBecauseOfGantt), next + .getStartTime()); + } + } else { + // Current was the last element + return createLastGap(element, current, resource); + } + } + return null; + } + + private LimitingResourceQueueElementGap createLastGap( + LimitingResourceQueueElement candidate, + LimitingResourceQueueElement element, Resource resource) { + + DateAndHour startTime = DateAndHour.Max( + getStartTimeBecauseOfGantt(candidate), element.getEndTime()); + return LimitingResourceQueueElementGap + .create(resource, startTime, null); + } + + private Map findFirstGapsInAllQueues( + LimitingResourceQueueElement element, + DateAndHour startDateBecauseOfGantt) { + + Map result = new HashMap(); + + for (LimitingResourceQueue each : limitingResourceQueues) { + LimitingResourceQueueElementGap gap = getFirstValidGap(each, element); + if (gap != null) { + result.put(gap, each); + } + } + return result; + } + + private LimitingResourceQueueElementGap findEarliestGap(Set gaps) { + LimitingResourceQueueElementGap earliestGap = null; + for (LimitingResourceQueueElementGap each: gaps) { + if (earliestGap == null || each.isBefore(earliestGap)) { + earliestGap = each; + } + } + return earliestGap; + } + + private DateAndHour[] calculateStartAndEndTime(List dayAssignments) { + DateAndHour[] result = new DateAndHour[2]; + + final DayAssignment start = dayAssignments.get(0); + final DayAssignment end = dayAssignments.get(dayAssignments.size() - 1); + result[0] = new DateAndHour(start.getDay(), start.getHours()); + result[1] = new DateAndHour(end.getDay(), end.getHours()); + + return result; } private void markAsModified(LimitingResourceQueueElement element) { @@ -378,78 +572,10 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel { } } - private DateAndHour findStartTimeInQueueForQueueElement( - LimitingResourceQueue queue, LimitingResourceQueueElement candidate) { - - final SortedSet elements = queue.getLimitingResourceQueueElements(); - if (!elements.isEmpty()) { - final List gapList = buildGapList(candidate, elements); - final DateAndHour startTime = findStartTimeInGapList(candidate, gapList); - return (startTime != null) ? startTime : afterLastElement(candidate, elements); - } - return getStartTimeBecauseOfGantt(candidate); - } - - private DateAndHour afterLastElement(LimitingResourceQueueElement candidate, - SortedSet elements) { - final DateAndHour lastElementEndTime = elements.last().getEndTime(); - final DateAndHour candidateStartTime = getStartTimeBecauseOfGantt(candidate); - return DateAndHour.Max(lastElementEndTime, candidateStartTime); - } - private DateAndHour getStartTimeBecauseOfGantt(LimitingResourceQueueElement element) { return new DateAndHour(new LocalDate(element.getEarlierStartDateBecauseOfGantt()), 0); } - private DateAndHour findStartTimeInGapList(LimitingResourceQueueElement candidate, - List gapList) { - for (LimitingResourceQueueElementGap each : gapList) { - if (each.canFit(candidate)) { - return each.getStartTime(); - } - } - return null; - } - - private List buildGapList(LimitingResourceQueueElement candidate, - final SortedSet elements) { - List result = new ArrayList(); - - // If start time of candidate element to fit in queue is before first - // element, create a gap between candidate and the first element of the - // queue - DateAndHour startTimeBecauseOfGantt = getStartTimeBecauseOfGantt(candidate); - final LimitingResourceQueueElement firstElement = elements.first(); - if (startTimeBecauseOfGantt.compareTo(firstElement.getStartTime()) < 0) { - result.add(createGap(firstElement.getResource(), startTimeBecauseOfGantt, - firstElement.getStartTime())); - } - - LimitingResourceQueueElement current, next; - // Only include gaps from candidate start time on - for (Iterator i = elements.iterator(); i - .hasNext();) { - - current = i.next(); - if (i.hasNext()) { - next = i.next(); - DateAndHour startTime = current.getEndTime(); - final DateAndHour endTime = next.getStartTime(); - - if (startTime.compareTo(startTimeBecauseOfGantt) <= 0) { - if (endTime.compareTo(startTimeBecauseOfGantt) <= 0) { - // Start and end of the gap are before earlierStartDateBecauseOfGanttTime - continue; - } - // earliestStartDateBecauseOfGantt is in between - startTime = startTimeBecauseOfGantt; - } - result.add(createGap(current.getResource(), startTime, endTime)); - } - } - return result; - } - public LimitingResourceQueueElementGap createGap(Resource resource, DateAndHour startTime, DateAndHour endTime) { return LimitingResourceQueueElementGap.create(resource, startTime, endTime); @@ -540,62 +666,43 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel { return null; } - private DateAndHour[] allocateDayAssignments( - ResourceAllocation resourceAllocation, DateAndHour startingTime) { + private DayAssignment createDayAssignment(ResourceAllocation resourceAllocation, + Resource resource, LocalDate date, int hoursToAllocate) { if (resourceAllocation instanceof SpecificResourceAllocation) { - return allocateDayAssignments( - (SpecificResourceAllocation) resourceAllocation, - startingTime); - } - if (resourceAllocation instanceof GenericResourceAllocation) { - // TODO: Generate day assignments for generic resource allocation + return SpecificDayAssignment.create(date, hoursToAllocate, resource); + } else if (resourceAllocation instanceof GenericResourceAllocation) { + return GenericDayAssignment.create(date, hoursToAllocate, resource); } return null; } - private DateAndHour[] allocateDayAssignments( - SpecificResourceAllocation resourceAllocation, + private List generateDayAssignments( + ResourceAllocation resourceAllocation, + Resource resource, DateAndHour startTime) { - List assignments = new ArrayList(); - - DateAndHour newStartTime = startTime; + List assignments = new ArrayList(); LocalDate date = startTime.getDate(); int totalHours = resourceAllocation.getIntendedTotalHours(); // Generate first day assignment - int hoursCanAllocate = hoursCanWorkOnDay(resourceAllocation, date, startTime.getHour()); + int hoursCanAllocate = hoursCanWorkOnDay(resource, date, startTime.getHour()); if (hoursCanAllocate > 0) { int hoursToAllocate = Math.min(totalHours, hoursCanAllocate); - SpecificDayAssignment dayAssignment = SpecificDayAssignment.create( - date, hoursToAllocate, resourceAllocation.getResource()); + DayAssignment dayAssignment = createDayAssignment(resourceAllocation, resource, date, hoursToAllocate); totalHours -= addDayAssignment(assignments, dayAssignment); - } else { - newStartTime = new DateAndHour(date.plusDays(1), 0); } // Generate rest of day assignments for (date = date.plusDays(1); totalHours > 0; date = date.plusDays(1)) { totalHours -= addDayAssignment(assignments, generateDayAssignment( - resourceAllocation, date, totalHours)); + resourceAllocation, resource, date, totalHours)); } - resourceAllocation.allocateLimitingDayAssignments(assignments); - - DateAndHour newEndTime = new DateAndHour(date, getEndingTime(assignments)); - DateAndHour[] startAndEndTime = {newStartTime, newEndTime}; - return startAndEndTime; + return assignments; } - private DayAssignment getLastDayAssignment(List dayAssignments) { - return dayAssignments.get(dayAssignments.size() - 1); - } - - private int getEndingTime(List dayAssignments) { - return (dayAssignments.isEmpty()) ? 0 : getLastDayAssignment(dayAssignments).getHours(); - } - - private int addDayAssignment(List list, SpecificDayAssignment dayAssignment) { + private int addDayAssignment(List list, DayAssignment dayAssignment) { if (dayAssignment != null) { list.add(dayAssignment); return dayAssignment.getHours(); @@ -603,26 +710,24 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel { return 0; } - private int hoursCanWorkOnDay(final SpecificResourceAllocation resourceAllocation, + private int hoursCanWorkOnDay(final Resource resource, final LocalDate date, int alreadyWorked) { - final ResourceCalendar calendar = resourceAllocation.getResource() - .getCalendar(); + final ResourceCalendar calendar = resource.getCalendar(); int hoursCanAllocate = calendar.toHours(date, ONE_RESOURCE_PER_DAY); return hoursCanAllocate - alreadyWorked; } - private SpecificDayAssignment generateDayAssignment( - final SpecificResourceAllocation resourceAllocation, + private DayAssignment generateDayAssignment( + final ResourceAllocation resourceAllocation, + Resource resource, final LocalDate date, int intentedHours) { - final ResourceCalendar calendar = resourceAllocation.getResource() - .getCalendar(); + final ResourceCalendar calendar = resource.getCalendar(); int hoursCanAllocate = calendar.toHours(date, ONE_RESOURCE_PER_DAY); if (hoursCanAllocate > 0) { int hoursToAllocate = Math.min(intentedHours, hoursCanAllocate); - return SpecificDayAssignment.create(date, hoursToAllocate, - resourceAllocation.getResource()); + return createDayAssignment(resourceAllocation, resource, date, hoursToAllocate); } return null; } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourcesController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourcesController.java index 85436bfd8..2abcb21ff 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourcesController.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourcesController.java @@ -358,15 +358,22 @@ public class LimitingResourcesController implements Composer { LimitingResourceQueueElementDTO dto) { LimitingResourceQueueElement element = dto.getOriginal(); - if (element.getResourceAllocation() instanceof GenericResourceAllocation) { - // TODO: Generic resources allocation - Log.error("Allocation of generic resources is not supported yet"); - return; + if (limitingResourceQueueModel + .assignLimitingResourceQueueElement(element)) { + Util.reloadBindings(gridUnassignedLimitingResourceQueueElements); + limitingResourcesPanel.appendQueueElementToQueue(element); + } else { + showErrorMessage(_("Cannot allocate selected element. There is not any queue " + + "that matches resource allocation criteria at any interval of time")); + } + } + + private void showErrorMessage(String error) { + try { + Messagebox.show(error, _("Error"), Messagebox.OK, Messagebox.ERROR); + } catch (InterruptedException e) { + } - limitingResourceQueueModel - .assignLimitingResourceQueueElement(element); - Util.reloadBindings(gridUnassignedLimitingResourceQueueElements); - limitingResourcesPanel.appendQueueElementToQueue(element); } private Checkbox automaticQueueing(