result = new ArrayList
();
- 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());
}
diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/limitingresources/LimitingResourcesLeftPane.java b/ganttzk/src/main/java/org/zkoss/ganttz/limitingresources/LimitingResourcesLeftPane.java
index 343c0ce46..fc579410e 100644
--- a/ganttzk/src/main/java/org/zkoss/ganttz/limitingresources/LimitingResourcesLeftPane.java
+++ b/ganttzk/src/main/java/org/zkoss/ganttz/limitingresources/LimitingResourcesLeftPane.java
@@ -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 modelForTree;
+ private MutableTreeModel modelForTree;
private final LimitingResourcesList limitingResourcesList;
- public LimitingResourcesLeftPane(MutableTreeModel modelForTree,
+ public LimitingResourcesLeftPane(
+ MutableTreeModel 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 closed = calculatedClosedItems(item);
- expand(line, closed);
- } else {
- collapse(line);
- }
+// if (openEvent.isOpen()) {
+// List 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 closed) {
- limitingResourcesList.expand(line, closed);
+ private void expand(LoadTimeLine line, List closed) {
+ // unnecesary
+ // limitingResourcesList.expand(line, closed);
}
private List calculatedClosedItems(Treeitem item) {
diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/limitingresources/LimitingResourcesList.java b/ganttzk/src/main/java/org/zkoss/ganttz/limitingresources/LimitingResourcesList.java
index 7a3257ec1..7150213dc 100644
--- a/ganttzk/src/main/java/org/zkoss/ganttz/limitingresources/LimitingResourcesList.java
+++ b/ganttzk/src/main/java/org/zkoss/ganttz/limitingresources/LimitingResourcesList.java
@@ -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 fromTimeLineToComponent = new HashMap();
+ private Map fromTimeLineToComponent = new HashMap();
- private final MutableTreeModel timelinesTree;
+ private final MutableTreeModel timelinesTree;
public LimitingResourcesList(TimeTracker timeTracker,
- MutableTreeModel timelinesTree) {
+ MutableTreeModel timelinesTree) {
this.timelinesTree = timelinesTree;
zoomListener = adjustTimeTrackerSizeListener();
timeTracker.addZoomListener(zoomListener);
- LoadTimeLine current = timelinesTree.getRoot();
- List toInsert = new ArrayList();
+ LimitingResourceQueue current = timelinesTree.getRoot();
+ List toInsert = new ArrayList();
fill(timelinesTree, current, toInsert);
insertAsComponents(timeTracker, toInsert);
}
- private void fill(MutableTreeModel timelinesTree,
- LoadTimeLine current, List result) {
+ private void fill(MutableTreeModel timelinesTree,
+ LimitingResourceQueue current, List 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 children) {
- for (LoadTimeLine loadTimeLine : children) {
+ List 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 closed) {
+ public void expand(LimitingResourceQueue line,
+ List closed) {
LimitingResourcesComponent parentComponent = getComponentFor(line);
Component nextSibling = parentComponent.getNextSibling();
- List childrenToOpen = getChildrenReverseOrderFor(line);
+ List 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 getChildrenReverseOrderFor(LoadTimeLine line) {
- List childrenOf = line.getAllChildren();
+ private List getChildrenReverseOrderFor(
+ LimitingResourceQueue line) {
+ List childrenOf = line.getAllChildren();
Collections.reverse(childrenOf);
return childrenOf;
}
diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/limitingresources/LimitingResourcesPanel.java b/ganttzk/src/main/java/org/zkoss/ganttz/limitingresources/LimitingResourcesPanel.java
index cd9fab257..8aad067f9 100644
--- a/ganttzk/src/main/java/org/zkoss/ganttz/limitingresources/LimitingResourcesPanel.java
+++ b/ganttzk/src/main/java/org/zkoss/ganttz/limitingresources/LimitingResourcesPanel.java
@@ -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 groups;
+ private List groups;
- private MutableTreeModel treeModel;
+ private MutableTreeModel 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 groups,
+ public LimitingResourcesPanel(List groups,
TimeTracker timeTracker) {
init(groups, timeTracker);
}
- public void init(List groups, TimeTracker timeTracker) {
+ public void init(List groups, TimeTracker timeTracker) {
this.groups = groups;
this.timeTracker = timeTracker;
treeModel = createModelForTree();
@@ -190,23 +190,25 @@ public class LimitingResourcesPanel extends HtmlMacroComponent {
.retrieve();
}
- private MutableTreeModel createModelForTree() {
- MutableTreeModel result = MutableTreeModel
- .create(LoadTimeLine.class);
- for (LoadTimeLine loadTimeLine : this.groups) {
- result.addToRoot(loadTimeLine);
- result = addNodes(result, loadTimeLine);
+ private MutableTreeModel createModelForTree() {
+ MutableTreeModel result = MutableTreeModel
+ .create(LimitingResourceQueue.class);
+ for (LimitingResourceQueue LimitingResourceQueue : this.groups) {
+ result.addToRoot(LimitingResourceQueue);
+ result = addNodes(result, LimitingResourceQueue);
}
return result;
}
- private MutableTreeModel addNodes(
- MutableTreeModel tree, LoadTimeLine parent) {
+ private MutableTreeModel addNodes(
+ MutableTreeModel 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;
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/ILimitingResourceQueueModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/ILimitingResourceQueueModel.java
index 2d60d856f..ba550463a 100644
--- a/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/ILimitingResourceQueueModel.java
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/ILimitingResourceQueueModel.java
@@ -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 getLoadTimeLines();
+ List getLimitingResourceQueues();
Interval getViewInterval();
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourceQueueModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourceQueueModel.java
index 4936c6154..f8ab2b4d7 100644
--- a/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourceQueueModel.java
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourceQueueModel.java
@@ -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 loadTimeLines;
+ private List 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 calculateLoadTimeLines() {
- List result = new ArrayList();
- result.addAll(groupsFor(genericAllocationsByCriterion()));
+ private List calculateLimitingResourceQueues() {
+ List result = new ArrayList();
+ result.addAll(groupsFor(resourcesToShow()));
return result;
}
@@ -226,37 +230,72 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
return new TimeLineRole(entity);
}
- /**
- * @param genericAllocationsByCriterion
- * @return
- */
- private List groupsFor(
- Map> genericAllocationsByCriterion) {
- List result = new ArrayList();
- List criterions = Criterion
- .sortByName(genericAllocationsByCriterion.keySet());
- for (Criterion criterion : criterions) {
- List allocations = ResourceAllocation
- .sortedByStartDate(genericAllocationsByCriterion
- .get(criterion));
- TimeLineRole role = getCurrentTimeLineRole(criterion);
+ private List groupsFor(List allResources) {
+ List result = new ArrayList();
+ for (Resource resource : allResources) {
+ LimitingResourceQueue group = buildGroup(resource);
+ if (!group.isEmpty()) {
+ result.add(group);
+ }
}
return result;
}
- private List buildTimeLinesForOrder(Criterion criterion,
- List> allocations) {
- List result = new ArrayList();
- result.addAll(buildTimeLinesForEachTask(criterion, allocations));
+ private LimitingResourceQueue buildGroup(Resource resource) {
+ List> sortedByStartDate = ResourceAllocation
+ .sortedByStartDate(resourceAllocationDAO
+ .findAllocationsRelatedTo(resource));
+ TimeLineRole role = getCurrentTimeLineRole(resource);
+ LimitingResourceQueue result = new LimitingResourceQueue(buildTimeLine(
+ resource, resource.getShortDescription(), sortedByStartDate,
+ "resource", role),
+ buildSecondLevel(resource, sortedByStartDate));
return result;
}
- private List buildTimeLinesForEachTask(Criterion criterion,
+ private LimitingResourceQueue buildTimeLine(Resource resource, String name,
+ List extends ResourceAllocation>> sortedByStartDate,
+ String type, TimeLineRole role) {
+ return new LimitingResourceQueue(name, PeriodsBuilder.build(
+ QueueTaskGenerator.onResource(resource), sortedByStartDate),
+ type, role);
+ }
+
+ private List buildSecondLevel(Resource resource,
+ List> sortedByStartDate) {
+ List result = new ArrayList();
+ Map>> 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>> byOrder) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ private List buildTimeLinesForEachTask(
+ Criterion criterion,
List> allocations) {
Map>> byTask = ResourceAllocation
.byTask(allocations);
- List secondLevel = new ArrayList();
+ List secondLevel = new ArrayList();
for (Entry>> entry : byTask.entrySet()) {
Task task = entry.getKey();
Set criterions = task.getCriterions();
@@ -271,23 +310,6 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
return secondLevel;
}
- private List buildTimeLinesForEachResource(
- Criterion criterion, List allocations,
- TimeLineRole role) {
- Map> byResource = GenericResourceAllocation
- .byResource(allocations);
-
- List secondLevel = new ArrayList();
- for (Entry> entry : byResource
- .entrySet()) {
- Resource resource = entry.getKey();
- List resourceAllocations = entry
- .getValue();
- String descriptionTimeLine = getDescriptionResourceWithCriterions(resource);
- }
- return secondLevel;
- }
-
private String getDescriptionResourceWithCriterions(Resource resource) {
Set criterionSatisfactions = resource
.getCriterionSatisfactions();
@@ -341,13 +363,15 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
return result;
}
- private List buildTimeLinesForOrder(Resource resource,
+ private List buildTimeLinesForOrder(
+ Resource resource,
List> sortedByStartDate) {
- List result = new ArrayList();
- result.addAll(buildTimeLinesForEachTask(resource,
- onlySpecific(sortedByStartDate)));
- result.addAll(buildTimeLinesForEachCriterion(resource,
- onlyGeneric(sortedByStartDate)));
+ List result = new ArrayList();
+ // 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 buildTimeLinesForEachCriterion(
+ private List buildTimeLinesForEachCriterion(
Resource resource, List sortdByStartDate) {
Map, List> byCriterions = GenericResourceAllocation
.byCriterions(sortdByStartDate);
- List result = new ArrayList();
+ List result = new ArrayList();
for (Entry, List> entry : byCriterions
.entrySet()) {
@@ -388,7 +412,8 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
return result;
}
- private List buildTimeLinesForEachTask(Resource resource,
+ private List buildTimeLinesForEachTask(
+ Resource resource,
List sortedByStartDate) {
List> listOnlySpecific = new ArrayList>(
@@ -396,7 +421,7 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
Map>> byTask = ResourceAllocation
.byTask(listOnlySpecific);
- List secondLevel = new ArrayList();
+ List secondLevel = new ArrayList();
for (Entry>> entry : byTask.entrySet()) {
Task task = entry.getKey();
TimeLineRole role = getCurrentTimeLineRole(task);
@@ -425,8 +450,8 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
@Override
- public List getLoadTimeLines() {
- return loadTimeLines;
+ public List 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 loadPeriodsGenerators = new LinkedList();
+
+ private final QueueTaskGeneratorFactory factory;
+
+ private PeriodsBuilder(QueueTaskGeneratorFactory factory,
+ List extends ResourceAllocation>> sortedByStartDate) {
+ this.factory = factory;
+ this.sortedByStartDate = sortedByStartDate;
+ }
+
+ public static List build(QueueTaskGeneratorFactory factory,
+ List extends ResourceAllocation>> sortedByStartDate) {
+ return new PeriodsBuilder(factory, sortedByStartDate).buildPeriods();
+ }
+
+ private List buildPeriods() {
+ for (ResourceAllocation> resourceAllocation : sortedByStartDate) {
+ loadPeriodsGenerators.add(factory.create(resourceAllocation));
+ }
+ joinPeriodGenerators();
+ return toGenerators(loadPeriodsGenerators);
+ }
+
+ private List toGenerators(List generators) {
+ List result = new ArrayList();
+ for (QueueTaskGenerator queueTaskGenerator : generators) {
+ result.add(queueTaskGenerator.build());
+ }
+ return result;
+ }
+
+ private void joinPeriodGenerators() {
+ ListIterator 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 generated = current.join(next);
+ final QueueTaskGenerator positionToComeBack = generated.get(0);
+ final List remaining = loadPeriodsGenerators
+ .subList(iterator.nextIndex(), loadPeriodsGenerators
+ .size());
+ List generatorsSortedByStartDate = mergeListsKeepingByStartSortOrder(
+ generated, remaining);
+ final int takenFromRemaining = generatorsSortedByStartDate
+ .size()
+ - generated.size();
+ removeNextElements(iterator, takenFromRemaining);
+ addAtCurrentPosition(iterator, generatorsSortedByStartDate);
+ rewind(iterator, positionToComeBack);
+ }
+ }
+ }
+
+ private QueueTaskGenerator findNextOneOverlapping(
+ ListIterator 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 iterator,
+ List sortedByStartDate) {
+ for (QueueTaskGenerator l : sortedByStartDate) {
+ iterator.add(l);
+ }
+ }
+
+ private void removeNextElements(ListIterator iterator,
+ final int elementsNumber) {
+ for (int i = 0; i < elementsNumber; i++) {
+ iterator.next();
+ iterator.remove();
+ }
+ }
+
+ private void rewind(ListIterator iterator,
+ QueueTaskGenerator nextOne) {
+ while (peekNext(iterator) != nextOne) {
+ iterator.previous();
+ }
+ }
+
+ private List mergeListsKeepingByStartSortOrder(
+ List joined, List remaining) {
+ List result = new ArrayList();
+ ListIterator joinedIterator = joined.listIterator();
+ ListIterator 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 iterator) {
+ if (!iterator.hasNext()) {
+ return null;
+ }
+ QueueTaskGenerator result = iterator.next();
+ iterator.previous();
+ return result;
+ }
+
}
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourcesController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourcesController.java
index e81303cb1..925738988 100644
--- a/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourcesController.java
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourcesController.java
@@ -139,7 +139,7 @@ public class LimitingResourcesController implements Composer {
private LimitingResourcesPanel buildLimitingResourcesPanel() {
return new LimitingResourcesPanel(limitingResourceQueueModel
- .getLoadTimeLines(),
+ .getLimitingResourceQueues(),
timeTracker);
}
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/QueueTaskGenerator.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/QueueTaskGenerator.java
new file mode 100644
index 000000000..7247617c1
--- /dev/null
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/QueueTaskGenerator.java
@@ -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 .
+ */
+
+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 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. emptyList());
+ }
+
+ public OnResourceFactory(Resource resource,
+ Collection 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 findResources(final Criterion criterion,
+ final IResourceDAO resourcesDAO) {
+ return resourcesDAO
+ .findSatisfyingCriterionsAtSomePoint(Collections
+ .singletonList(criterion));
+ }
+ };
+ }
+
+ protected final LocalDate start;
+ protected final LocalDate end;
+
+ private List> allocationsOnInterval = new ArrayList>();
+
+ protected QueueTaskGenerator(LocalDate start,
+ LocalDate end, List> allocationsOnInterval) {
+ Validate.notNull(start);
+ Validate.notNull(end);
+ Validate.notNull(allocationsOnInterval);
+ this.start = start;
+ this.end = end;
+ this.allocationsOnInterval = ResourceAllocation
+ .getSatisfied(allocationsOnInterval);
+ }
+
+ public List 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> getAllocationsOnInterval() {
+ return allocationsOnInterval;
+ }
+
+ private List stripEmpty(
+ QueueTaskGenerator... generators) {
+ List result = new ArrayList();
+ 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> 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> plusAllocations(
+ QueueTaskGenerator other) {
+ List> result = new ArrayList>();
+ 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> 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.> asList(initial));
+ this.resource = resource;
+ this.criterion = criterion;
+ }
+
+ @Override
+ protected QueueTaskGenerator create(LocalDate start, LocalDate end,
+ List> 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 resourcesSatisfyingCriterionAtSomePoint;
+
+ public QueueTaskGeneratorOnCriterion(Criterion criterion,
+ ResourceAllocation> allocation,
+ List resourcesSatisfyingCriterionAtSomePoint) {
+ this(criterion, allocation.getStartDate(), allocation.getEndDate(),
+ Arrays.> asList(allocation),
+ resourcesSatisfyingCriterionAtSomePoint);
+ }
+
+ public QueueTaskGeneratorOnCriterion(Criterion criterion,
+ LocalDate startDate, LocalDate endDate,
+ List> allocations,
+ List resourcesSatisfyingCriterionAtSomePoint) {
+ super(startDate, endDate, allocations);
+ this.criterion = criterion;
+ this.resourcesSatisfyingCriterionAtSomePoint = resourcesSatisfyingCriterionAtSomePoint;
+ }
+
+ @Override
+ protected QueueTaskGenerator create(LocalDate start, LocalDate end,
+ List> allocationsOnInterval) {
+ QueueTaskGeneratorOnCriterion result = new QueueTaskGeneratorOnCriterion(
+ criterion, start, end, allocationsOnInterval,
+ resourcesSatisfyingCriterionAtSomePoint);
+ result.specificByResourceCached = specificByResourceCached;
+ return result;
+ }
+
+ private List 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> specificByResourceCached = new HashMap>();
+
+ private List getSpecificOrderedAssignmentsFor(
+ Resource resource) {
+ if (!specificByResourceCached.containsKey(resource)) {
+ specificByResourceCached.put(resource, DayAssignment
+ .specific(DayAssignment.orderedByDay(resource
+ .getAssignments())));
+ }
+ return specificByResourceCached.get(resource);
+ }
+
+ private int sum(List specific) {
+ int result = 0;
+ for (SpecificDayAssignment s : specific) {
+ result += s.getHours();
+ }
+ return result;
+ }
+
+}