ItEr56S09RFAspectosGraficosRecursoLimitantesItEr55S11: Added QueueTask and LimitingResourceQueue classes
This commit is contained in:
parent
a06aea5656
commit
b58750d830
10 changed files with 1005 additions and 126 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ public class LimitingResourcesController implements Composer {
|
|||
|
||||
private LimitingResourcesPanel buildLimitingResourcesPanel() {
|
||||
return new LimitingResourcesPanel(limitingResourceQueueModel
|
||||
.getLoadTimeLines(),
|
||||
.getLimitingResourceQueues(),
|
||||
timeTracker);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue