ItEr56S09RFAspectosGraficosRecursoLimitantesItEr55S11: Added QueueTask and LimitingResourceQueue classes

This commit is contained in:
Lorenzo Tilve 2010-04-27 19:34:17 +02:00 committed by Javier Moran Rua
parent a06aea5656
commit b58750d830
10 changed files with 1005 additions and 126 deletions

View file

@ -0,0 +1,213 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.zkoss.ganttz.data.limitingresource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.apache.commons.lang.Validate;
import org.joda.time.LocalDate;
import org.zkoss.ganttz.data.resourceload.TimeLineRole;
import org.zkoss.ganttz.util.Interval;
public class LimitingResourceQueue {
private final String conceptName;
private final List<QueueTask> loadPeriods;
private final TimeLineRole<?> timeLineRole;
private final String type;
private final List<LimitingResourceQueue> children;
public LimitingResourceQueue(String conceptName,
List<QueueTask> loadPeriods,
TimeLineRole<?> role) {
Validate.notEmpty(conceptName);
Validate.notNull(loadPeriods);
this.loadPeriods = QueueTask.sort(loadPeriods);
this.conceptName = conceptName;
this.type = "";
this.timeLineRole = role;
this.children = Collections
.unmodifiableList(new ArrayList<LimitingResourceQueue>());
}
public LimitingResourceQueue(String conceptName,
List<QueueTask> loadPeriods,
String type, TimeLineRole<?> role) {
Validate.notEmpty(conceptName);
Validate.notNull(loadPeriods);
this.loadPeriods = QueueTask.sort(loadPeriods);
this.conceptName = conceptName;
this.timeLineRole = role;
this.type = type;
this.children = Collections
.unmodifiableList(new ArrayList<LimitingResourceQueue>());
}
public LimitingResourceQueue(LimitingResourceQueue principal, List<LimitingResourceQueue> children) {
Validate.notEmpty(principal.getConceptName());
Validate.notNull(principal.getQueueTasks());
this.loadPeriods = QueueTask.sort(principal.getQueueTasks());
this.conceptName = principal.getConceptName();
this.timeLineRole = principal.getRole();
this.type = principal.getType();
Validate.notNull(children);
allChildrenAreNotEmpty(children);
this.children = Collections
.unmodifiableList(new ArrayList<LimitingResourceQueue>(children));
}
public List<QueueTask> getQueueTasks() {
return loadPeriods;
}
public String getConceptName() {
return conceptName;
}
public TimeLineRole<?> getRole() {
return timeLineRole;
}
private QueueTask getFirst() {
return loadPeriods.get(0);
}
private QueueTask getLast() {
return loadPeriods.get(loadPeriods.size() - 1);
}
public LocalDate getStartPeriod() {
if (isEmpty()) {
return null;
}
return getFirst().getStart();
}
public boolean isEmpty() {
return loadPeriods.isEmpty();
}
public LocalDate getEndPeriod() {
if (isEmpty()) {
return null;
}
return getLast().getEnd();
}
public String getType() {
return this.type;
}
public static Interval getIntervalFrom(List<LimitingResourceQueue> timeLines) {
Validate.notEmpty(timeLines);
LocalDate start = null;
LocalDate end = null;
for (LimitingResourceQueue loadTimeLine : timeLines) {
Validate.notNull(loadTimeLine.getStart());
start = min(start, loadTimeLine.getStart());
Validate.notNull(loadTimeLine.getEnd());
end = max(end, loadTimeLine.getEnd());
}
return new Interval(toDate(start), toDate(end));
}
private static Date toDate(LocalDate localDate) {
return localDate.toDateTimeAtStartOfDay().toDate();
}
private static LocalDate max(LocalDate one, LocalDate other) {
if (one == null) {
return other;
}
if (other == null) {
return one;
}
return one.compareTo(other) > 0 ? one : other;
}
private static LocalDate min(LocalDate one, LocalDate other) {
if (one == null) {
return other;
}
if (other == null) {
return one;
}
return one.compareTo(other) < 0 ? one : other;
}
private static void allChildrenAreNotEmpty(List<LimitingResourceQueue> lines) {
for (LimitingResourceQueue l : lines) {
if (l.isEmpty()) {
throw new IllegalArgumentException(l + " is empty");
}
if (l.hasChildren()) {
allChildrenAreNotEmpty(l.getChildren());
}
}
}
public boolean hasChildren() {
return (!children.isEmpty());
}
public List<LimitingResourceQueue> getChildren() {
return children;
}
public List<LimitingResourceQueue> getAllChildren() {
List<LimitingResourceQueue> result = new ArrayList<LimitingResourceQueue>();
for (LimitingResourceQueue child : children) {
result.addAll(child.getAllChildren());
result.add(child);
}
return result;
}
public LocalDate getStart() {
LocalDate result = getStartPeriod();
for (LimitingResourceQueue loadTimeLine : getChildren()) {
LocalDate start = loadTimeLine.getStart();
if (start != null) {
result = result == null || result.compareTo(start) > 0 ? start
: result;
}
}
return result;
}
public LocalDate getEnd() {
LocalDate result = getEndPeriod();
for (LimitingResourceQueue loadTimeLine : getChildren()) {
LocalDate end = loadTimeLine.getEnd();
if (end != null) {
result = result == null || result.compareTo(end) < 0 ? end : result;
}
}
return result;
}
}

View file

