ItEr49S16CUVistaRecursosTempoPorProxectoItEr28S07: Adds to the resource loading screen a tree structure.

Adds to the resource loading screen a tree structure to sort the resources load by orders and, by the
    specific and general criterions.It pulls up the children property to LoadTimeLine and converts it to
    a List<LoadTimeLine>. It pull up the method HasChildren and the rest of methods at LoadTimeLinesGroup,
    so the LoadTimeLinesGroup is not already needed.
This commit is contained in:
Susana Montes Pedreira 2010-03-05 09:38:01 +01:00 committed by Javier Moran Rua
parent 8da563b358
commit f8ae88d94b
13 changed files with 415 additions and 226 deletions

View file

@ -42,15 +42,23 @@ public class LoadPeriod {
private final LoadLevel loadLevel;
private final int totalResourceWorkHours;
public LoadPeriod(LocalDate start, LocalDate end, LoadLevel loadLevel) {
private final int assignedHours;
public LoadPeriod(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() {
@ -114,4 +122,11 @@ public class LoadPeriod {
return loadLevel;
}
public int getTotalResourceWorkHours() {
return totalResourceWorkHours;
}
public int getAssignedHours() {
return assignedHours;
}
}

View file

@ -20,23 +20,32 @@
package org.zkoss.ganttz.data.resourceload;
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.util.Interval;
public class LoadTimeLine {
private final String conceptName;
private final List<LoadPeriod> loadPeriods;
private final String type;
private final List<LoadTimeLine> children;
public LoadTimeLine(String conceptName, List<LoadPeriod> loadPeriods) {
Validate.notEmpty(conceptName);
Validate.notNull(loadPeriods);
this.loadPeriods = LoadPeriod.sort(loadPeriods);
this.conceptName = conceptName;
this.type = "";
this.children = Collections
.unmodifiableList(new ArrayList<LoadTimeLine>());
}
public LoadTimeLine(String conceptName, List<LoadPeriod> loadPeriods,
@ -46,6 +55,21 @@ public class LoadTimeLine {
this.loadPeriods = LoadPeriod.sort(loadPeriods);
this.conceptName = conceptName;
this.type = type;
this.children = Collections
.unmodifiableList(new ArrayList<LoadTimeLine>());
}
public LoadTimeLine(LoadTimeLine principal, List<LoadTimeLine> children) {
Validate.notEmpty(principal.getConceptName());
Validate.notNull(principal.getLoadPeriods());
this.loadPeriods = LoadPeriod.sort(principal.getLoadPeriods());
this.conceptName = principal.getConceptName();
this.type = principal.getType();
Validate.notNull(children);
allChildrenAreNotEmpty(children);
this.children = Collections
.unmodifiableList(new ArrayList<LoadTimeLine>(children));
}
public List<LoadPeriod> getLoadPeriods() {
@ -64,7 +88,7 @@ public class LoadTimeLine {
return loadPeriods.get(loadPeriods.size() - 1);
}
public LocalDate getStart() {
public LocalDate getStartPeriod() {
if (isEmpty()) {
return null;
}
@ -75,7 +99,7 @@ public class LoadTimeLine {
return loadPeriods.isEmpty();
}
public LocalDate getEnd() {
public LocalDate getEndPeriod() {
if (isEmpty()) {
return null;
}
@ -85,4 +109,93 @@ public class LoadTimeLine {
public String getType() {
return this.type;
}
public static Interval getIntervalFrom(List<LoadTimeLine> timeLines) {
Validate.notEmpty(timeLines);
LocalDate start = null;
LocalDate end = null;
for (LoadTimeLine 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<LoadTimeLine> lines) {
for (LoadTimeLine 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<LoadTimeLine> getChildren() {
return children;
}
public List<LoadTimeLine> getAllChildren() {
List<LoadTimeLine> result = new ArrayList<LoadTimeLine>();
for (LoadTimeLine child : children) {
result.addAll(child.getAllChildren());
result.add(child);
}
return result;
}
public LocalDate getStart() {
LocalDate result = getStartPeriod();
for (LoadTimeLine 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 (LoadTimeLine loadTimeLine : getChildren()) {
LocalDate end = loadTimeLine.getEnd();
if (end != null) {
result = result == null || result.compareTo(end) < 0 ? end : result;
}
}
return result;
}
}

View file

@ -1,134 +0,0 @@
/*
* 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.resourceload;
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.util.Interval;
public class LoadTimelinesGroup {
public static Interval getIntervalFrom(List<LoadTimelinesGroup> timeLines) {
Validate.notEmpty(timeLines);
LocalDate start = null;
LocalDate end = null;
for (LoadTimelinesGroup loadTimelinesGroup : timeLines) {
Validate.notNull(loadTimelinesGroup.getStart());
start = min(start, loadTimelinesGroup.getStart());
Validate.notNull(loadTimelinesGroup.getEnd());
end = max(end, loadTimelinesGroup.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 final LoadTimeLine principal;
private final List<LoadTimeLine> children;
public LoadTimelinesGroup(LoadTimeLine principal,
List<? extends LoadTimeLine> children) {
Validate.notNull(principal);
Validate.notNull(children);
allChildrenAreNotEmpty(children);
this.principal = principal;
this.children = Collections
.unmodifiableList(new ArrayList<LoadTimeLine>(children));
}
private static void allChildrenAreNotEmpty(
List<? extends LoadTimeLine> lines) {
for (LoadTimeLine l : lines) {
if (l.isEmpty()) {
throw new IllegalArgumentException(l + " is empty");
}
}
}
public LoadTimeLine getPrincipal() {
return principal;
}
public List<LoadTimeLine> getChildren() {
return children;
}
private List<LoadTimeLine> getAll() {
List<LoadTimeLine> result = new ArrayList<LoadTimeLine>();
result.add(getPrincipal());
result.addAll(getChildren());
return result;
}
public LocalDate getStart() {
LocalDate result = null;
for (LoadTimeLine loadTimeLine : getAll()) {
LocalDate start = loadTimeLine.getStart();
result = result == null || result.compareTo(start) > 0 ? start
: result;
}
return result;
}
public LocalDate getEnd() {
LocalDate result = null;
for (LoadTimeLine loadTimeLine : getAll()) {
LocalDate end = loadTimeLine.getEnd();
result = result == null || result.compareTo(end) < 0 ? end
: result;
}
return result;
}
public boolean isEmpty() {
return principal.isEmpty();
}
}

View file

@ -96,8 +96,15 @@ public class ResourceLoadComponent extends XulElement {
Div result = new Div();
result.setClass(String.format("taskassignmentinterval %s", loadPeriod
.getLoadLevel().getCategory()));
result.setTooltiptext("Load: "
+ loadPeriod.getLoadLevel().getPercentage() + "%");
String load = "Load: " + loadPeriod.getLoadLevel().getPercentage()
+ "% , ";
if (loadPeriod.getLoadLevel().getPercentage() == Integer.MAX_VALUE) {
load = "";
}
result.setTooltiptext(load
+ "total work hours: " + loadPeriod.getTotalResourceWorkHours()
+ " , " + "assigned hours: " + loadPeriod.getAssignedHours());
result.setLeft(forCSS(getStartPixels(datesMapper, loadPeriod)));
result.setWidth(forCSS(getWidthPixels(datesMapper, loadPeriod)));

View file

@ -20,6 +20,10 @@
package org.zkoss.ganttz.resourceload;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.zkoss.ganttz.data.resourceload.LoadTimeLine;
import org.zkoss.ganttz.util.MutableTreeModel;
import org.zkoss.zk.ui.Component;
@ -31,6 +35,7 @@ import org.zkoss.zul.Div;
import org.zkoss.zul.Label;
import org.zkoss.zul.Popup;
import org.zkoss.zul.Treecell;
import org.zkoss.zul.Treechildren;
import org.zkoss.zul.Treeitem;
import org.zkoss.zul.TreeitemRenderer;
import org.zkoss.zul.Treerow;
@ -41,7 +46,8 @@ public class ResourceLoadLeftPane extends HtmlMacroComponent {
private MutableTreeModel<LoadTimeLine> modelForTree;
private final ResourceLoadList resourceLoadList;
public ResourceLoadLeftPane(MutableTreeModel<LoadTimeLine> modelForTree,
public ResourceLoadLeftPane(
MutableTreeModel<LoadTimeLine> modelForTree,
ResourceLoadList resourceLoadList) {
this.resourceLoadList = resourceLoadList;
this.modelForTree = modelForTree;
@ -58,26 +64,31 @@ public class ResourceLoadLeftPane extends HtmlMacroComponent {
private TreeitemRenderer getRendererForTree() {
return new TreeitemRenderer() {
@Override
public void render(Treeitem item, Object data) throws Exception {
public void render(Treeitem item, Object data)
throws Exception {
LoadTimeLine line = (LoadTimeLine) data;
item.setOpen(true);
item.setOpen(false);
item.setValue(line);
Treerow row = new Treerow();
Treecell cell = new Treecell();
Component component = createComponent(line);
item.appendChild(row);
row.appendChild(cell);
cell.appendChild(component);
collapse(line);
addExpandedListener(item, line);
}
private void addExpandedListener(Treeitem item,
private void addExpandedListener(final Treeitem item,
final LoadTimeLine line) {
item.addEventListener("onOpen", new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
OpenEvent openEvent = (OpenEvent) event;
if (openEvent.isOpen()) {
expand(line);
List<LoadTimeLine> closed = calculatedClosedItems(item);
expand(line, closed);
} else {
collapse(line);
}
@ -101,8 +112,46 @@ public class ResourceLoadLeftPane extends HtmlMacroComponent {
resourceLoadList.collapse(line);
}
private void expand(LoadTimeLine line) {
resourceLoadList.expand(line);
private void expand(LoadTimeLine line, List<LoadTimeLine> closed) {
resourceLoadList.expand(line, closed);
}
private List<LoadTimeLine> calculatedClosedItems(Treeitem item) {
List<LoadTimeLine> result = new ArrayList<LoadTimeLine>();
Treechildren treeChildren = item.getTreechildren();
if (treeChildren != null) {
List<Treeitem> myTreeItems = (List<Treeitem>) treeChildren
.getChildren();
Iterator<Treeitem> iterator = myTreeItems.iterator();
while (iterator.hasNext()) {
Treeitem child = (Treeitem) iterator.next();
if (!child.isOpen()) {
result.addAll(getLineChildrenBy(child));
} else {
result.addAll(calculatedClosedItems(child));
}
}
}
return result;
}
private List<LoadTimeLine> getLineChildrenBy(Treeitem item) {
List<LoadTimeLine> result = new ArrayList<LoadTimeLine>();
LoadTimeLine line = getLineByTreeitem(item);
if (line != null) {
result.addAll(line.getAllChildren());
}
return result;
}
private LoadTimeLine getLineByTreeitem(Treeitem child) {
LoadTimeLine line = null;
try {
line = (LoadTimeLine) child.getValue();
} catch (Exception e) {
return null;
}
return line;
}
private Tree getContainerTree() {
@ -115,7 +164,6 @@ public class ResourceLoadLeftPane extends HtmlMacroComponent {
return result;
}
private Component createSecondLevel(LoadTimeLine loadTimeLine) {
Div result = createLabelWithName(loadTimeLine);
result.setSclass("secondlevel");

View file

@ -70,15 +70,6 @@ public class ResourceLoadList extends HtmlMacroComponent implements
}
}
private List<LoadTimeLine> getChildrenOf(LoadTimeLine parent) {
List<LoadTimeLine> result = new ArrayList<LoadTimeLine>();
final int length = timelinesTree.getChildCount(parent);
for (int i = 0; i < length; i++) {
result.add(timelinesTree.getChild(parent, i));
}
return result;
}
private IZoomLevelChangedListener adjustTimeTrackerSizeListener() {
return new IZoomLevelChangedListener() {
@ -103,7 +94,7 @@ public class ResourceLoadList extends HtmlMacroComponent implements
}
public void collapse(LoadTimeLine line) {
for (LoadTimeLine l : getChildrenOf(line)) {
for (LoadTimeLine l : line.getAllChildren()) {
getComponentFor(l).detach();
}
}
@ -114,10 +105,14 @@ public class ResourceLoadList extends HtmlMacroComponent implements
return resourceLoadComponent;
}
public void expand(LoadTimeLine line) {
public void expand(LoadTimeLine line, List<LoadTimeLine> closed) {
ResourceLoadComponent parentComponent = getComponentFor(line);
Component nextSibling = parentComponent.getNextSibling();
for (LoadTimeLine loadTimeLine : getChildrenReverseOrderFor(line)) {
List<LoadTimeLine> childrenToOpen = getChildrenReverseOrderFor(line);
childrenToOpen.removeAll(closed);
for (LoadTimeLine loadTimeLine : childrenToOpen) {
ResourceLoadComponent child = getComponentFor(loadTimeLine);
insertBefore(child, nextSibling);
nextSibling = child;
@ -126,7 +121,7 @@ public class ResourceLoadList extends HtmlMacroComponent implements
}
private List<LoadTimeLine> getChildrenReverseOrderFor(LoadTimeLine line) {
List<LoadTimeLine> childrenOf = getChildrenOf(line);
List<LoadTimeLine> childrenOf = line.getAllChildren();
Collections.reverse(childrenOf);
return childrenOf;
}

View file

@ -24,7 +24,6 @@ import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.zkoss.ganttz.data.resourceload.LoadTimeLine;
import org.zkoss.ganttz.data.resourceload.LoadTimelinesGroup;
import org.zkoss.ganttz.timetracker.TimeTracker;
import org.zkoss.ganttz.timetracker.TimeTrackerComponent;
import org.zkoss.ganttz.timetracker.zoom.ZoomLevel;
@ -60,7 +59,7 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
private ResourceLoadList resourceLoadList;
private final List<LoadTimelinesGroup> groups;
private final List<LoadTimeLine> groups;
private MutableTreeModel<LoadTimeLine> treeModel;
@ -68,7 +67,7 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
private Listbox listZoomLevels;
public ResourcesLoadPanel(List<LoadTimelinesGroup> groups,
public ResourcesLoadPanel(List<LoadTimeLine> groups,
TimeTracker timeTracker) {
this.groups = groups;
this.timeTracker = timeTracker;
@ -145,18 +144,28 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
private MutableTreeModel<LoadTimeLine> createModelForTree() {
MutableTreeModel<LoadTimeLine> result = MutableTreeModel
.create(LoadTimeLine.class);
for (LoadTimelinesGroup loadTimelinesGroup : this.groups) {
LoadTimeLine principal = loadTimelinesGroup.getPrincipal();
result.addToRoot(principal);
result.add(principal, loadTimelinesGroup.getChildren());
for (LoadTimeLine loadTimeLine : this.groups) {
result.addToRoot(loadTimeLine);
result = addNodes(result, loadTimeLine);
}
return result;
}
private MutableTreeModel<LoadTimeLine> addNodes(
MutableTreeModel<LoadTimeLine> tree, LoadTimeLine parent) {
if (!parent.getChildren().isEmpty()) {
tree.add(parent, parent.getChildren());
for (LoadTimeLine loadTimeLine : parent.getChildren()) {
tree = addNodes(tree, loadTimeLine);
}
}
return tree;
}
private TimeTrackerComponent timeTrackerForResourcesLoadPanel(
TimeTracker timeTracker) {
return new TimeTrackerComponent(timeTracker) {
@Override
protected void scrollHorizontalPercentage(int pixelsDisplacement) {
response("", new AuInvoke(resourceLoadList,

View file

@ -54,35 +54,44 @@ public class LoadPeriodTest {
private void givenExampleLoadPeriod(LocalDate start, LocalDate end,
LoadLevel loadLevel) {
loadPeriod = new LoadPeriod(start, end, loadLevel);
loadPeriod = new LoadPeriod(start, end, totalHours, assignedHours,
loadLevel);
}
@Test(expected = IllegalArgumentException.class)
public void aLoadPeriodMustHaveAStartDate() {
new LoadPeriod(null, new LocalDate(), correctLoadLevel());
new LoadPeriod(null, new LocalDate(), totalHours, assignedHours,
correctLoadLevel());
}
private static final int totalHours = 100;
private static final int assignedHours = 40;
private static LoadLevel correctLoadLevel() {
return new LoadLevel(40);
}
@Test(expected = IllegalArgumentException.class)
public void aLoadPeriodMustHaveAnEndDate() {
new LoadPeriod(new LocalDate(), null, correctLoadLevel());
new LoadPeriod(new LocalDate(), null, totalHours, assignedHours,
correctLoadLevel());
}
@Test(expected = IllegalArgumentException.class)
public void theEndDateCantBeBeforeTheStartDate() {
LocalDate start = new LocalDate(2009, 10, 4);
LocalDate end = new LocalDate(2009, 10, 3);
new LoadPeriod(start, end, correctLoadLevel());
new LoadPeriod(start, end, totalHours, assignedHours,
correctLoadLevel());
}
@Test
public void theEndDateCanBeTheSameThanTheStartDate() {
LocalDate start = new LocalDate(2009, 10, 4);
LocalDate end = new LocalDate(2009, 10, 4);
new LoadPeriod(start, end, correctLoadLevel());
new LoadPeriod(start, end, totalHours, assignedHours,
correctLoadLevel());
}
@Test
@ -128,7 +137,8 @@ public class LoadPeriodTest {
private static LoadPeriod create(int startYear, int startMonth,
int startDay, int endYear, int endMonth, int endDay) {
return new LoadPeriod(new LocalDate(startYear, startMonth, startDay),
new LocalDate(endYear, endMonth, endDay), correctLoadLevel());
new LocalDate(endYear, endMonth, endDay), totalHours,
assignedHours, correctLoadLevel());
}
@Test(expected = IllegalArgumentException.class)
@ -178,7 +188,7 @@ public class LoadPeriodTest {
@Test(expected = IllegalArgumentException.class)
public void aLoadPeriodMustHaveANotNullLoadLevel() {
givenExampleLoadPeriod();
new LoadPeriod(start, end, null);
new LoadPeriod(start, end, totalHours, assignedHours, null);
}
@Test

View file

@ -62,7 +62,8 @@ public class LoadTimelineTest {
conceptName = "bla";
loadTimeLine = new LoadTimeLine(conceptName, Arrays
.asList(new LoadPeriod(new LocalDate(2009, 10, 5),
new LocalDate(2009, 10, 11), new LoadLevel(20))));
new LocalDate(2009, 10, 11), 100, 20,
new LoadLevel(20))));
}
@Test
@ -75,9 +76,9 @@ public class LoadTimelineTest {
@Test
public void aLoadTimelineSortsItsReceivedPeriods() {
LoadPeriod l1 = new LoadPeriod(new LocalDate(2009, 10, 5),
new LocalDate(2009, 10, 11), new LoadLevel(20));
new LocalDate(2009, 10, 11), 100, 20, new LoadLevel(20));
LoadPeriod l2 = new LoadPeriod(new LocalDate(2009, 5, 3),
new LocalDate(2009, 6, 3), new LoadLevel(20));
new LocalDate(2009, 6, 3), 100, 20, new LoadLevel(20));
LoadTimeLine loadTimeLine = new LoadTimeLine("bla", Arrays.asList(l1, l2));
List<LoadPeriod> loadPeriods = loadTimeLine.getLoadPeriods();
@ -88,9 +89,9 @@ public class LoadTimelineTest {
@Test(expected = IllegalArgumentException.class)
public void theLoadPeriodsMustNotOverlap() {
LoadPeriod l1 = new LoadPeriod(new LocalDate(2009, 10, 5),
new LocalDate(2009, 10, 11), new LoadLevel(20));
new LocalDate(2009, 10, 11), 100, 20, new LoadLevel(20));
LoadPeriod l2 = new LoadPeriod(new LocalDate(2009, 5, 3),
new LocalDate(2009, 10, 10), new LoadLevel(20));
new LocalDate(2009, 10, 10), 100, 20, new LoadLevel(20));
new LoadTimeLine("bla", Arrays.asList(l1, l2));
}

View file

@ -23,7 +23,7 @@ package org.navalplanner.web.resourceload;
import java.util.List;
import org.navalplanner.business.orders.entities.Order;
import org.zkoss.ganttz.data.resourceload.LoadTimelinesGroup;
import org.zkoss.ganttz.data.resourceload.LoadTimeLine;
import org.zkoss.ganttz.timetracker.zoom.ZoomLevel;
import org.zkoss.ganttz.util.Interval;
@ -33,7 +33,7 @@ public interface IResourceLoadModel {
void initGlobalView(Order filterBy);
List<LoadTimelinesGroup> getLoadTimeLines();
List<LoadTimeLine> getLoadTimeLines();
Interval getViewInterval();

View file

@ -196,7 +196,8 @@ abstract class LoadPeriodGenerator {
}
public LoadPeriod build() {
return new LoadPeriod(start, end, new LoadLevel(
return new LoadPeriod(start, end, getTotalWorkHours(),
getHoursAssigned(), new LoadLevel(
calculateLoadPercentage()));
}

View file

@ -20,6 +20,8 @@
package org.navalplanner.web.resourceload;
import static org.navalplanner.web.I18nHelper._;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -36,6 +38,7 @@ import org.zkoss.ganttz.resourceload.ResourcesLoadPanel.IToolbarCommand;
import org.zkoss.ganttz.timetracker.TimeTracker;
import org.zkoss.ganttz.timetracker.zoom.SeveralModificators;
import org.zkoss.zk.ui.util.Composer;
import org.zkoss.zul.Messagebox;
/**
* Controller for global resourceload view
@ -69,16 +72,28 @@ public class ResourceLoadController implements Composer {
}
public void reload() {
if (filterBy == null) {
resourceLoadModel.initGlobalView();
} else {
resourceLoadModel.initGlobalView(filterBy);
try {
if (filterBy == null) {
resourceLoadModel.initGlobalView();
} else {
resourceLoadModel.initGlobalView(filterBy);
}
ResourcesLoadPanel resourcesLoadPanel = buildResourcesLoadPanel();
this.parent.getChildren().clear();
this.parent.appendChild(resourcesLoadPanel);
resourcesLoadPanel.afterCompose();
addCommands(resourcesLoadPanel);
} catch (IllegalArgumentException e) {
try {
Messagebox
.show(
_("Some lines have not allocation periods.\nBelow it shows the load all company resources"),
_("Error"), Messagebox.OK, Messagebox.ERROR);
} catch (InterruptedException o) {
throw new RuntimeException(e);
}
}
ResourcesLoadPanel resourcesLoadPanel = buildResourcesLoadPanel();
this.parent.getChildren().clear();
this.parent.appendChild(resourcesLoadPanel);
resourcesLoadPanel.afterCompose();
addCommands(resourcesLoadPanel);
}
private void addCommands(ResourcesLoadPanel resourcesLoadPanel) {

View file

@ -27,6 +27,7 @@ import java.util.Arrays;
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;
@ -36,7 +37,9 @@ import java.util.Map.Entry;
import org.joda.time.LocalDate;
import org.navalplanner.business.orders.daos.IOrderDAO;
import org.navalplanner.business.orders.daos.IOrderElementDAO;
import org.navalplanner.business.orders.entities.Order;
import org.navalplanner.business.orders.entities.OrderElement;
import org.navalplanner.business.planner.daos.IResourceAllocationDAO;
import org.navalplanner.business.planner.daos.ITaskSourceDAO;
import org.navalplanner.business.planner.entities.GenericResourceAllocation;
@ -54,7 +57,6 @@ import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.zkoss.ganttz.data.resourceload.LoadPeriod;
import org.zkoss.ganttz.data.resourceload.LoadTimeLine;
import org.zkoss.ganttz.data.resourceload.LoadTimelinesGroup;
import org.zkoss.ganttz.timetracker.zoom.ZoomLevel;
import org.zkoss.ganttz.util.Interval;
@ -65,6 +67,9 @@ public class ResourceLoadModel implements IResourceLoadModel {
@Autowired
private IResourceDAO resourcesDAO;
@Autowired
private IOrderElementDAO orderElementDAO;
@Autowired
private IOrderDAO orderDAO;
@ -74,7 +79,7 @@ public class ResourceLoadModel implements IResourceLoadModel {
@Autowired
private IResourceAllocationDAO resourceAllocationDAO;
private List<LoadTimelinesGroup> loadTimeLines;
private List<LoadTimeLine> loadTimeLines;
private Interval viewInterval;
private Order filterBy;
@ -94,9 +99,9 @@ public class ResourceLoadModel implements IResourceLoadModel {
}
private void doGlobalView() {
loadTimeLines = calculateLoadTimelinesGroups();
loadTimeLines = calculateLoadTimeLines();
if (!loadTimeLines.isEmpty()) {
viewInterval = LoadTimelinesGroup.getIntervalFrom(loadTimeLines);
viewInterval = LoadTimeLine.getIntervalFrom(loadTimeLines);
} else {
viewInterval = new Interval(new Date(), plusFiveYears(new Date()));
}
@ -109,8 +114,8 @@ public class ResourceLoadModel implements IResourceLoadModel {
return calendar.getTime();
}
private List<LoadTimelinesGroup> calculateLoadTimelinesGroups() {
List<LoadTimelinesGroup> result = new ArrayList<LoadTimelinesGroup>();
private List<LoadTimeLine> calculateLoadTimeLines() {
List<LoadTimeLine> result = new ArrayList<LoadTimeLine>();
result.addAll(groupsFor(resourcesToShow()));
result.addAll(groupsFor(genericAllocationsByCriterion()));
return result;
@ -159,15 +164,16 @@ public class ResourceLoadModel implements IResourceLoadModel {
return resourcesDAO.list(Resource.class);
}
private List<LoadTimelinesGroup> groupsFor(
private List<LoadTimeLine> groupsFor(
Map<Criterion, List<GenericResourceAllocation>> genericAllocationsByCriterion) {
List<LoadTimelinesGroup> result = new ArrayList<LoadTimelinesGroup>();
List<LoadTimeLine> result = new ArrayList<LoadTimeLine>();
for (Entry<Criterion, List<GenericResourceAllocation>> entry : genericAllocationsByCriterion
.entrySet()) {
List<GenericResourceAllocation> allocations = ResourceAllocation
.sortedByStartDate(entry.getValue());
LoadTimelinesGroup group = new LoadTimelinesGroup(createPrincipal(
entry.getKey(), allocations), new ArrayList<LoadTimeLine>());
LoadTimeLine group = new LoadTimeLine(createPrincipal(
entry.getKey(), allocations),
new ArrayList<LoadTimeLine>());
if (!group.isEmpty()) {
result.add(group);
}
@ -188,10 +194,10 @@ public class ResourceLoadModel implements IResourceLoadModel {
value);
}
private List<LoadTimelinesGroup> groupsFor(List<Resource> allResources) {
List<LoadTimelinesGroup> result = new ArrayList<LoadTimelinesGroup>();
private List<LoadTimeLine> groupsFor(List<Resource> allResources) {
List<LoadTimeLine> result = new ArrayList<LoadTimeLine>();
for (Resource resource : allResources) {
LoadTimelinesGroup group = buildGroup(resource);
LoadTimeLine group = buildGroup(resource);
if (!group.isEmpty()) {
result.add(group);
}
@ -199,18 +205,99 @@ public class ResourceLoadModel implements IResourceLoadModel {
return result;
}
private LoadTimelinesGroup buildGroup(Resource resource) {
private LoadTimeLine buildGroup(Resource resource) {
List<ResourceAllocation<?>> sortedByStartDate = ResourceAllocation
.sortedByStartDate(resourceAllocationDAO
.findAllocationsRelatedTo(resource));
return new LoadTimelinesGroup(buildTimeLine(resource, resource
.getShortDescription(), sortedByStartDate), buildSecondLevel(
resource, sortedByStartDate));
LoadTimeLine result = new LoadTimeLine(buildTimeLine(
resource, resource.getShortDescription(), sortedByStartDate),
buildSecondLevel(resource, sortedByStartDate));
return result;
}
private List<LoadTimeLine> buildSecondLevel(Resource resource,
List<ResourceAllocation<?>> sortedByStartDate) {
List<LoadTimeLine> result = new ArrayList<LoadTimeLine>();
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
LoadTimeLine lineOthersOrders = buildTimeLinesForOtherOrders(
resource, byOrder);
if (lineOthersOrders != null) {
result.add(lineOthersOrders);
}
} else {
result.addAll(buildTimeLinesGroupForOrder(resource, byOrder));
}
return result;
}
private LoadTimeLine buildTimeLinesForOtherOrders(Resource resource,
Map<Order, List<ResourceAllocation<?>>> byOrder) {
List<ResourceAllocation<?>> resourceAllocations = getAllSortedValues(byOrder);
if (resourceAllocations.isEmpty()) {
return null;
}
LoadTimeLine group = new LoadTimeLine(buildTimeLine(
resource, "Others ordes", resourceAllocations),
buildTimeLinesGroupForOrder(resource, byOrder));
return group;
}
private List<LoadTimeLine> buildTimeLinesGroupForOrder(
Resource resource, Map<Order, List<ResourceAllocation<?>>> byOrder) {
List<LoadTimeLine> result = new ArrayList<LoadTimeLine>();
for (Order order : byOrder.keySet()) {
result.add(new LoadTimeLine(buildTimeLine(resource,
order
.getName(), byOrder.get(order)), buildTimeLinesForOrder(
resource, byOrder.get(order))));
}
return result;
}
private List<ResourceAllocation<?>> getAllSortedValues(
Map<Order, List<ResourceAllocation<?>>> byOrder) {
List<ResourceAllocation<?>> resourceAllocations = new ArrayList<ResourceAllocation<?>>();
for (List<ResourceAllocation<?>> listAllocations : byOrder.values()) {
resourceAllocations.addAll(listAllocations);
}
return ResourceAllocation.sortedByStartDate(resourceAllocations);
}
private void initializeIfNeeded(
Map<Order, List<ResourceAllocation<?>>> result, Order order) {
if (!result.containsKey(order)) {
result.put(order, new ArrayList<ResourceAllocation<?>>());
}
}
@Transactional(readOnly = true)
public Map<Order, List<ResourceAllocation<?>>> byOrder(
Collection<? extends ResourceAllocation<?>> allocations) {
Map<Order, List<ResourceAllocation<?>>> result = new HashMap<Order, List<ResourceAllocation<?>>>();
for (ResourceAllocation<?> resourceAllocation : allocations) {
if (resourceAllocation.getTask() != null) {
OrderElement orderElement = resourceAllocation.getTask()
.getOrderElement();
Order order = orderElementDAO
.loadOrderAvoidingProxyFor(orderElement);
initializeIfNeeded(result, order);
result.get(order).add(resourceAllocation);
}
}
return result;
}
private List<LoadTimeLine> buildTimeLinesForOrder(Resource resource,
List<ResourceAllocation<?>> sortedByStartDate) {
List<LoadTimeLine> result = new ArrayList<LoadTimeLine>();
result.addAll(buildTimeLinesForEachTask(resource,
onlySpecific(sortedByStartDate)));
result.addAll(buildTimeLinesForEachCriterion(resource,
@ -244,27 +331,49 @@ public class ResourceLoadModel implements IResourceLoadModel {
Resource resource, List<GenericResourceAllocation> sortdByStartDate) {
Map<Set<Criterion>, List<GenericResourceAllocation>> byCriterions = GenericResourceAllocation
.byCriterions(sortdByStartDate);
List<LoadTimeLine> result = new ArrayList<LoadTimeLine>();
for (Entry<Set<Criterion>, List<GenericResourceAllocation>> entry : byCriterions
.entrySet()) {
LoadTimeLine timeLine = buildTimeLine(entry.getKey(), resource,
entry.getValue());
if (!timeLine.isEmpty()) {
result.add(timeLine);
Map<Task, List<ResourceAllocation<?>>> byTask = ResourceAllocation
.byTask(entry.getValue());
for (Entry<Task, List<ResourceAllocation<?>>> entryTask : byTask.entrySet()) {
Task task = entryTask.getKey();
List<GenericResourceAllocation> resouceAllocations = getGenericResourceAllocation(entryTask
.getValue());
LoadTimeLine timeLine = buildTimeLine(entry.getKey(), task,
resource, resouceAllocations);
if (!timeLine.isEmpty()) {
result.add(timeLine);
}
}
}
return result;
}
private List<LoadTimeLine> buildTimeLinesForEachTask(Resource resource,
private List<GenericResourceAllocation> getGenericResourceAllocation(
List<ResourceAllocation<?>> list) {
List<GenericResourceAllocation> result = new ArrayList<GenericResourceAllocation>();
for (ResourceAllocation<?> resourceAllocation : list) {
if (resourceAllocation instanceof GenericResourceAllocation) {
result.add((GenericResourceAllocation) resourceAllocation);
}
}
return result;
}
private List<LoadTimeLine> buildTimeLinesForEachTask(
Resource resource,
List<SpecificResourceAllocation> sortedByStartDate) {
Map<Task, List<ResourceAllocation<?>>> byTask = ResourceAllocation
.byTask(sortedByStartDate);
List<LoadTimeLine> secondLevel = new ArrayList<LoadTimeLine>();
for (Entry<Task, List<ResourceAllocation<?>>> entry : byTask.entrySet()) {
Task task = entry.getKey();
LoadTimeLine timeLine = buildTimeLine(resource,
getTaskName(task),
LoadTimeLine timeLine = buildTimeLine(resource, task.getName(),
entry.getValue(), "specific");
if (!timeLine.isEmpty()) {
secondLevel.add(timeLine);
@ -274,22 +383,22 @@ public class ResourceLoadModel implements IResourceLoadModel {
return secondLevel;
}
private String getTaskName(Task task) {
TaskElement topMost = task.getTopMost();
String prefix = topMost != task ? (topMost.getName() + " :: ") : "";
return prefix + task.getName();
}
private LoadTimeLine buildTimeLine(Collection<Criterion> criterions,
Task task,
Resource resource,
List<GenericResourceAllocation> allocationsSortedByStartDate) {
LoadPeriodGeneratorFactory periodGeneratorFactory = LoadPeriodGenerator
.onResourceSatisfying(resource, criterions);
return new LoadTimeLine(getName(criterions), PeriodsBuilder.build(
periodGeneratorFactory, allocationsSortedByStartDate),
return new LoadTimeLine(getName(criterions, task), PeriodsBuilder
.build(periodGeneratorFactory, allocationsSortedByStartDate),
"generic");
}
public static String getName(Collection<? extends Criterion> criterions,Task task) {
String prefix = task.getName();
return (prefix + " :: " + getName(criterions));
}
public static String getName(Collection<? extends Criterion> criterions) {
if (criterions.isEmpty()) {
return _("[generic all workers]");
@ -299,7 +408,7 @@ public class ResourceLoadModel implements IResourceLoadModel {
for (Criterion criterion : criterions) {
names[i++] = criterion.getName();
}
return Arrays.toString(names);
return (Arrays.toString(names));
}
private LoadTimeLine buildTimeLine(Resource resource, String name,
@ -315,7 +424,7 @@ public class ResourceLoadModel implements IResourceLoadModel {
}
@Override
public List<LoadTimelinesGroup> getLoadTimeLines() {
public List<LoadTimeLine> getLoadTimeLines() {
return loadTimeLines;
}