@ -0,0 +1,128 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.zkoss.ganttz.data.limitingresource;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.Validate;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.joda.time.LocalDate;
import org.zkoss.ganttz.data.resourceload.LoadLevel;
public class QueueTask {
private static final Log LOG = LogFactory.getLog(QueueTask.class);
private final LocalDate start;
private final LocalDate end;
private final LoadLevel loadLevel;
private final int totalResourceWorkHours;
private final int assignedHours;
public QueueTask(LocalDate start, LocalDate end,
int totalResourceWorkHours, int assignedHours, LoadLevel loadLevel) {
Validate.notNull(start);
Validate.notNull(end);
Validate.notNull(loadLevel);
Validate.notNull(totalResourceWorkHours);
Validate.notNull(assignedHours);
Validate.isTrue(!start.isAfter(end));
this.start = start;
this.end = end;
this.loadLevel = loadLevel;
this.totalResourceWorkHours = totalResourceWorkHours;
this.assignedHours = assignedHours;
}
public LocalDate getStart() {
return start;
}
public LocalDate getEnd() {
return end;
}
// public boolean overlaps(QueueTask other) {
// return start.isBefore(other.end) && end.isAfter(other.start);
// }
/**
* @param loadPeriods
* @return
* @throws IllegalArgumentException
* if some of the QueueTask overlaps
*/
public static List<QueueTask> sort(List<QueueTask> loadPeriods)
throws IllegalArgumentException {
ArrayList<QueueTask> result = new ArrayList<QueueTask>(loadPeriods);
// Collections.sort(result, new Comparator<QueueTask>() {
// @Override
// public int compare(QueueTask o1, QueueTask o2) {
// if (o1.overlaps(o2)) {
// LOG.warn(o1 + " overlaps with " + o2);
// throw new IllegalArgumentException(o1 + " overlaps with "
// + o2);
// }
// int comparison = compareLocalDates(o1.start, o2.start);
// if (comparison != 0) {
// return comparison;
// }
// return compareLocalDates(o1.end, o2.end);
// }
// });
return result;
}
private static int compareLocalDates(LocalDate l1, LocalDate l2) {
if (l1.isBefore(l2)) {
return -1;
}
if (l1.isAfter(l2)) {
return 1;
}
return 0;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
public LoadLevel getLoadLevel() {
return loadLevel;
}
public int getTotalResourceWorkHours() {
return totalResourceWorkHours;
}
public int getAssignedHours() {
return assignedHours;
}
}

View file

@ -26,8 +26,8 @@ import java.util.List;
import org.joda.time.LocalDate;
import org.zkoss.ganttz.IDatesMapper;
import org.zkoss.ganttz.data.resourceload.LoadPeriod;
import org.zkoss.ganttz.data.resourceload.LoadTimeLine;
import org.zkoss.ganttz.data.limitingresource.LimitingResourceQueue;
import org.zkoss.ganttz.data.limitingresource.QueueTask;
import org.zkoss.ganttz.timetracker.TimeTracker;
import org.zkoss.ganttz.timetracker.zoom.IZoomLevelChangedListener;
import org.zkoss.ganttz.timetracker.zoom.ZoomLevel;
@ -41,33 +41,36 @@ import org.zkoss.zul.impl.XulElement;
public class LimitingResourcesComponent extends XulElement {
public static LimitingResourcesComponent create(TimeTracker timeTracker,
LoadTimeLine loadLine) {
return new LimitingResourcesComponent(timeTracker, loadLine);
LimitingResourceQueue limitingResourceQueue) {
return new LimitingResourcesComponent(timeTracker,
limitingResourceQueue);
}
private final LoadTimeLine loadLine;
private final LimitingResourceQueue loadLine;
private final TimeTracker timeTracker;
private transient IZoomLevelChangedListener zoomChangedListener;
private LimitingResourcesComponent(final TimeTracker timeTracker,
final LoadTimeLine loadLine) {
this.loadLine = loadLine;
final LimitingResourceQueue limitingResourceQueue) {
this.loadLine = limitingResourceQueue;
this.timeTracker = timeTracker;
createChildren(loadLine, timeTracker.getMapper());
createChildren(limitingResourceQueue, timeTracker.getMapper());
zoomChangedListener = new IZoomLevelChangedListener() {
@Override
public void zoomLevelChanged(ZoomLevel detailLevel) {
getChildren().clear();
createChildren(loadLine, timeTracker.getMapper());
createChildren(limitingResourceQueue, timeTracker.getMapper());
invalidate();
}
};
this.timeTracker.addZoomListener(zoomChangedListener);
}
private void createChildren(LoadTimeLine loadLine, IDatesMapper mapper) {
List<Div> divs = createDivsForPeriods(mapper, loadLine.getLoadPeriods());
private void createChildren(LimitingResourceQueue limitingResourceQueue,
IDatesMapper mapper) {
List<Div> divs = createDivsForPeriods(mapper, limitingResourceQueue
.getQueueTasks());
for (Div div : divs) {
appendChild(div);
}
@ -83,16 +86,16 @@ public class LimitingResourcesComponent extends XulElement {
private static List<Div> createDivsForPeriods(IDatesMapper datesMapper,
List<LoadPeriod> loadPeriods) {
List<QueueTask> list) {
List<Div> result = new ArrayList<Div>();
for (LoadPeriod loadPeriod : loadPeriods) {
for (QueueTask loadPeriod : list) {
result.add(createDivForPeriod(datesMapper, loadPeriod));
}
return result;
}
private static Div createDivForPeriod(IDatesMapper datesMapper,
LoadPeriod loadPeriod) {
QueueTask loadPeriod) {
Div result = new Div();
result.setClass(String.format("taskassignmentinterval %s", loadPeriod
.getLoadLevel().getCategory()));
@ -112,7 +115,7 @@ public class LimitingResourcesComponent extends XulElement {
}
private static int getWidthPixels(IDatesMapper datesMapper,
LoadPeriod loadPeriod) {
QueueTask loadPeriod) {
LocalDate start = loadPeriod.getStart();
LocalDate end = loadPeriod.getEnd();
return datesMapper
@ -128,7 +131,7 @@ public class LimitingResourcesComponent extends XulElement {
}
private static int getStartPixels(IDatesMapper datesMapper,
LoadPeriod loadPeriod) {
QueueTask loadPeriod) {
return datesMapper.toPixels(loadPeriod.getStart().toDateMidnight()
.toDate());
}

View file

@ -24,6 +24,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.zkoss.ganttz.data.limitingresource.LimitingResourceQueue;
import org.zkoss.ganttz.data.resourceload.LoadTimeLine;
import org.zkoss.ganttz.util.MutableTreeModel;
import org.zkoss.zk.ui.Component;
@ -43,13 +44,14 @@ import org.zkoss.zul.api.Tree;
public class LimitingResourcesLeftPane extends HtmlMacroComponent {
private MutableTreeModel<LoadTimeLine> modelForTree;
private MutableTreeModel<LimitingResourceQueue> modelForTree;
private final LimitingResourcesList limitingResourcesList;
public LimitingResourcesLeftPane(MutableTreeModel<LoadTimeLine> modelForTree,
public LimitingResourcesLeftPane(
MutableTreeModel<LimitingResourceQueue> treeModel,
LimitingResourcesList resourceLoadList) {
this.limitingResourcesList = resourceLoadList;
this.modelForTree = modelForTree;
this.modelForTree = treeModel;
}
@ -75,7 +77,7 @@ public class LimitingResourcesLeftPane extends HtmlMacroComponent {
item.appendChild(row);
row.appendChild(cell);
cell.appendChild(component);
collapse(line);
// collapse(line);
addExpandedListener(item, line);
}
@ -85,12 +87,12 @@ public class LimitingResourcesLeftPane extends HtmlMacroComponent {
@Override
public void onEvent(Event event) throws Exception {
OpenEvent openEvent = (OpenEvent) event;
if (openEvent.isOpen()) {
List<LoadTimeLine> closed = calculatedClosedItems(item);
expand(line, closed);
} else {
collapse(line);
}
// if (openEvent.isOpen()) {
// List<LoadTimeLine> closed = calculatedClosedItems(item);
// expand(line, closed);
// } else {
// collapse(line);
// }
}
});
}
@ -107,12 +109,14 @@ public class LimitingResourcesLeftPane extends HtmlMacroComponent {
};
}
private void collapse(LoadTimeLine line) {
private void collapse(LimitingResourceQueue line) {
// unnecesary
limitingResourcesList.collapse(line);
}
private void expand(LoadTimeLine line, List<LoadTimeLine> closed) {
limitingResourcesList.expand(line, closed);
private void expand(LoadTimeLine line, List<LimitingResourceQueue> closed) {
// unnecesary
// limitingResourcesList.expand(line, closed);
}
private List<LoadTimeLine> calculatedClosedItems(Treeitem item) {

View file

@ -26,7 +26,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.zkoss.ganttz.data.resourceload.LoadTimeLine;
import org.zkoss.ganttz.data.limitingresource.LimitingResourceQueue;
import org.zkoss.ganttz.timetracker.TimeTracker;
import org.zkoss.ganttz.timetracker.zoom.IZoomLevelChangedListener;
import org.zkoss.ganttz.timetracker.zoom.ZoomLevel;
@ -45,26 +45,26 @@ public class LimitingResourcesList extends HtmlMacroComponent implements
private final IZoomLevelChangedListener zoomListener;
private Map<LoadTimeLine, LimitingResourcesComponent> fromTimeLineToComponent = new HashMap<LoadTimeLine, LimitingResourcesComponent>();
private Map<LimitingResourceQueue, LimitingResourcesComponent> fromTimeLineToComponent = new HashMap<LimitingResourceQueue, LimitingResourcesComponent>();
private final MutableTreeModel<LoadTimeLine> timelinesTree;
private final MutableTreeModel<LimitingResourceQueue> timelinesTree;
public LimitingResourcesList(TimeTracker timeTracker,
MutableTreeModel<LoadTimeLine> timelinesTree) {
MutableTreeModel<LimitingResourceQueue> timelinesTree) {
this.timelinesTree = timelinesTree;
zoomListener = adjustTimeTrackerSizeListener();
timeTracker.addZoomListener(zoomListener);
LoadTimeLine current = timelinesTree.getRoot();
List<LoadTimeLine> toInsert = new ArrayList<LoadTimeLine>();
LimitingResourceQueue current = timelinesTree.getRoot();
List<LimitingResourceQueue> toInsert = new ArrayList<LimitingResourceQueue>();
fill(timelinesTree, current, toInsert);
insertAsComponents(timeTracker, toInsert);
}
private void fill(MutableTreeModel<LoadTimeLine> timelinesTree,
LoadTimeLine current, List<LoadTimeLine> result) {
private void fill(MutableTreeModel<LimitingResourceQueue> timelinesTree,
LimitingResourceQueue current, List<LimitingResourceQueue> result) {
final int length = timelinesTree.getChildCount(current);
for (int i = 0; i < length; i++) {
LoadTimeLine child = timelinesTree.getChild(current, i);
LimitingResourceQueue child = timelinesTree.getChild(current, i);
result.add(child);
fill(timelinesTree, child, result);
}
@ -84,45 +84,47 @@ public class LimitingResourcesList extends HtmlMacroComponent implements
}
private void insertAsComponents(TimeTracker timetracker,
List<LoadTimeLine> children) {
for (LoadTimeLine loadTimeLine : children) {
List<LimitingResourceQueue> children) {
for (LimitingResourceQueue LimitingResourceQueue : children) {
LimitingResourcesComponent component = LimitingResourcesComponent
.create(
timetracker, loadTimeLine);
timetracker, LimitingResourceQueue);
appendChild(component);
fromTimeLineToComponent.put(loadTimeLine, component);
fromTimeLineToComponent.put(LimitingResourceQueue, component);
}
}
public void collapse(LoadTimeLine line) {
for (LoadTimeLine l : line.getAllChildren()) {
public void collapse(LimitingResourceQueue line) {
for (LimitingResourceQueue l : line.getAllChildren()) {
getComponentFor(l).detach();
}
}
private LimitingResourcesComponent getComponentFor(LoadTimeLine l) {
private LimitingResourcesComponent getComponentFor(LimitingResourceQueue l) {
LimitingResourcesComponent resourceLoadComponent = fromTimeLineToComponent
.get(l);
return resourceLoadComponent;
}
public void expand(LoadTimeLine line, List<LoadTimeLine> closed) {
public void expand(LimitingResourceQueue line,
List<LimitingResourceQueue> closed) {
LimitingResourcesComponent parentComponent = getComponentFor(line);
Component nextSibling = parentComponent.getNextSibling();
List<LoadTimeLine> childrenToOpen = getChildrenReverseOrderFor(line);
List<LimitingResourceQueue> childrenToOpen = getChildrenReverseOrderFor(line);
childrenToOpen.removeAll(closed);
for (LoadTimeLine loadTimeLine : childrenToOpen) {
LimitingResourcesComponent child = getComponentFor(loadTimeLine);
for (LimitingResourceQueue LimitingResourceQueue : childrenToOpen) {
LimitingResourcesComponent child = getComponentFor(LimitingResourceQueue);
insertBefore(child, nextSibling);
nextSibling = child;
}
}
private List<LoadTimeLine> getChildrenReverseOrderFor(LoadTimeLine line) {
List<LoadTimeLine> childrenOf = line.getAllChildren();
private List<LimitingResourceQueue> getChildrenReverseOrderFor(
LimitingResourceQueue line) {
List<LimitingResourceQueue> childrenOf = line.getAllChildren();
Collections.reverse(childrenOf);
return childrenOf;
}

View file

@ -25,7 +25,7 @@ import static org.zkoss.ganttz.i18n.I18nHelper._;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.zkoss.ganttz.data.resourceload.LoadTimeLine;
import org.zkoss.ganttz.data.limitingresource.LimitingResourceQueue;
import org.zkoss.ganttz.timetracker.TimeTracker;
import org.zkoss.ganttz.timetracker.TimeTrackerComponent;
import org.zkoss.ganttz.timetracker.zoom.ZoomLevel;
@ -61,9 +61,9 @@ public class LimitingResourcesPanel extends HtmlMacroComponent {
private LimitingResourcesList limitingResourcesList;
private List<LoadTimeLine> groups;
private List<LimitingResourceQueue> groups;
private MutableTreeModel<LoadTimeLine> treeModel;
private MutableTreeModel<LimitingResourceQueue> treeModel;
private TimeTracker timeTracker;
@ -78,13 +78,13 @@ public class LimitingResourcesPanel extends HtmlMacroComponent {
private static final String filterCriterions = _("Filter by criterions");
private boolean filterbyResources = true;
public LimitingResourcesPanel(List<LoadTimeLine> groups,
public LimitingResourcesPanel(List<LimitingResourceQueue> groups,
TimeTracker timeTracker) {
init(groups, timeTracker);
}
public void init(List<LoadTimeLine> groups, TimeTracker timeTracker) {
public void init(List<LimitingResourceQueue> groups, TimeTracker timeTracker) {
this.groups = groups;
this.timeTracker = timeTracker;
treeModel = createModelForTree();
@ -190,23 +190,25 @@ public class LimitingResourcesPanel extends HtmlMacroComponent {
.retrieve();
}
private MutableTreeModel<LoadTimeLine> createModelForTree() {
MutableTreeModel<LoadTimeLine> result = MutableTreeModel
.create(LoadTimeLine.class);
for (LoadTimeLine loadTimeLine : this.groups) {
result.addToRoot(loadTimeLine);
result = addNodes(result, loadTimeLine);
private MutableTreeModel<LimitingResourceQueue> createModelForTree() {
MutableTreeModel<LimitingResourceQueue> result = MutableTreeModel
.create(LimitingResourceQueue.class);
for (LimitingResourceQueue LimitingResourceQueue : this.groups) {
result.addToRoot(LimitingResourceQueue);
result = addNodes(result, LimitingResourceQueue);
}
return result;
}
private MutableTreeModel<LoadTimeLine> addNodes(
MutableTreeModel<LoadTimeLine> tree, LoadTimeLine parent) {
private MutableTreeModel<LimitingResourceQueue> addNodes(
MutableTreeModel<LimitingResourceQueue> tree,
LimitingResourceQueue parent) {
if (!parent.getChildren().isEmpty()) {
tree.add(parent, parent.getChildren());
for (LoadTimeLine loadTimeLine : parent.getChildren()) {
tree = addNodes(tree, loadTimeLine);
for (LimitingResourceQueue LimitingResourceQueue : parent
.getChildren()) {
tree = addNodes(tree, LimitingResourceQueue);
}
}
return tree;

View file

@ -24,7 +24,7 @@ import java.util.List;
import org.navalplanner.business.orders.entities.Order;
import org.navalplanner.business.planner.entities.TaskElement;
import org.zkoss.ganttz.data.resourceload.LoadTimeLine;
import org.zkoss.ganttz.data.limitingresource.LimitingResourceQueue;
import org.zkoss.ganttz.timetracker.zoom.ZoomLevel;
import org.zkoss.ganttz.util.Interval;
@ -34,7 +34,7 @@ public interface ILimitingResourceQueueModel {
void initGlobalView(Order filterBy, boolean filterByResources);
List<LoadTimeLine> getLoadTimeLines();
List<LimitingResourceQueue> getLimitingResourceQueues();
Interval getViewInterval();

View file

@ -28,7 +28,9 @@ import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
@ -63,7 +65,8 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.zkoss.ganttz.data.resourceload.LoadTimeLine;
import org.zkoss.ganttz.data.limitingresource.LimitingResourceQueue;
import org.zkoss.ganttz.data.limitingresource.QueueTask;
import org.zkoss.ganttz.data.resourceload.TimeLineRole;
import org.zkoss.ganttz.timetracker.zoom.ZoomLevel;
import org.zkoss.ganttz.util.Interval;
@ -93,7 +96,7 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
@Autowired
private IOrderAuthorizationDAO orderAuthorizationDAO;
private List<LoadTimeLine> loadTimeLines;
private List<LimitingResourceQueue> limitingResourceQueues;
private Interval viewInterval;
private Order filterBy;
@ -148,9 +151,10 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
}
private void doGlobalView() {
loadTimeLines = calculateLoadTimeLines();
if (!loadTimeLines.isEmpty()) {
viewInterval = LoadTimeLine.getIntervalFrom(loadTimeLines);
limitingResourceQueues = calculateLimitingResourceQueues();
if (!limitingResourceQueues.isEmpty()) {
viewInterval = LimitingResourceQueue
.getIntervalFrom(limitingResourceQueues);
} else {
viewInterval = new Interval(new Date(), plusFiveYears(new Date()));
}
@ -163,9 +167,9 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
return calendar.getTime();
}
private List<LoadTimeLine> calculateLoadTimeLines() {
List<LoadTimeLine> result = new ArrayList<LoadTimeLine>();
result.addAll(groupsFor(genericAllocationsByCriterion()));
private List<LimitingResourceQueue> calculateLimitingResourceQueues() {
List<LimitingResourceQueue> result = new ArrayList<LimitingResourceQueue>();
result.addAll(groupsFor(resourcesToShow()));
return result;
}
@ -226,37 +230,72 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
return new TimeLineRole<BaseEntity>(entity);
}
/**
* @param genericAllocationsByCriterion
* @return
*/
private List<LoadTimeLine> groupsFor(
Map<Criterion, List<GenericResourceAllocation>> genericAllocationsByCriterion) {
List<LoadTimeLine> result = new ArrayList<LoadTimeLine>();
List<Criterion> criterions = Criterion
.sortByName(genericAllocationsByCriterion.keySet());
for (Criterion criterion : criterions) {
List<GenericResourceAllocation> allocations = ResourceAllocation
.sortedByStartDate(genericAllocationsByCriterion
.get(criterion));
TimeLineRole<BaseEntity> role = getCurrentTimeLineRole(criterion);
private List<LimitingResourceQueue> groupsFor(List<Resource> allResources) {
List<LimitingResourceQueue> result = new ArrayList<LimitingResourceQueue>();
for (Resource resource : allResources) {
LimitingResourceQueue group = buildGroup(resource);
if (!group.isEmpty()) {
result.add(group);
}
}
return result;
}
private List<LoadTimeLine> buildTimeLinesForOrder(Criterion criterion,
List<ResourceAllocation<?>> allocations) {
List<LoadTimeLine> result = new ArrayList<LoadTimeLine>();
result.addAll(buildTimeLinesForEachTask(criterion, allocations));
private LimitingResourceQueue buildGroup(Resource resource) {
List<ResourceAllocation<?>> sortedByStartDate = ResourceAllocation
.sortedByStartDate(resourceAllocationDAO
.findAllocationsRelatedTo(resource));
TimeLineRole<BaseEntity> role = getCurrentTimeLineRole(resource);
LimitingResourceQueue result = new LimitingResourceQueue(buildTimeLine(
resource, resource.getShortDescription(), sortedByStartDate,
"resource", role),
buildSecondLevel(resource, sortedByStartDate));
return result;
}
private List<LoadTimeLine> buildTimeLinesForEachTask(Criterion criterion,
private LimitingResourceQueue buildTimeLine(Resource resource, String name,
List<? extends ResourceAllocation<?>> sortedByStartDate,
String type, TimeLineRole<BaseEntity> role) {
return new LimitingResourceQueue(name, PeriodsBuilder.build(
QueueTaskGenerator.onResource(resource), sortedByStartDate),
type, role);
}
private List<LimitingResourceQueue> buildSecondLevel(Resource resource,
List<ResourceAllocation<?>> sortedByStartDate) {
List<LimitingResourceQueue> result = new ArrayList<LimitingResourceQueue>();
Map<Order, List<ResourceAllocation<?>>> byOrder = byOrder(sortedByStartDate);
if (filter()) {
// build time lines for current order
result.addAll(buildTimeLinesForOrder(resource, byOrder
.get(filterBy)));
byOrder.remove(filterBy);
// build time lines for other orders
LimitingResourceQueue lineOthersOrders = buildTimeLinesForOtherOrders(
resource, byOrder);
if (lineOthersOrders != null) {
result.add(lineOthersOrders);
}
} else {
// result.addAll(buildTimeLinesGroupForOrder(resource, byOrder));
}
return result;
}
private LimitingResourceQueue buildTimeLinesForOtherOrders(
Resource resource, Map<Order, List<ResourceAllocation<?>>> byOrder) {
// TODO Auto-generated method stub
return null;
}
private List<LimitingResourceQueue> buildTimeLinesForEachTask(
Criterion criterion,
List<ResourceAllocation<?>> allocations) {
Map<Task, List<ResourceAllocation<?>>> byTask = ResourceAllocation
.byTask(allocations);
List<LoadTimeLine> secondLevel = new ArrayList<LoadTimeLine>();
List<LimitingResourceQueue> secondLevel = new ArrayList<LimitingResourceQueue>();
for (Entry<Task, List<ResourceAllocation<?>>> entry : byTask.entrySet()) {
Task task = entry.getKey();
Set<Criterion> criterions = task.getCriterions();
@ -271,23 +310,6 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
return secondLevel;
}
private List<LoadTimeLine> buildTimeLinesForEachResource(
Criterion criterion, List<GenericResourceAllocation> allocations,
TimeLineRole<BaseEntity> role) {
Map<Resource, List<GenericResourceAllocation>> byResource = GenericResourceAllocation
.byResource(allocations);
List<LoadTimeLine> secondLevel = new ArrayList<LoadTimeLine>();
for (Entry<Resource, List<GenericResourceAllocation>> entry : byResource
.entrySet()) {
Resource resource = entry.getKey();
List<GenericResourceAllocation> resourceAllocations = entry
.getValue();
String descriptionTimeLine = getDescriptionResourceWithCriterions(resource);
}
return secondLevel;
}
private String getDescriptionResourceWithCriterions(Resource resource) {
Set<CriterionSatisfaction> criterionSatisfactions = resource
.getCriterionSatisfactions();
@ -341,13 +363,15 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
return result;
}
private List<LoadTimeLine> buildTimeLinesForOrder(Resource resource,
private List<LimitingResourceQueue> buildTimeLinesForOrder(
Resource resource,
List<ResourceAllocation<?>> sortedByStartDate) {
List<LoadTimeLine> result = new ArrayList<LoadTimeLine>();
result.addAll(buildTimeLinesForEachTask(resource,
onlySpecific(sortedByStartDate)));
result.addAll(buildTimeLinesForEachCriterion(resource,
onlyGeneric(sortedByStartDate)));
List<LimitingResourceQueue> result = new ArrayList<LimitingResourceQueue>();
// Add all time lines
// result.addAll(buildTimeLinesForEachTask(resource,
// onlySpecific(sortedByStartDate)));
// result.addAll(buildTimeLinesForEachCriterion(resource,
// onlyGeneric(sortedByStartDate)));
return result;
}
@ -363,12 +387,12 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
sortedByStartDate);
}
private List<LoadTimeLine> buildTimeLinesForEachCriterion(
private List<LimitingResourceQueue> buildTimeLinesForEachCriterion(
Resource resource, List<GenericResourceAllocation> sortdByStartDate) {
Map<Set<Criterion>, List<GenericResourceAllocation>> byCriterions = GenericResourceAllocation
.byCriterions(sortdByStartDate);
List<LoadTimeLine> result = new ArrayList<LoadTimeLine>();
List<LimitingResourceQueue> result = new ArrayList<LimitingResourceQueue>();
for (Entry<Set<Criterion>, List<GenericResourceAllocation>> entry : byCriterions
.entrySet()) {
@ -388,7 +412,8 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
return result;
}
private List<LoadTimeLine> buildTimeLinesForEachTask(Resource resource,
private List<LimitingResourceQueue> buildTimeLinesForEachTask(
Resource resource,
List<SpecificResourceAllocation> sortedByStartDate) {
List<ResourceAllocation<?>> listOnlySpecific = new ArrayList<ResourceAllocation<?>>(
@ -396,7 +421,7 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
Map<Task, List<ResourceAllocation<?>>> byTask = ResourceAllocation
.byTask(listOnlySpecific);
List<LoadTimeLine> secondLevel = new ArrayList<LoadTimeLine>();
List<LimitingResourceQueue> secondLevel = new ArrayList<LimitingResourceQueue>();
for (Entry<Task, List<ResourceAllocation<?>>> entry : byTask.entrySet()) {
Task task = entry.getKey();
TimeLineRole<BaseEntity> role = getCurrentTimeLineRole(task);
@ -425,8 +450,8 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
@Override
public List<LoadTimeLine> getLoadTimeLines() {
return loadTimeLines;
public List<LimitingResourceQueue> getLimitingResourceQueues() {
return limitingResourceQueues;
}
@Override
@ -440,4 +465,141 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
.getStart()), new LocalDate(interval.getFinish()));
}
}
class PeriodsBuilder {
private final List<? extends ResourceAllocation<?>> sortedByStartDate;
private final List<QueueTaskGenerator> loadPeriodsGenerators = new LinkedList<QueueTaskGenerator>();
private final QueueTaskGeneratorFactory factory;
private PeriodsBuilder(QueueTaskGeneratorFactory factory,
List<? extends ResourceAllocation<?>> sortedByStartDate) {
this.factory = factory;
this.sortedByStartDate = sortedByStartDate;
}
public static List<QueueTask> build(QueueTaskGeneratorFactory factory,
List<? extends ResourceAllocation<?>> sortedByStartDate) {
return new PeriodsBuilder(factory, sortedByStartDate).buildPeriods();
}
private List<QueueTask> buildPeriods() {
for (ResourceAllocation<?> resourceAllocation : sortedByStartDate) {
loadPeriodsGenerators.add(factory.create(resourceAllocation));
}
joinPeriodGenerators();
return toGenerators(loadPeriodsGenerators);
}
private List<QueueTask> toGenerators(List<QueueTaskGenerator> generators) {
List<QueueTask> result = new ArrayList<QueueTask>();
for (QueueTaskGenerator queueTaskGenerator : generators) {
result.add(queueTaskGenerator.build());
}
return result;
}
private void joinPeriodGenerators() {
ListIterator<QueueTaskGenerator> iterator = loadPeriodsGenerators
.listIterator();
while (iterator.hasNext()) {
final QueueTaskGenerator current = findNextOneOverlapping(iterator);
if (current != null) {
rewind(iterator, current);
iterator.remove();
QueueTaskGenerator next = iterator.next();
iterator.remove();
List<QueueTaskGenerator> generated = current.join(next);
final QueueTaskGenerator positionToComeBack = generated.get(0);
final List<QueueTaskGenerator> remaining = loadPeriodsGenerators
.subList(iterator.nextIndex(), loadPeriodsGenerators
.size());
List<QueueTaskGenerator> generatorsSortedByStartDate = mergeListsKeepingByStartSortOrder(
generated, remaining);
final int takenFromRemaining = generatorsSortedByStartDate
.size()
- generated.size();
removeNextElements(iterator, takenFromRemaining);
addAtCurrentPosition(iterator, generatorsSortedByStartDate);
rewind(iterator, positionToComeBack);
}
}
}
private QueueTaskGenerator findNextOneOverlapping(
ListIterator<QueueTaskGenerator> iterator) {
while (iterator.hasNext()) {
QueueTaskGenerator current = iterator.next();
if (!iterator.hasNext()) {
return null;
}
QueueTaskGenerator next = peekNext(iterator);
if (current.overlaps(next)) {
return current;
}
}
return null;
}
private void addAtCurrentPosition(
ListIterator<QueueTaskGenerator> iterator,
List<QueueTaskGenerator> sortedByStartDate) {
for (QueueTaskGenerator l : sortedByStartDate) {
iterator.add(l);
}
}
private void removeNextElements(ListIterator<QueueTaskGenerator> iterator,
final int elementsNumber) {
for (int i = 0; i < elementsNumber; i++) {
iterator.next();
iterator.remove();
}
}
private void rewind(ListIterator<QueueTaskGenerator> iterator,
QueueTaskGenerator nextOne) {
while (peekNext(iterator) != nextOne) {
iterator.previous();
}
}
private List<QueueTaskGenerator> mergeListsKeepingByStartSortOrder(
List<QueueTaskGenerator> joined, List<QueueTaskGenerator> remaining) {
List<QueueTaskGenerator> result = new ArrayList<QueueTaskGenerator>();
ListIterator<QueueTaskGenerator> joinedIterator = joined.listIterator();
ListIterator<QueueTaskGenerator> remainingIterator = remaining
.listIterator();
while (joinedIterator.hasNext() && remainingIterator.hasNext()) {
QueueTaskGenerator fromJoined = peekNext(joinedIterator);
QueueTaskGenerator fromRemaining = peekNext(remainingIterator);
if (fromJoined.getStart().compareTo(fromRemaining.getStart()) <= 0) {
result.add(fromJoined);
joinedIterator.next();
} else {
result.add(fromRemaining);
remainingIterator.next();
}
}
if (joinedIterator.hasNext()) {
result.addAll(joined.subList(joinedIterator.nextIndex(), joined
.size()));
}
return result;
}
private QueueTaskGenerator peekNext(
ListIterator<QueueTaskGenerator> iterator) {
if (!iterator.hasNext()) {
return null;
}
QueueTaskGenerator result = iterator.next();
iterator.previous();
return result;
}
}

View file

@ -139,7 +139,7 @@ public class LimitingResourcesController implements Composer {
private LimitingResourcesPanel buildLimitingResourcesPanel() {
return new LimitingResourcesPanel(limitingResourceQueueModel
.getLoadTimeLines(),
.getLimitingResourceQueues(),
timeTracker);
}

View file

@ -0,0 +1,365 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.navalplanner.web.limitingresources;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.Validate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.joda.time.LocalDate;
import org.navalplanner.business.planner.entities.DayAssignment;
import org.navalplanner.business.planner.entities.GenericResourceAllocation;
import org.navalplanner.business.planner.entities.ResourceAllocation;
import org.navalplanner.business.planner.entities.SpecificDayAssignment;
import org.navalplanner.business.resources.daos.IResourceDAO;
import org.navalplanner.business.resources.entities.Criterion;
import org.navalplanner.business.resources.entities.CriterionCompounder;
import org.navalplanner.business.resources.entities.ICriterion;
import org.navalplanner.business.resources.entities.Resource;
import org.zkoss.ganttz.data.limitingresource.QueueTask;
import org.zkoss.ganttz.data.resourceload.LoadLevel;
interface QueueTaskGeneratorFactory {
QueueTaskGenerator create(ResourceAllocation<?> allocation);
}
abstract class QueueTaskGenerator {
private static final Log LOG = LogFactory.getLog(QueueTaskGenerator.class);
public static QueueTaskGeneratorFactory onResource(Resource resource) {
return new OnResourceFactory(resource);
}
public static QueueTaskGeneratorFactory onResourceSatisfying(
Resource resource, Collection<Criterion> criterions) {
return new OnResourceFactory(resource, criterions);
}
private static class OnResourceFactory implements
QueueTaskGeneratorFactory {
private final Resource resource;
private final ICriterion criterion;
public OnResourceFactory(Resource resource) {
this(resource, Collections.<Criterion> emptyList());
}
public OnResourceFactory(Resource resource,
Collection<Criterion> criterionsToSatisfy) {
Validate.notNull(resource);
this.resource = resource;
this.criterion = CriterionCompounder.buildAnd(criterionsToSatisfy)
.getResult();
}
@Override
public QueueTaskGenerator create(ResourceAllocation<?> allocation) {
return new QueueTaskGeneratorOnResource(resource, allocation,
criterion);
}
}
public static QueueTaskGeneratorFactory onCriterion(
final Criterion criterion, final IResourceDAO resourcesDAO) {
return new QueueTaskGeneratorFactory() {
@Override
public QueueTaskGenerator create(ResourceAllocation<?> allocation) {
return new QueueTaskGeneratorOnCriterion(criterion,
allocation, findResources(criterion, resourcesDAO));
}
private List<Resource> findResources(final Criterion criterion,
final IResourceDAO resourcesDAO) {
return resourcesDAO
.findSatisfyingCriterionsAtSomePoint(Collections
.singletonList(criterion));
}
};
}
protected final LocalDate start;
protected final LocalDate end;
private List<ResourceAllocation<?>> allocationsOnInterval = new ArrayList<ResourceAllocation<?>>();
protected QueueTaskGenerator(LocalDate start,
LocalDate end, List<ResourceAllocation<?>> allocationsOnInterval) {
Validate.notNull(start);
Validate.notNull(end);
Validate.notNull(allocationsOnInterval);
this.start = start;
this.end = end;
this.allocationsOnInterval = ResourceAllocation
.getSatisfied(allocationsOnInterval);
}
public List<QueueTaskGenerator> join(QueueTaskGenerator next) {
if (!overlaps(next)) {
return stripEmpty(this, next);
}
if (isIncluded(next)) {
return stripEmpty(this.until(next.start), intersect(next), this
.from(next.end));
}
assert overlaps(next) && !isIncluded(next);
return stripEmpty(this.until(next.start), intersect(next), next
.from(end));
}
protected List<ResourceAllocation<?>> getAllocationsOnInterval() {
return allocationsOnInterval;
}
private List<QueueTaskGenerator> stripEmpty(
QueueTaskGenerator... generators) {
List<QueueTaskGenerator> result = new ArrayList<QueueTaskGenerator>();
for (QueueTaskGenerator loadPeriodGenerator : generators) {
if (!loadPeriodGenerator.isEmpty()) {
result.add(loadPeriodGenerator);
}
}
return result;
}
private boolean isEmpty() {
return start.equals(end);
}
protected abstract QueueTaskGenerator create(LocalDate start,
LocalDate end, List<ResourceAllocation<?>> allocationsOnInterval);
private QueueTaskGenerator intersect(QueueTaskGenerator other) {
return create(max(this.start, other.start),
min(this.end, other.end), plusAllocations(other));
}
private static LocalDate max(LocalDate l1, LocalDate l2) {
return l1.compareTo(l2) < 0 ? l2 : l1;
}
private static LocalDate min(LocalDate l1, LocalDate l2) {
return l1.compareTo(l2) < 0 ? l1 : l2;
}
private List<ResourceAllocation<?>> plusAllocations(
QueueTaskGenerator other) {
List<ResourceAllocation<?>> result = new ArrayList<ResourceAllocation<?>>();
result.addAll(allocationsOnInterval);
result.addAll(other.allocationsOnInterval);
return result;
}
private QueueTaskGenerator from(LocalDate newStart) {
return create(newStart, end,
allocationsOnInterval);
}
private QueueTaskGenerator until(LocalDate newEnd) {
return create(start, newEnd,
allocationsOnInterval);
}
boolean overlaps(QueueTaskGenerator other) {
return (start.compareTo(other.end) < 0 && other.start
.compareTo(this.end) < 0);
}
private boolean isIncluded(QueueTaskGenerator other) {
return other.start.compareTo(start) >= 0
&& other.end.compareTo(end) <= 0;
}
public QueueTask build() {
return new QueueTask(start, end, getTotalWorkHours(),
getHoursAssigned(), new LoadLevel(
calculateLoadPercentage()));
}
protected abstract int getTotalWorkHours();
private int calculateLoadPercentage() {
final int totalResourceWorkHours = getTotalWorkHours();
int assigned = getHoursAssigned();
if (totalResourceWorkHours == 0) {
return assigned == 0 ? 0 : Integer.MAX_VALUE;
}
double proportion = assigned / (double) totalResourceWorkHours;
return new BigDecimal(proportion).scaleByPowerOfTen(2).intValue();
}
protected abstract int getHoursAssigned();
protected final int sumAllocations() {
int sum = 0;
for (ResourceAllocation<?> resourceAllocation : allocationsOnInterval) {
sum += getAssignedHoursFor(resourceAllocation);
}
return sum;
}
protected abstract int getAssignedHoursFor(
ResourceAllocation<?> resourceAllocation);
public LocalDate getStart() {
return start;
}
public LocalDate getEnd() {
return end;
}
}
class QueueTaskGeneratorOnResource extends QueueTaskGenerator {
private Resource resource;
private final ICriterion criterion;
QueueTaskGeneratorOnResource(Resource resource, LocalDate start,
LocalDate end, List<ResourceAllocation<?>> allocationsOnInterval,
ICriterion criterion) {
super(start, end, allocationsOnInterval);
this.resource = resource;
this.criterion = criterion;
}
QueueTaskGeneratorOnResource(Resource resource,
ResourceAllocation<?> initial, ICriterion criterion) {
super(initial.getStartDate(), initial.getEndDate(), Arrays.<ResourceAllocation<?>> asList(initial));
this.resource = resource;
this.criterion = criterion;
}
@Override
protected QueueTaskGenerator create(LocalDate start, LocalDate end,
List<ResourceAllocation<?>> allocationsOnInterval) {
return new QueueTaskGeneratorOnResource(resource, start, end,
allocationsOnInterval, criterion);
}
@Override
protected int getTotalWorkHours() {
return resource.getTotalWorkHours(start, end, criterion);
}
@Override
protected int getAssignedHoursFor(ResourceAllocation<?> resourceAllocation) {
return resourceAllocation.getAssignedHours(resource, start, end);
}
@Override
protected int getHoursAssigned() {
return sumAllocations();
}
}
class QueueTaskGeneratorOnCriterion extends QueueTaskGenerator {
private final Criterion criterion;
private final List<Resource> resourcesSatisfyingCriterionAtSomePoint;
public QueueTaskGeneratorOnCriterion(Criterion criterion,
ResourceAllocation<?> allocation,
List<Resource> resourcesSatisfyingCriterionAtSomePoint) {
this(criterion, allocation.getStartDate(), allocation.getEndDate(),
Arrays.<ResourceAllocation<?>> asList(allocation),
resourcesSatisfyingCriterionAtSomePoint);
}
public QueueTaskGeneratorOnCriterion(Criterion criterion,
LocalDate startDate, LocalDate endDate,
List<ResourceAllocation<?>> allocations,
List<Resource> resourcesSatisfyingCriterionAtSomePoint) {
super(startDate, endDate, allocations);
this.criterion = criterion;
this.resourcesSatisfyingCriterionAtSomePoint = resourcesSatisfyingCriterionAtSomePoint;
}
@Override
protected QueueTaskGenerator create(LocalDate start, LocalDate end,
List<ResourceAllocation<?>> allocationsOnInterval) {
QueueTaskGeneratorOnCriterion result = new QueueTaskGeneratorOnCriterion(
criterion, start, end, allocationsOnInterval,
resourcesSatisfyingCriterionAtSomePoint);
result.specificByResourceCached = specificByResourceCached;
return result;
}
private List<GenericResourceAllocation> genericAllocationsOnInterval() {
return ResourceAllocation.getOfType(GenericResourceAllocation.class,
getAllocationsOnInterval());
}
@Override
protected int getAssignedHoursFor(ResourceAllocation<?> resourceAllocation) {
return resourceAllocation.getAssignedHours(start, end);
}
@Override
protected int getTotalWorkHours() {
int sum = 0;
for (Resource resource : resourcesSatisfyingCriterionAtSomePoint) {
sum += resource.getTotalWorkHours(start, end, criterion);
}
return sum;
}
@Override
protected int getHoursAssigned() {
return sumAllocations();
}
private Map<Resource, List<SpecificDayAssignment>> specificByResourceCached = new HashMap<Resource, List<SpecificDayAssignment>>();
private List<SpecificDayAssignment> getSpecificOrderedAssignmentsFor(
Resource resource) {
if (!specificByResourceCached.containsKey(resource)) {
specificByResourceCached.put(resource, DayAssignment
.specific(DayAssignment.orderedByDay(resource
.getAssignments())));
}
return specificByResourceCached.get(resource);
}
private int sum(List<SpecificDayAssignment> specific) {
int result = 0;
for (SpecificDayAssignment s : specific) {
result += s.getHours();
}
return result;
}
}