diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java b/ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java index 09c0e04c4..7900a18d1 100644 --- a/ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java +++ b/ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java @@ -132,6 +132,10 @@ public class ResourcesLoadPanel extends HtmlMacroComponent { leftPane = new ResourceLoadLeftPane(treeModel, resourceLoadList); } + public TimeTracker getTimeTracker() { + return timeTracker; + } + public ListModel getFilters() { String[] filters = new String[] { FILTER_RESOURCES, FILTER_CRITERIA }; return new SimpleListModel(filters); diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/util/Emitter.java b/ganttzk/src/main/java/org/zkoss/ganttz/util/Emitter.java new file mode 100644 index 000000000..f1b0ed2dc --- /dev/null +++ b/ganttzk/src/main/java/org/zkoss/ganttz/util/Emitter.java @@ -0,0 +1,70 @@ +/* + * This file is part of NavalPlan + * + * Copyright (C) 2011 Igalia, S.L. + * + * 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.zkoss.ganttz.util; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Óscar González Fernández + */ +public class Emitter { + + public interface IEmissionListener { + + public void newEmission(T value); + } + + private T lastValue; + + private List> listeners = new ArrayList>(); + + public static Emitter withInitial(T initialValue) { + return new Emitter(initialValue); + } + + private Emitter(T initialValue) { + this.lastValue = initialValue; + } + + public T getLastValue() { + return lastValue; + } + + public void emit(T value) { + this.lastValue = value; + fireListeners(value); + } + + private void fireListeners(T value) { + for (IEmissionListener each : listeners) { + each.newEmission(value); + } + } + + public void addListener(IEmissionListener listener) { + this.listeners.add(listener); + } + + public void removeListener(IEmissionListener listener) { + this.listeners.remove(listener); + } +} diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/SpecificResourceAllocation.java b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/SpecificResourceAllocation.java index 6af078558..241a2605f 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/SpecificResourceAllocation.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/SpecificResourceAllocation.java @@ -431,4 +431,5 @@ public class SpecificResourceAllocation extends return !intervalsRelatedWith.isEmpty(); } + } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/company/CompanyPlanningModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/company/CompanyPlanningModel.java index 7219a4405..64d5809f4 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/company/CompanyPlanningModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/company/CompanyPlanningModel.java @@ -98,6 +98,8 @@ import org.zkoss.ganttz.extensions.IContext; import org.zkoss.ganttz.timetracker.TimeTracker; import org.zkoss.ganttz.timetracker.zoom.IZoomLevelChangedListener; import org.zkoss.ganttz.timetracker.zoom.ZoomLevel; +import org.zkoss.ganttz.util.Emitter; +import org.zkoss.ganttz.util.Emitter.IEmissionListener; import org.zkoss.ganttz.util.Interval; import org.zkoss.zk.au.out.AuInsertAfter; import org.zkoss.zk.ui.Executions; @@ -427,11 +429,30 @@ public class CompanyPlanningModel implements ICompanyPlanningModel { public static Tabpanel appendLoadChartAndLegend(Tabpanel loadChartPannel, Timeplot loadChart) { + return appendLoadChartAndLegend(loadChartPannel, + Emitter.withInitial(loadChart)); + } + + public static Tabpanel appendLoadChartAndLegend(Tabpanel loadChartPannel, + Emitter loadChartEmitter) { Hbox hbox = new Hbox(); hbox.appendChild(getLoadChartLegend()); - Div div = new Div(); - div.appendChild(loadChart); + final Div div = new Div(); + Timeplot timePlot = loadChartEmitter.getLastValue(); + if (timePlot != null) { + div.appendChild(timePlot); + } + loadChartEmitter.addListener(new IEmissionListener() { + + @Override + public void newEmission(Timeplot timePlot) { + div.getChildren().clear(); + if (timePlot != null) { + div.appendChild(timePlot); + } + } + }); div.setSclass("plannergraph"); hbox.appendChild(div); diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/resourceload/IResourceLoadModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/resourceload/IResourceLoadModel.java index 785113cab..df2878ae3 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/resourceload/IResourceLoadModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/resourceload/IResourceLoadModel.java @@ -21,57 +21,18 @@ package org.navalplanner.web.resourceload; -import java.util.List; - -import org.joda.time.LocalDate; import org.navalplanner.business.orders.entities.Order; -import org.navalplanner.business.planner.entities.DayAssignment; import org.navalplanner.business.planner.entities.TaskElement; -import org.navalplanner.business.resources.entities.Criterion; -import org.navalplanner.business.resources.entities.Resource; -import org.navalplanner.web.planner.order.PlanningStateCreator.PlanningState; public interface IResourceLoadModel { - ResourceLoadDisplayData calculateDataToDisplay(boolean filterByResources); - - ResourceLoadDisplayData calculateDataToDisplay(PlanningState filterBy, - boolean filterByResources); + ResourceLoadDisplayData calculateDataToDisplay( + ResourceLoadParameters parameters); Order getOrderByTask(TaskElement task); boolean userCanRead(Order order, String loginName); - void setResourcesToShow(List resourcesList); - - void clearResourcesToShow(); - - void setCriteriaToShow(List criteriaList); - - void clearCriteriaToShow(); - - void setInitDateFilter(LocalDate value); - - void setEndDateFilter(LocalDate value); - - LocalDate getInitDateFilter(); - - LocalDate getEndDateFilter(); - - List getDayAssignments(); - - List getResources(); - boolean isExpandResourceLoadViewCharts(); - List getAllResourcesList(); - - List getAllCriteriaList(); - - int getPageSize(); - - int getPageFilterPosition(); - - void setPageFilterPosition(int pageFilterPosition); - } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/resourceload/ResourceLoadController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/resourceload/ResourceLoadController.java index 0ee98c18d..c94df033c 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/resourceload/ResourceLoadController.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/resourceload/ResourceLoadController.java @@ -54,6 +54,7 @@ import org.navalplanner.web.planner.order.BankHolidaysMarker; import org.navalplanner.web.planner.order.IOrderPlanningGate; import org.navalplanner.web.planner.order.PlanningStateCreator; import org.navalplanner.web.planner.order.PlanningStateCreator.PlanningState; +import org.navalplanner.web.resourceload.ResourceLoadParameters.Paginator; import org.navalplanner.web.security.SecurityUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanDefinition; @@ -73,6 +74,7 @@ import org.zkoss.ganttz.timetracker.TimeTracker; import org.zkoss.ganttz.timetracker.zoom.IZoomLevelChangedListener; import org.zkoss.ganttz.timetracker.zoom.SeveralModificators; import org.zkoss.ganttz.timetracker.zoom.ZoomLevel; +import org.zkoss.ganttz.util.Emitter; import org.zkoss.ganttz.util.Interval; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; @@ -119,18 +121,8 @@ public class ResourceLoadController implements Composer { private Reloader reloader = new Reloader(); - private TimeTracker timeTracker; - private IOrderPlanningGate planningControllerEntryPoints; - private ZoomLevel zoomLevel; - - private List keepAliveZoomListeners = new ArrayList(); - - private List keepAliveChartVisibilityListeners = new ArrayList(); - - private Chart loadChart; - public ResourceLoadController() { } @@ -165,6 +157,8 @@ public class ResourceLoadController implements Composer { private ListenerTracker listeners = new ListenerTracker(); + private TimeTracker timeTracker; + public Reloader() { } @@ -177,16 +171,6 @@ public class ResourceLoadController implements Composer { return visualizationModifiers = buildVisualizationModifiers(); } - private FilterTypeChanger getTypeChanger() { - for (VisualizationModifier each : getVisualizationModifiers()) { - if (each instanceof VisualizationModifier) { - return (FilterTypeChanger) each; - } - } - throw new RuntimeException(FilterTypeChanger.class.getSimpleName() - + " should always be among the visualization modifiers"); - } - private List listenersToAdd = null; private List getListenersToAdd() { @@ -225,14 +209,15 @@ public class ResourceLoadController implements Composer { for (VisualizationModifier each : getVisualizationModifiers()) { each.checkDependencies(); } + ResourceLoadParameters parameters = new ResourceLoadParameters( + filterBy); for (VisualizationModifier each : getVisualizationModifiers()) { - each.applyToModel(resourceLoadModel); + each.applyToParameters(parameters); } - ResourceLoadDisplayData dataToShow = calculateDataToDisplay(getTypeChanger() - .isFilterByResources()); - timeTracker = buildTimeTracker(dataToShow); + ResourceLoadDisplayData dataToShow = resourceLoadModel.calculateDataToDisplay(parameters); + timeTracker = buildTimeTracker(dataToShow); if (resourcesLoadPanel == null) { resourcesLoadPanel = buildPanel(dataToShow); listeners.addListeners(resourcesLoadPanel, getListenersToAdd()); @@ -246,32 +231,29 @@ public class ResourceLoadController implements Composer { timeTracker); } - resourcesLoadPanel.setLoadChart(buildChart(resourcesLoadPanel)); resourcesLoadPanel.afterCompose(); addCommands(resourcesLoadPanel); for (VisualizationModifier each : getVisualizationModifiers()) { - each.updateUI(resourcesLoadPanel, resourceLoadModel); + each.updateUI(resourcesLoadPanel, dataToShow); } } + private TimeTracker buildTimeTracker(ResourceLoadDisplayData dataToShow) { + ZoomLevel zoomLevel = dataToShow.getInitialZoomLevel(); + TimeTracker result = new TimeTracker(dataToShow.getViewInterval(), + zoomLevel, SeveralModificators.create(), + SeveralModificators.create(createBankHolidaysMarker()), + parent); + return result; + } + private ResourcesLoadPanel buildPanel(ResourceLoadDisplayData dataToShow) { return new ResourcesLoadPanel(dataToShow.getLoadTimeLines(), timeTracker, parent, resourceLoadModel.isExpandResourceLoadViewCharts(), PaginationType.EXTERNAL_PAGINATION); } - - private ResourceLoadDisplayData calculateDataToDisplay( - boolean filterByResources) { - if (isGlobal()) { - return resourceLoadModel - .calculateDataToDisplay(filterByResources); - } else { - return resourceLoadModel.calculateDataToDisplay(filterBy, - filterByResources); - } - } } private List buildVisualizationModifiers() { @@ -285,6 +267,7 @@ public class ResourceLoadController implements Composer { result.add(bandbox); result.add(new ByNamePaginator(onChange, filterBy, filterTypeChanger, bandbox)); + result.add(new LoadChart(onChange, filterBy)); return result; } @@ -370,10 +353,10 @@ public class ResourceLoadController implements Composer { } - void applyToModel(IResourceLoadModel model) { + void applyToParameters(ResourceLoadParameters parameters) { } - void updateUI(ResourcesLoadPanel panel, IResourceLoadModel model) { + void updateUI(ResourcesLoadPanel panel, ResourceLoadDisplayData generatedData) { } } @@ -390,6 +373,11 @@ public class ResourceLoadController implements Composer { return filterByResources; } + @Override + void applyToParameters(ResourceLoadParameters parameters) { + parameters.setFilterByResources(filterByResources); + } + @Override public Object addAndReturnListener(ResourcesLoadPanel panel) { IFilterChangedListener listener = new IFilterChangedListener() { @@ -468,22 +456,11 @@ public class ResourceLoadController implements Composer { } @Override - void applyToModel(IResourceLoadModel model) { - model.setInitDateFilter(startDateValue); - model.setEndDateFilter(endDateValue); + void applyToParameters(ResourceLoadParameters parameters) { + parameters.setInitDateFilter(startDateValue); + parameters.setEndDateFilter(endDateValue); } - @Override - void updateUI(ResourcesLoadPanel panel, IResourceLoadModel model) { - if (isAppliedToOrder()) { - return; - } - startDateValue = model.getInitDateFilter(); - startBox.setValue(asDate(startDateValue)); - - endDateValue = model.getEndDateFilter(); - endBox.setValue(asDate(endDateValue)); - } } private static abstract class DependingOnFiltering extends @@ -579,14 +556,16 @@ public class ResourceLoadController implements Composer { } @Override - void applyToModel(IResourceLoadModel model) { + void applyToParameters(ResourceLoadParameters parameters) { if (!hasEntitiesSelected()) { - model.clearResourcesToShow(); - model.clearCriteriaToShow(); + parameters.clearResourcesToShow(); + parameters.clearCriteriaToShow(); } else if (isFilteringByResource()) { - model.setResourcesToShow(as(Resource.class, entitiesSelected)); + parameters.setResourcesToShow(as(Resource.class, + entitiesSelected)); } else { - model.setCriteriaToShow(as(Criterion.class, entitiesSelected)); + parameters.setCriteriaToShow(as(Criterion.class, + entitiesSelected)); } } @@ -659,24 +638,23 @@ public class ResourceLoadController implements Composer { } @Override - void applyToModel(IResourceLoadModel model) { - model.setPageFilterPosition(currentPosition); + void applyToParameters(ResourceLoadParameters parameters) { + parameters.setPageFilterPosition(currentPosition); } @Override - void updateUI(ResourcesLoadPanel panel, IResourceLoadModel model) { + void updateUI(ResourcesLoadPanel panel, ResourceLoadDisplayData generatedData) { panel.setInternalPaginationDisabled(bandbox.hasEntitiesSelected()); - - List newAllEntities = getAllEntities(model); - if (this.currentPosition != model.getPageFilterPosition()) { - this.currentPosition = model.getPageFilterPosition(); - } + Paginator paginator = generatedData + .getPaginator(); + List newAllEntities = paginator.getAll(); if (this.allEntitiesShown == null || !equivalent(this.allEntitiesShown, newAllEntities)) { this.currentPosition = initialPage(); this.allEntitiesShown = newAllEntities; updatePages(panel.getPaginationFilterCombobox(), - pagesByName(this.allEntitiesShown, model.getPageSize())); + pagesByName(this.allEntitiesShown, + paginator.getPageSize())); } } @@ -725,15 +703,6 @@ public class ResourceLoadController implements Composer { } } - private List getAllEntities( - IResourceLoadModel model) { - if (isFilteringByResource()) { - return model.getAllResourcesList(); - } else { - return model.getAllCriteriaList(); - } - } - private List pagesByName(List list, int pageSize) { if (list.isEmpty()) { return new ArrayList(); @@ -799,6 +768,146 @@ public class ResourceLoadController implements Composer { return result; } + class LoadChart extends VisualizationModifier implements IListenerAdder { + + private Emitter emitter = Emitter.withInitial(null); + + private volatile Chart loadChart; + + private IZoomLevelChangedListener zoomLevelListener; + + public LoadChart(Runnable onChange, PlanningState filterBy) { + super(onChange, filterBy); + } + + void setup(ResourcesLoadPanel panel) { + panel.setLoadChart(buildChart(panel, emitter)); + } + + public Object addAndReturnListener(ResourcesLoadPanel panel) { + IChartVisibilityChangedListener visibilityChangedListener = fillOnChartVisibilityChange(); + panel.addChartVisibilityListener(visibilityChangedListener); + return visibilityChangedListener; + } + + private IChartVisibilityChangedListener fillOnChartVisibilityChange() { + IChartVisibilityChangedListener result = new IChartVisibilityChangedListener() { + + @Override + public void chartVisibilityChanged(final boolean visible) { + if (visible && loadChart != null) { + loadChart.fillChart(); + } + } + }; + return result; + } + + private Tabbox buildChart(ResourcesLoadPanel resourcesLoadPanel, + Emitter timePlot) { + Tabbox chartComponent = new Tabbox(); + chartComponent.setOrient("vertical"); + chartComponent.setHeight("200px"); + + Tabs chartTabs = new Tabs(); + chartTabs.appendChild(new Tab(_("Load"))); + chartComponent.appendChild(chartTabs); + chartTabs.setWidth("124px"); + + Tabpanels chartTabpanels = new Tabpanels(); + Tabpanel loadChartPannel = new Tabpanel(); + // avoid adding Timeplot since it has some pending issues + CompanyPlanningModel.appendLoadChartAndLegend(loadChartPannel, + timePlot); + chartTabpanels.appendChild(loadChartPannel); + chartComponent.appendChild(chartTabpanels); + return chartComponent; + } + + @Override + void updateUI(ResourcesLoadPanel panel, + ResourceLoadDisplayData generatedData) { + TimeTracker timeTracker = panel.getTimeTracker(); + zoomLevelListener = fillOnZoomChange(panel); + timeTracker.addZoomListener(zoomLevelListener); + + Timeplot newLoadChart = buildLoadChart(panel, generatedData, + timeTracker); + emitter.emit(newLoadChart); + } + + private Timeplot buildLoadChart(ResourcesLoadPanel resourcesLoadPanel, + ResourceLoadDisplayData generatedData, TimeTracker timeTracker) { + Timeplot chartLoadTimeplot = createEmptyTimeplot(); + + loadChart = new Chart(chartLoadTimeplot, + new ResourceLoadChartFiller(generatedData), timeTracker); + loadChart.setZoomLevel(timeTracker.getDetailLevel()); + if (resourcesLoadPanel.isVisibleChart()) { + loadChart.fillChart(); + } + return chartLoadTimeplot; + } + + private IZoomLevelChangedListener fillOnZoomChange( + final ResourcesLoadPanel resourcesLoadPanel) { + + IZoomLevelChangedListener zoomListener = new IZoomLevelChangedListener() { + + @Override + public void zoomLevelChanged(ZoomLevel detailLevel) { + if (loadChart == null) { + return; + } + loadChart.setZoomLevel(detailLevel); + + if (resourcesLoadPanel.isVisibleChart()) { + loadChart.fillChart(); + } + adjustZoomPositionScroll(resourcesLoadPanel); + } + }; + + return zoomListener; + } + } + + private void adjustZoomPositionScroll(ResourcesLoadPanel resourcesLoadPanel) { + resourcesLoadPanel.getTimeTrackerComponent().movePositionScroll(); + } + + private Timeplot createEmptyTimeplot() { + Timeplot timeplot = new Timeplot(); + timeplot.appendChild(new Plotinfo()); + return timeplot; + } + + private class ResourceLoadChartFiller extends StandardLoadChartFiller { + + private final ResourceLoadDisplayData generatedData; + + public ResourceLoadChartFiller(ResourceLoadDisplayData generatedData) { + this.generatedData = generatedData; + } + + @Override + protected String getOptionalJavascriptCall() { + return null; + } + + @Override + protected ILoadChartData getDataOn(Interval interval) { + List assignments = generatedData + .getDayAssignmentsConsidered(); + List resources = generatedData.getResourcesConsidered(); + ResourceLoadChartData data = new ResourceLoadChartData(assignments, + resources); + return data.on(getStart(generatedData.getFilterStart(), interval), + getEnd(generatedData.getFilterEnd(), interval)); + } + + } + private static class ListenerTracker { private final List trackedListeners = new ArrayList(); @@ -816,24 +925,12 @@ public class ResourceLoadController implements Composer { .size()])); } - private TimeTracker buildTimeTracker(ResourceLoadDisplayData dataToShow) { - zoomLevel = (timeTracker == null) ? dataToShow.getInitialZoomLevel() - : timeTracker.getDetailLevel(); - return new TimeTracker(dataToShow.getViewInterval(), zoomLevel, - SeveralModificators.create(), - SeveralModificators.create(createBankHolidaysMarker()), parent); - } - private BankHolidaysMarker createBankHolidaysMarker() { BaseCalendar defaultCalendar = configurationDAO.getConfiguration() .getDefaultCalendar(); return BankHolidaysMarker.create(defaultCalendar); } - private boolean isGlobal() { - return filterBy == null; - } - public void filterBy(Order order) { this.filterBy = order == null ? null : planningStateCreator .retrieveOrCreate(parent.getDesktop(), order); @@ -848,111 +945,4 @@ public class ResourceLoadController implements Composer { return this.planningControllerEntryPoints; } - private org.zkoss.zk.ui.Component buildChart( - ResourcesLoadPanel resourcesLoadPanel) { - Tabbox chartComponent = new Tabbox(); - chartComponent.setOrient("vertical"); - chartComponent.setHeight("200px"); - - Tabs chartTabs = new Tabs(); - chartTabs.appendChild(new Tab(_("Load"))); - chartComponent.appendChild(chartTabs); - chartTabs.setWidth("124px"); - - Tabpanels chartTabpanels = new Tabpanels(); - Tabpanel loadChartPannel = new Tabpanel(); - // avoid adding Timeplot since it has some pending issues - CompanyPlanningModel.appendLoadChartAndLegend(loadChartPannel, - buildLoadChart(resourcesLoadPanel)); - chartTabpanels.appendChild(loadChartPannel); - chartComponent.appendChild(chartTabpanels); - - return chartComponent; - } - - private Timeplot buildLoadChart(ResourcesLoadPanel resourcesLoadPanel) { - Timeplot chartLoadTimeplot = createEmptyTimeplot(); - - loadChart = new Chart(chartLoadTimeplot, - new ResourceLoadChartFiller(), timeTracker); - loadChart.setZoomLevel(zoomLevel); - if (resourcesLoadPanel.isVisibleChart()) { - loadChart.fillChart(); - } - timeTracker.addZoomListener(fillOnZoomChange(resourcesLoadPanel, - loadChart)); - resourcesLoadPanel - .addChartVisibilityListener(fillOnChartVisibilityChange(loadChart)); - - return chartLoadTimeplot; - } - - private IZoomLevelChangedListener fillOnZoomChange( - final ResourcesLoadPanel resourcesLoadPanel, final Chart loadChart) { - - IZoomLevelChangedListener zoomListener = new IZoomLevelChangedListener() { - - @Override - public void zoomLevelChanged(ZoomLevel detailLevel) { - loadChart.setZoomLevel(detailLevel); - - if (resourcesLoadPanel.isVisibleChart()) { - loadChart.fillChart(); - } - adjustZoomPositionScroll(resourcesLoadPanel); - } - }; - - keepAliveZoomListeners.add(zoomListener); - - return zoomListener; - } - - private void adjustZoomPositionScroll(ResourcesLoadPanel resourcesLoadPanel) { - resourcesLoadPanel.getTimeTrackerComponent().movePositionScroll(); - } - - private IChartVisibilityChangedListener fillOnChartVisibilityChange( - final Chart loadChart) { - IChartVisibilityChangedListener chartVisibilityChangedListener = new IChartVisibilityChangedListener() { - - @Override - public void chartVisibilityChanged(final boolean visible) { - if (visible) { - loadChart.fillChart(); - } - } - }; - - keepAliveChartVisibilityListeners.add(chartVisibilityChangedListener); - return chartVisibilityChangedListener; - } - - private Timeplot createEmptyTimeplot() { - Timeplot timeplot = new Timeplot(); - timeplot.appendChild(new Plotinfo()); - return timeplot; - } - - private class ResourceLoadChartFiller extends StandardLoadChartFiller { - - @Override - protected String getOptionalJavascriptCall() { - return null; - } - - @Override - protected ILoadChartData getDataOn(Interval interval) { - List dayAssignments = resourceLoadModel - .getDayAssignments(); - List resources = resourceLoadModel.getResources(); - ResourceLoadChartData data = new ResourceLoadChartData( - dayAssignments, resources); - return data.on( - getStart(resourceLoadModel.getInitDateFilter(), interval), - getEnd(resourceLoadModel.getEndDateFilter(), interval)); - } - - } - } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/resourceload/ResourceLoadDisplayData.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/resourceload/ResourceLoadDisplayData.java index 5aa652d43..ab1535f8e 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/resourceload/ResourceLoadDisplayData.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/resourceload/ResourceLoadDisplayData.java @@ -3,21 +3,82 @@ package org.navalplanner.web.resourceload; import java.util.Calendar; import java.util.Date; import java.util.List; +import java.util.concurrent.Callable; +import org.apache.commons.lang.Validate; import org.joda.time.LocalDate; +import org.navalplanner.business.common.BaseEntity; +import org.navalplanner.business.planner.entities.DayAssignment; +import org.navalplanner.business.resources.entities.Resource; +import org.navalplanner.web.resourceload.ResourceLoadParameters.Paginator; import org.zkoss.ganttz.data.resourceload.LoadTimeLine; import org.zkoss.ganttz.timetracker.zoom.ZoomLevel; import org.zkoss.ganttz.util.Interval; public class ResourceLoadDisplayData { + private static Callable cached(Callable callable) { + return new CachedCallable(callable); + } + + private static T resolve(Callable callable) { + try { + return callable.call(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static class CachedCallable implements Callable { + private final Callable callable; + + private T result; + + public CachedCallable(Callable callable) { + Validate.notNull(callable); + this.callable = callable; + } + + @Override + public T call() throws Exception { + if (result != null) { + return result; + } + return result = callable.call(); + } + + } + private final List timeLines; private final Interval viewInterval; - public ResourceLoadDisplayData(List timeLines) { + private final Paginator paginator; + + private final Callable> resourcesConsidered; + + private final Callable> assignmentsConsidered; + + private final LocalDate filterStart; + + private final LocalDate filterEnd; + + public ResourceLoadDisplayData(List timeLines, + LocalDate filterStart, LocalDate filterEnd, + Paginator paginator, + Callable> resourcesConsidered, + Callable> assignmentsConsidered) { + Validate.notNull(timeLines); + Validate.notNull(paginator); + Validate.notNull(resourcesConsidered); + Validate.notNull(assignmentsConsidered); this.timeLines = timeLines; + this.filterStart = filterStart; + this.filterEnd = filterEnd; this.viewInterval = getViewIntervalFrom(timeLines); + this.paginator = paginator; + this.resourcesConsidered = cached(resourcesConsidered); + this.assignmentsConsidered = cached(assignmentsConsidered); } private static Interval getViewIntervalFrom(List timeLines) { @@ -49,4 +110,24 @@ public class ResourceLoadDisplayData { new LocalDate(interval.getFinish())); } + public Paginator getPaginator() { + return paginator; + } + + public List getResourcesConsidered() { + return resolve(resourcesConsidered); + } + + public List getDayAssignmentsConsidered() { + return resolve(assignmentsConsidered); + } + + public LocalDate getFilterStart() { + return filterStart; + } + + public LocalDate getFilterEnd() { + return filterEnd; + } + } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/resourceload/ResourceLoadModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/resourceload/ResourceLoadModel.java index 8686f9cb5..632bcfa95 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/resourceload/ResourceLoadModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/resourceload/ResourceLoadModel.java @@ -30,6 +30,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.LinkedList; @@ -38,17 +39,18 @@ import java.util.ListIterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.concurrent.Callable; import org.joda.time.LocalDate; import org.navalplanner.business.calendars.daos.IBaseCalendarDAO; import org.navalplanner.business.calendars.entities.ResourceCalendar; +import org.navalplanner.business.common.AdHocTransactionService; import org.navalplanner.business.common.BaseEntity; -import org.navalplanner.business.common.daos.IConfigurationDAO; +import org.navalplanner.business.common.IAdHocTransactionService; import org.navalplanner.business.common.exceptions.InstanceNotFoundException; import org.navalplanner.business.orders.daos.IOrderDAO; import org.navalplanner.business.orders.entities.Order; import org.navalplanner.business.orders.entities.OrderElement; -import org.navalplanner.business.planner.daos.IDayAssignmentDAO; import org.navalplanner.business.planner.daos.IResourceAllocationDAO; import org.navalplanner.business.planner.entities.DayAssignment; import org.navalplanner.business.planner.entities.GenericResourceAllocation; @@ -76,6 +78,8 @@ import org.navalplanner.web.planner.order.PlanningStateCreator.RelatedWithAnyOf; import org.navalplanner.web.planner.order.PlanningStateCreator.RelatedWithResource; import org.navalplanner.web.planner.order.PlanningStateCreator.SpecificRelatedWithCriterionOnInterval; import org.navalplanner.web.planner.order.PlanningStateCreator.TaskOnInterval; +import org.navalplanner.web.resourceload.ResourceLoadParameters.IReattacher; +import org.navalplanner.web.resourceload.ResourceLoadParameters.Paginator; import org.navalplanner.web.security.SecurityUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanDefinition; @@ -115,72 +119,25 @@ public class ResourceLoadModel implements IResourceLoadModel { @Autowired private IScenarioManager scenarioManager; - private PlanningState filterBy; - - private boolean filterByResources = true; - - /** - * Contains the resources to be shown when specified manually using - * the Bandbox - */ - private List resourcesToShowList = new ArrayList(); - - /** - * Contains the criteria to be shown when specified manually using - * the Bandbox - */ - private List criteriaToShowList = new ArrayList(); - - private LocalDate initDateFilter; - private LocalDate endDateFilter; - - @Autowired - private IDayAssignmentDAO dayAssignmentDAO; - @Autowired private IBaseCalendarDAO baseCalendarDAO; @Autowired - private IConfigurationDAO configurationDAO; - - private int pageFilterPosition = 0; - private int pageSize = 10; - - /** - * Contains all the resources which have to be filtered page by page - */ - private List allResourcesList; - - /** - * Contains all the resources which have to be filtered page by page - */ - List allCriteriaList; - - private Scenario getCurrentScenario() { - if (filterBy != null) { - return filterBy.getCurrentScenario(); - } - return scenarioManager.getCurrent(); - } + private IAdHocTransactionService transactionService; @Override @Transactional(readOnly = true) - public ResourceLoadDisplayData calculateDataToDisplay(boolean filterByResources) { - filterBy = null; - this.filterByResources = filterByResources; - return new ResourceLoadDisplayData(calculateLoadTimeLines()); - } - - @Override - @Transactional(readOnly = true) - public ResourceLoadDisplayData calculateDataToDisplay(PlanningState filterBy, - boolean filterByResources) { - this.filterBy = filterBy; - this.filterBy.reattach(); - this.filterBy.reassociateResourcesWithSession(); - this.filterByResources = filterByResources; - return new ResourceLoadDisplayData(calculateLoadTimeLines()); + public ResourceLoadDisplayData calculateDataToDisplay( + ResourceLoadParameters parameters) { + ResourceAllocationsFinder allocationsFinder = create(parameters); + List loadTimeLines = allocationsFinder.buildTimeLines(); + return new ResourceLoadDisplayData(loadTimeLines, + parameters.getInitDateFilter(), + parameters.getEndDateFilter(), allocationsFinder.getPaginator(), + allocationsFinder.lazilyGetResourcesIncluded(), + allocationsFinder.lazilyGetAssignmentsShown()); } + @Override @Transactional(readOnly = true) @@ -215,134 +172,803 @@ public class ResourceLoadModel implements IResourceLoadModel { return false; } - private List calculateLoadTimeLines() { - List result = new ArrayList(); - if (filterByResources) { - result.addAll(groupsFor(resourcesToShow())); - } else { - allocationsByCriterion = allocationsByCriterion(); - result.addAll(groupsFor(allocationsByCriterion)); - } - return result; + public ResourceAllocationsFinder create(ResourceLoadParameters parameters) { + return parameters.isFilterByResources() ? new ByResourceFinder( + parameters) : new ByCriterionFinder(parameters); } - private Map>> allocationsByCriterion; + private abstract class ResourceAllocationsFinder { - private Map>> allocationsByCriterion() { - if (!criteriaToShowList.isEmpty()) { - reattachCriteriaToShow(); - // reattaching criterions so the query returns the same criteria as - // keys - allCriteriaList = new ArrayList(criteriaToShowList); + protected final ResourceLoadParameters parameters; + + private ResourceAllocationsFinder(ResourceLoadParameters parameters) { + this.parameters = parameters; + } + + @SuppressWarnings("unchecked") + public Callable> lazilyGetResourcesIncluded() { + return AdHocTransactionService.readOnlyProxy(transactionService, + Callable.class, new Callable>() { + + @Override + public List call() throws Exception { + return reattach(getResourcesIncluded()); + } + + private List reattach(List resources) { + for (Resource resource : resources) { + resourcesDAO.reattach(resource); + ResourceCalendar calendar = resource + .getCalendar(); + baseCalendarDAO.reattach(calendar); + BaseCalendarModel + .forceLoadBaseCalendar(calendar); + resource.getAssignments().size(); + } + return resources; + } + + }); + } + + abstract List getResourcesIncluded(); + + public Callable> lazilyGetAssignmentsShown() { + return new Callable>() { + + @Override + public List call() throws Exception { + return getAssignmentsShown(); + } + + }; + } + + private List getAssignmentsShown() { + List result = new ArrayList(); + Map>> foundAllocations = getFoundAllocations(); + for (Entry>> each : foundAllocations + .entrySet()) { + for (ResourceAllocation eachAllocation : each.getValue()) { + result.addAll(eachAllocation.getAssignments()); + } + } + return result; + } + + abstract List buildTimeLines(); + + abstract Map>> getFoundAllocations(); + + abstract Paginator getPaginator(); + + Scenario getCurrentScenario() { + PlanningState state = parameters.getPlanningState(); + if (state != null) { + return state.getCurrentScenario(); + } + return scenarioManager.getCurrent(); + } + + Collection> doReplacementsIfNeeded( + Collection> allocations, + IAllocationCriteria criteria) { + if (parameters.getPlanningState() == null) { + return allocations; + } + return parameters.getPlanningState().replaceByCurrentOnes( + allocations, criteria); + } + + protected IAllocationCriteria onInterval() { + return new TaskOnInterval(parameters.getInitDateFilter(), + parameters.getEndDateFilter()); + } + + } + + private class ByResourceFinder extends ResourceAllocationsFinder { + + private final Map>> allocationsByResource; + private Paginator resources; + + public ByResourceFinder(ResourceLoadParameters parameters) { + super(parameters); + this.resources = resourcesToShow(); + this.allocationsByResource = eachWithAllocations(this.resources + .getForCurrentPage()); + } + + @Override + Paginator getPaginator() { + return resources; + } + + @Override + List getResourcesIncluded() { + return resources.getForCurrentPage(); + } + + @Override + Map>> getFoundAllocations() { + return allocationsByResource; + } + + @Override + List buildTimeLines() { + return new ByResourceLoadTimesLinesBuilder(parameters) + .buildGroupsByResource(getFoundAllocations()); + } + + private Paginator resourcesToShow() { + return parameters.getEntities(Resource.class, + new Callable>() { + + @Override + public List call() throws Exception { + if (parameters.thereIsCurrentOrder()) { + return resourcesForActiveTasks(); + } else { + return allResources(); + } + } + + private List resourcesForActiveTasks() { + return Resource.sortByName(parameters + .getPlanningState() + .getResourcesRelatedWithAllocations()); + } + + private List allResources() { + return Resource.sortByName(resourcesDAO + .list(Resource.class)); + } + }, new IReattacher() { + + @Override + public Resource reattach(Resource entity) { + return resourcesDAO.findExistingEntity(entity + .getId()); + } + }); + } + + private Map>> eachWithAllocations( + List allResources) { + Map>> result = new LinkedHashMap>>(); + for (Resource resource : allResources) { + IAllocationCriteria criteria = and(onInterval(), + relatedToResource(resource)); + result.put(resource, ResourceAllocation + .sortedByStartDate(doReplacementsIfNeeded( + resourceAllocationDAO.findAllocationsRelatedTo( + getCurrentScenario(), resource, + parameters.getInitDateFilter(), + parameters.getEndDateFilter()), + criteria))); + } + return result; + } + + private IAllocationCriteria relatedToResource(Resource resource) { + return new RelatedWithResource(resource); + } + + } + + private class ByCriterionFinder extends + ResourceAllocationsFinder { + + private final Map>> allocationsByCriterion; + private final Paginator criterions; + + public ByCriterionFinder(ResourceLoadParameters parameters) { + super(parameters); + this.criterions = findCriterions(); + this.allocationsByCriterion = allocationsByCriterion(this.criterions + .getForCurrentPage()); + } + + @Override + Paginator getPaginator() { + return criterions; + } + + @Override + List getResourcesIncluded() { + Set result = new HashSet(); + for (List> each : getFoundAllocations() + .values()) { + for (ResourceAllocation eachAllocation : each) { + result.addAll(eachAllocation.getAssociatedResources()); + } + } + return new ArrayList(result); + } + + @Override + protected Map>> getFoundAllocations() { + return allocationsByCriterion; + } + + @Override + List buildTimeLines() { + return new ByCriterionLoadTimesLinesBuilder(parameters) + .buildGroupsByCriterion(getFoundAllocations()); + } + + private Paginator findCriterions() { + return parameters.getEntities(Criterion.class, + criterionRetriever(), new IReattacher() { + + @Override + public Criterion reattach(Criterion entity) { + criterionDAO.reattachUnmodifiedEntity(entity); + return entity; + } + }); + } + + Callable> criterionRetriever() { + return new Callable>() { + + @Override + public List call() throws Exception { + return Criterion + .sortByInclusionTypeAndName(findCriterions()); + } + + private Collection findCriterions() { + if (parameters.thereIsCurrentOrder()) { + List tasks = justTasks(parameters + .getCurrentOrder() + .getAllChildrenAssociatedTaskElements()); + return getCriterionsOn(tasks); + } else { + return findAllocationsGroupedByCriteria().keySet(); + } + } + + private List getCriterionsOn( + Collection tasks) { + Set result = new LinkedHashSet(); + for (Task eachTask : tasks) { + result.addAll(getCriterionsOn(eachTask)); + } + return new ArrayList(result); + } + + private Set getCriterionsOn(Task task) { + Set result = new LinkedHashSet(); + for (GenericResourceAllocation eachAllocation : onlyGeneric(task + .getSatisfiedResourceAllocations())) { + result.addAll(eachAllocation.getCriterions()); + } + return result; + } + }; + } + + private Map>> allocationsByCriterion( + List criterions) { return withAssociatedSpecific(findAllocationsGroupedByCriteria( - scenarioManager.getCurrent(), criteriaToShowList)); + scenarioManager.getCurrent(), criterions)); } - Map> result = findAllocationsByCriterion(); - allCriteriaList = Criterion.sortByInclusionTypeAndName(result.keySet()); - if (pageFilterPosition == -1) { - return withAssociatedSpecific(result); + + private Map> findAllocationsGroupedByCriteria( + Scenario onScenario, List relatedWith) { + Map> result = resourceAllocationDAO + .findGenericAllocationsBySomeCriterion(onScenario, + relatedWith, + asDate(parameters.getInitDateFilter()), + asDate(parameters.getEndDateFilter())); + return doReplacementsIfNeeded(result, + and(onInterval(), new RelatedWithAnyOf(relatedWith))); } - List criteriaReallyShown = allCriteriaList.subList( - pageFilterPosition, getEndPositionForCriterionPageFilter()); - return withAssociatedSpecific(onlyForThePagesShown(criteriaReallyShown, - result)); - } - private Map> findAllocationsByCriterion() { - if (filter()) { - List tasks = justTasks(filterBy.getOrder() - .getAllChildrenAssociatedTaskElements()); - return findAllocationsGroupedByCriteria(getCurrentScenario(), - getCriterionsOn(tasks)); - } else { - return findAllocationsGroupedByCriteria(); - } - } - - private IAllocationCriteria onInterval() { - return new TaskOnInterval(initDateFilter, endDateFilter); - } - - private Map> findAllocationsGroupedByCriteria( - Scenario onScenario, - List relatedWith) { - Map> result = resourceAllocationDAO - .findGenericAllocationsBySomeCriterion(onScenario, relatedWith, - asDate(initDateFilter), asDate(endDateFilter)); - return doReplacementsIfNeeded(result, - and(onInterval(), new RelatedWithAnyOf(relatedWith))); - } - - private Map> findAllocationsGroupedByCriteria() { - return doReplacementsIfNeeded( - resourceAllocationDAO.findGenericAllocationsByCriterion( - getCurrentScenario(), - asDate(initDateFilter), asDate(endDateFilter)), - onInterval()); - } - - private Map> doReplacementsIfNeeded( - Map> map, - IAllocationCriteria criteria) { - if (filterBy == null) { - return map; - } - Map> result = new HashMap>(); - for (Entry> each : map - .entrySet()) { - List> replaced = filterBy - .replaceByCurrentOnes(each.getValue(), criteria); - if (!replaced.isEmpty()) { - result.put(each.getKey(), ResourceAllocation.getOfType( - GenericResourceAllocation.class, replaced)); + private Map>> withAssociatedSpecific( + Map> genericAllocationsByCriterion) { + Map>> result = new HashMap>>(); + for (Entry> each : genericAllocationsByCriterion + .entrySet()) { + List> both = new ArrayList>(); + both.addAll(each.getValue()); + both.addAll(doReplacementsIfNeeded(resourceAllocationDAO + .findSpecificAllocationsRelatedTo(getCurrentScenario(), + each.getKey(), + asDate(parameters.getInitDateFilter()), + asDate(parameters.getEndDateFilter())), + and(onInterval(), specificRelatedTo(each.getKey())))); + result.put(each.getKey(), both); } + return result; } - return result; - } - private Map>> withAssociatedSpecific( - Map> genericAllocationsByCriterion) { - Map>> result = new HashMap>>(); - for (Entry> each : genericAllocationsByCriterion - .entrySet()) { - List> both = new ArrayList>(); - both.addAll(each.getValue()); - both.addAll(doReplacementsIfNeeded(resourceAllocationDAO - .findSpecificAllocationsRelatedTo(getCurrentScenario(), - each.getKey(), - asDate(initDateFilter), asDate(endDateFilter)), - and(onInterval(), specificRelatedTo(each.getKey())))); - result.put(each.getKey(), both); + private IAllocationCriteria specificRelatedTo(Criterion key) { + return new SpecificRelatedWithCriterionOnInterval(key, + parameters.getInitDateFilter(), + parameters.getEndDateFilter()); } - return result; - } - private IAllocationCriteria specificRelatedTo(Criterion key) { - return new SpecificRelatedWithCriterionOnInterval(key, - initDateFilter, endDateFilter); - } - - private Collection> doReplacementsIfNeeded( - Collection> allocations, - IAllocationCriteria criteria) { - if (filterBy == null) { - return allocations; + private Map> findAllocationsGroupedByCriteria() { + return doReplacementsIfNeeded( + resourceAllocationDAO.findGenericAllocationsByCriterion( + getCurrentScenario(), + asDate(parameters.getInitDateFilter()), + asDate(parameters.getEndDateFilter())), + onInterval()); } - return filterBy.replaceByCurrentOnes(allocations, criteria); - } - private > Map> onlyForThePagesShown( - List criteriaReallyShown, - Map> allocationsByCriteria) { - Map> result = new HashMap>(); - for (Criterion each : criteriaReallyShown) { - if (allocationsByCriteria.get(each) != null) { - result.put(each, allocationsByCriteria.get(each)); + private Map> doReplacementsIfNeeded( + Map> map, + IAllocationCriteria criteria) { + if (!parameters.thereIsCurrentOrder()) { + return map; } + Map> result = new HashMap>(); + for (Entry> each : map + .entrySet()) { + List> replaced = parameters + .getPlanningState().replaceByCurrentOnes( + each.getValue(), criteria); + if (!replaced.isEmpty()) { + result.put(each.getKey(), ResourceAllocation.getOfType( + GenericResourceAllocation.class, replaced)); + } + } + return result; } - return result; + } + class LoadTimeLinesBuilder { + + final PeriodBuilderFactory periodBuilderFactory; + private final ResourceLoadParameters parameters; + + public LoadTimeLinesBuilder(ResourceLoadParameters parameters) { + this.parameters = parameters; + this.periodBuilderFactory = new PeriodBuilderFactory( + parameters.getInitDateFilter(), + parameters.getEndDateFilter()); + } + + TimeLineRole getCurrentTimeLineRole(BaseEntity entity) { + return new TimeLineRole(entity); + } + + LoadTimeLine buildGroupFor(Resource resource, + List> sortedByStartDate) { + TimeLineRole role = getCurrentTimeLineRole(resource); + LoadTimeLine result = new LoadTimeLine(buildTimeLine(resource, + resource.getName(), sortedByStartDate, "resource", role), + buildSecondLevel(resource, sortedByStartDate)); + return result; + } + + private List buildSecondLevel(Resource resource, + List> sortedByStartDate) { + List result = new ArrayList(); + Map>> byOrder = byOrder(sortedByStartDate); + + if (thereIsCurrentOrder()) { + List> forCurrentOrder = byOrder + .get(getCurrentOrder()); + if (forCurrentOrder != null) { + result.addAll(buildTimeLinesForOrder(resource, + forCurrentOrder)); + } + byOrder.remove(getCurrentOrder()); + // 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; + } + + Order getCurrentOrder() { + return parameters.getCurrentOrder(); + } + + boolean thereIsCurrentOrder() { + return parameters.thereIsCurrentOrder(); + } + + private List buildTimeLinesForOrder(Resource resource, + List> sortedByStartDate) { + List result = new ArrayList(); + result.addAll(buildTimeLinesForEachTask(resource, + onlySpecific(sortedByStartDate))); + result.addAll(buildTimeLinesForEachCriterion(resource, + onlyGeneric(sortedByStartDate))); + Collections.sort(result, LoadTimeLine.byStartAndEndDate()); + return result; + } + + private List buildTimeLinesForEachTask(Resource resource, + List sortedByStartDate) { + + List> listOnlySpecific = new ArrayList>( + sortedByStartDate); + Map>> byTask = ResourceAllocation + .byTask(listOnlySpecific); + + List secondLevel = new ArrayList(); + for (Entry>> entry : byTask + .entrySet()) { + Task task = entry.getKey(); + TimeLineRole role = getCurrentTimeLineRole(task); + LoadTimeLine timeLine = buildTimeLine(resource, task.getName(), + entry.getValue(), "specific", role); + if (!timeLine.isEmpty()) { + secondLevel.add(timeLine); + } + + } + return secondLevel; + } + + private List buildTimeLinesForEachCriterion( + Resource resource, + List sortdByStartDate) { + Map, List> byCriterions = GenericResourceAllocation + .byCriterions(sortdByStartDate); + + List result = new ArrayList(); + for (Entry, List> entry : byCriterions + .entrySet()) { + + Map>> byTask = ResourceAllocation + .byTask(new ArrayList>(entry + .getValue())); + + for (Entry>> entryTask : byTask + .entrySet()) { + + Task task = entryTask.getKey(); + List resouceAllocations = onlyGeneric(entryTask + .getValue()); + TimeLineRole role = getCurrentTimeLineRole(task); + LoadTimeLine timeLine = buildTimeLine(entry.getKey(), task, + resource, "generic", resouceAllocations, role); + if (!timeLine.isEmpty()) { + result.add(timeLine); + } + + } + } + return result; + } + + private LoadTimeLine buildTimeLine(Collection criterions, + Task task, Resource resource, String type, + List allocationsSortedByStartDate, + TimeLineRole role) { + LoadPeriodGeneratorFactory periodGeneratorFactory = LoadPeriodGenerator + .onResourceSatisfying(resource, criterions); + List loadPeriods = periodBuilderFactory.build( + periodGeneratorFactory, allocationsSortedByStartDate); + return new LoadTimeLine(getName(criterions, task), loadPeriods, + type, role); + } + + String getName(Collection criterions, Task task) { + String prefix = task.getName(); + return (prefix + " :: " + Criterion.getCaptionFor(criterions)); + } + + private LoadTimeLine buildTimeLinesForOtherOrders(Resource resource, + Map>> byOrder) { + List> resourceAllocations = getAllSortedValues(byOrder); + if (resourceAllocations.isEmpty()) { + return null; + } + TimeLineRole role = getCurrentTimeLineRole(null); + LoadTimeLine group = new LoadTimeLine( + buildTimeLine(resource, _("Other projects"), + resourceAllocations, "resource", role), + buildTimeLinesGroupForOrder(resource, byOrder)); + return group; + } + + List> getAllSortedValues( + Map>> byOrder) { + List> resourceAllocations = new ArrayList>(); + for (List> listAllocations : byOrder.values()) { + resourceAllocations.addAll(listAllocations); + } + return ResourceAllocation.sortedByStartDate(resourceAllocations); + } + + private List buildTimeLinesGroupForOrder( + Resource resource, + Map>> byOrder) { + List result = new ArrayList(); + for (Order order : byOrder.keySet()) { + TimeLineRole role = getCurrentTimeLineRole(order); + result.add(new LoadTimeLine(buildTimeLine(resource, + order.getName(), byOrder.get(order), "resource", role), + buildTimeLinesForOrder(resource, byOrder.get(order)))); + } + Collections.sort(result, LoadTimeLine.byStartAndEndDate()); + return result; + } + + LoadTimeLine buildTimeLine(Resource resource, String name, + List> sortedByStartDate, + String type, TimeLineRole role) { + + List loadPeriods = periodBuilderFactory + .build(LoadPeriodGenerator.onResource(resource), + sortedByStartDate); + return new LoadTimeLine(name, loadPeriods, type, role); + } + + } + + class ByResourceLoadTimesLinesBuilder extends LoadTimeLinesBuilder { + + public ByResourceLoadTimesLinesBuilder(ResourceLoadParameters parameters) { + super(parameters); + } + + List buildGroupsByResource( + Map>> map) { + List result = new ArrayList(); + for (Entry>> each : map + .entrySet()) { + LoadTimeLine l = buildGroupFor(each.getKey(), each.getValue()); + if (!l.isEmpty()) { + result.add(l); + } + } + return result; + } + + } + + class ByCriterionLoadTimesLinesBuilder extends LoadTimeLinesBuilder { + + public ByCriterionLoadTimesLinesBuilder( + ResourceLoadParameters parameters) { + super(parameters); + } + + List buildGroupsByCriterion( + Map>> map) { + return groupsFor(map); + } + + private List groupsFor( + Map>> allocationsByCriterion) { + List result = new ArrayList(); + for (Entry>> each : allocationsByCriterion + .entrySet()) { + Criterion criterion = each.getKey(); + List> allocations = ResourceAllocation + .sortedByStartDate(each.getValue()); + if (allocations == null) { + continue; + } + TimeLineRole role = getCurrentTimeLineRole(criterion); + LoadTimeLine group = new LoadTimeLine(createMain(criterion, + allocations, role), buildSecondaryLevels(criterion, + allocations)); + if (!group.isEmpty()) { + result.add(group); + } + } + return result; + } + + private LoadTimeLine createMain(Criterion criterion, + List> orderedAllocations, + TimeLineRole role) { + return new LoadTimeLine(criterion.getType().getName() + ": " + + criterion.getName(), createPeriods(criterion, + orderedAllocations), "global-generic", role); + } + + private List createPeriods(Criterion criterion, + List> value) { + return periodBuilderFactory.build(LoadPeriodGenerator.onCriterion( + criterion, resourcesSearchModel), value); + } + + private List buildSecondaryLevels(Criterion criterion, + List> allocations) { + List result = new ArrayList(); + result.addAll(buildSubLevels(criterion, ResourceAllocation + .getOfType(GenericResourceAllocation.class, allocations))); + result.add(buildRelatedSpecificAllocations(criterion, allocations)); + Collections.sort(result, LoadTimeLine.byStartAndEndDate()); + return result; + } + + private List buildSubLevels(Criterion criterion, + List> allocations) { + List result = new ArrayList(); + Map>> byOrder = byOrder(new ArrayList>( + allocations)); + + if (thereIsCurrentOrder()) { + List> allocationsForCurrent = byOrder + .get(getCurrentOrder()); + if (allocationsForCurrent != null) { + result.addAll(buildTimeLinesForOrder(getCurrentOrder(), + criterion, allocationsForCurrent)); + } + byOrder.remove(getCurrentOrder()); + // build time lines for other orders + LoadTimeLine lineOthersOrders = buildTimeLinesForOtherOrders( + criterion, byOrder); + if (lineOthersOrders != null) { + result.add(lineOthersOrders); + } + } else { + result.addAll(buildTimeLinesGroupForOrder(criterion, byOrder)); + } + return result; + } + + private LoadTimeLine buildTimeLinesForOtherOrders(Criterion criterion, + Map>> byOrder) { + List> allocations = getAllSortedValues(byOrder); + if (allocations.isEmpty()) { + return null; + } + + LoadTimeLine group = new LoadTimeLine(buildTimeLine(criterion, + "Other projects", "global-generic", allocations, + getCurrentTimeLineRole(null)), buildTimeLinesGroupForOrder( + criterion, byOrder)); + return group; + } + + private List buildTimeLinesGroupForOrder( + Criterion criterion, + Map>> byOrder) { + List result = new ArrayList(); + for (Order order : byOrder.keySet()) { + if (byOrder.get(order) == null) { + // no allocations found for order + continue; + } + TimeLineRole role = getCurrentTimeLineRole(order); + result.add(new LoadTimeLine(buildTimeLine(criterion, + order.getName(), "global-generic", byOrder.get(order), + role), buildTimeLinesForOrder(order, criterion, + byOrder.get(order)))); + } + return result; + } + + LoadTimeLine buildTimeLine(Criterion criterion, String name, + String type, List> allocations, + TimeLineRole role) { + List generics = onlyGeneric(allocations); + return new LoadTimeLine(name, createPeriods(criterion, generics), + type, role); + } + + private List buildTimeLinesForOrder(Order order, + Criterion criterion, List> allocations) { + List result = new ArrayList(); + result.addAll(buildTimeLinesForEachTask(criterion, + onlyGeneric(allocations))); + result.addAll(buildTimeLinesForEachResource(criterion, + onlySpecific(allocations), getCurrentTimeLineRole(order))); + Collections.sort(result, LoadTimeLine.byStartAndEndDate()); + return result; + } + + private List buildTimeLinesForEachTask( + Criterion criterion, List allocations) { + Map> byTask = ResourceAllocation + .byTask(allocations); + + List secondLevel = new ArrayList(); + for (Entry> entry : byTask + .entrySet()) { + Task task = entry.getKey(); + + Map, List> mapSameCriteria = getAllocationsWithSameCriteria((entry + .getValue())); + for (Entry, List> entrySameCriteria : mapSameCriteria + .entrySet()) { + Set criterions = entrySameCriteria.getKey(); + List genericAllocations = entrySameCriteria + .getValue(); + List> resourceAllocations = new ArrayList>( + genericAllocations); + TimeLineRole role = getCurrentTimeLineRole(task); + + /** + * Each resource line has the same role than its allocated + * task, so that link with the resource allocation screen + */ + LoadTimeLine timeLine = new LoadTimeLine(buildTimeLine( + criterions, task, criterion, "global-generic", + resourceAllocations, role), + buildTimeLinesForEachResource(criterion, + genericAllocations, role)); + if (!timeLine.isEmpty()) { + secondLevel.add(timeLine); + } + } + } + return secondLevel; + } + + private List buildTimeLinesForEachResource( + Criterion criterion, + List> allocations, + TimeLineRole role) { + Map>> byResource = ResourceAllocation + .byResource(allocations); + + List secondLevel = new ArrayList(); + for (Entry>> entry : byResource + .entrySet()) { + Resource resource = entry.getKey(); + List> resourceAllocations = entry + .getValue(); + String descriptionTimeLine = resource.getShortDescription(); + + LoadTimeLine timeLine = buildTimeLine(resource, + descriptionTimeLine, resourceAllocations, "generic", + role); + if (!timeLine.isEmpty()) { + secondLevel.add(timeLine); + } + + } + return secondLevel; + } + + private LoadTimeLine buildTimeLine(Collection criterions, + Task task, Criterion criterion, String type, + List> allocations, + TimeLineRole role) { + return buildTimeLine(criterion, getName(criterions, task), type, + allocations, role); + } + + private LoadTimeLine buildRelatedSpecificAllocations( + Criterion criterion, + List> allocations) { + List specific = ResourceAllocation + .getOfType(SpecificResourceAllocation.class, allocations); + + LoadTimeLine main = new LoadTimeLine(_("Specific Allocations"), + createPeriods(criterion, specific), "related-specific", + getCurrentTimeLineRole(criterion)); + List children = buildGroupsFor(ResourceAllocation + .byResource(new ArrayList>(specific))); + return new LoadTimeLine(main, children); + } + + private List buildGroupsFor( + Map>> map) { + List result = new ArrayList(); + for (Entry>> each : map + .entrySet()) { + LoadTimeLine l = buildGroupFor(each.getKey(), each.getValue()); + if (!l.isEmpty()) { + result.add(l); + } + } + return result; + } + + } + + public static Date asDate(LocalDate date) { if (date == null) { return null; @@ -357,428 +983,11 @@ public class ResourceLoadModel implements IResourceLoadModel { return LocalDate.fromDateFields(date); } - private void reattachCriteriaToShow() { - for (Criterion each : criteriaToShowList) { - criterionDAO.reattachUnmodifiedEntity(each); - } - } - - private List getCriterionsOn(Collection tasks) { - Set result = new LinkedHashSet(); - for (Task eachTask : tasks) { - result.addAll(getCriterionsOn(eachTask)); - } - return new ArrayList(result); - } - - private Set getCriterionsOn(Task task) { - Set result = new LinkedHashSet(); - for (GenericResourceAllocation eachAllocation : onlyGeneric(task - .getSatisfiedResourceAllocations())) { - result.addAll(eachAllocation.getCriterions()); - } - return result; - } - - private List resourcesToShow() { - if(!resourcesToShowList.isEmpty()) { - return getResourcesToShowReattached(); - } - // if we haven't manually specified some resources to show, we load them - if (filter()) { - allResourcesList = resourcesForActiveTasks(); - } else { - allResourcesList = allResources(); - } - return applyPagination(allResourcesList); - } - - private List applyPagination(List allResourcesList) { - if (pageFilterPosition == -1) { - return allResourcesList; - } - return allResourcesList.subList(pageFilterPosition, Math.min( - pageFilterPosition + pageSize, allResourcesList.size())); - } - - private List criteriaToShow() { - List criteriaList; - if(!criteriaToShowList.isEmpty()) { - criteriaList = criteriaToShowList; - } - else if(pageFilterPosition == -1) { - criteriaList = allCriteriaList; - } - else { - criteriaList = allCriteriaList.subList( - pageFilterPosition, getEndPositionForCriterionPageFilter()); - } - return criteriaList; - } - - @Override - public List getAllResourcesList() { - return allResourcesList; - } - - @Override - public List getAllCriteriaList() { - return allCriteriaList; - } - - @Override - public int getPageFilterPosition() { - return pageFilterPosition; - } - - @Override - public void setPageFilterPosition(int pageFilterPosition) { - this.pageFilterPosition = pageFilterPosition; - } - - @Override - public int getPageSize() { - return pageSize; - } - - private int getEndPositionForCriterionPageFilter() { - return - (pageFilterPosition + pageSize < allCriteriaList.size())? - pageFilterPosition + pageSize : - allCriteriaList.size(); - } - - private boolean filter() { - return filterBy != null; - } - - private List resourcesForActiveTasks() { - return Resource.sortByName(filterBy - .getResourcesRelatedWithAllocations()); - } - - private List allResources() { - return Resource.sortByName(resourcesDAO.list(Resource.class)); - } - - private TimeLineRole getCurrentTimeLineRole(BaseEntity entity) { - return new TimeLineRole(entity); - } - - /** - * @param allocationsByCriterion - * @return - */ - private List groupsFor( - Map>> allocationsByCriterion) { - List result = new ArrayList(); - for(Criterion criterion : criteriaToShow()) { - if (allocationsByCriterion.get(criterion) == null) { - // no allocations found for criterion - continue; - } - List> allocations = ResourceAllocation - .sortedByStartDate(allocationsByCriterion - .get(criterion)); - TimeLineRole role = getCurrentTimeLineRole(criterion); - LoadTimeLine group = new LoadTimeLine(createMain(criterion, - allocations, role), buildSecondaryLevels(criterion, - allocations)); - if (!group.isEmpty()) { - result.add(group); - } - } - return result; - } - - private List buildSecondaryLevels(Criterion criterion, - List> allocations) { - List result = new ArrayList(); - result.addAll(buildSubLevels(criterion, ResourceAllocation.getOfType( - GenericResourceAllocation.class, allocations))); - result.add(buildRelatedSpecificAllocations(criterion, allocations)); - Collections.sort(result, LoadTimeLine.byStartAndEndDate()); - return result; - } - - private LoadTimeLine buildRelatedSpecificAllocations(Criterion criterion, - List> allocations) { - List specific = ResourceAllocation - .getOfType(SpecificResourceAllocation.class, allocations); - - LoadTimeLine main = new LoadTimeLine(_("Specific Allocations"), - createPeriods(criterion, specific), "related-specific", - getCurrentTimeLineRole(criterion)); - List children = buildGroupsFor(ResourceAllocation - .byResource(new ArrayList>(specific))); - return new LoadTimeLine(main, children); - } - - private List buildSubLevels(Criterion criterion, - List> allocations) { - List result = new ArrayList(); - Map>> byOrder = byOrder(new ArrayList>( - allocations)); - - // REVISAR ESTO ANTES DE ACABAR - if (filter()) { - // build time lines for current order - if (byOrder.get(filterBy.getOrder()) != null) { - result.addAll(buildTimeLinesForOrder(filterBy.getOrder(), - criterion, byOrder.get(filterBy.getOrder()))); - } - byOrder.remove(filterBy.getOrder()); - // build time lines for other orders - LoadTimeLine lineOthersOrders = buildTimeLinesForOtherOrders( - criterion, byOrder); - if (lineOthersOrders != null) { - result.add(lineOthersOrders); - } - } else { - result.addAll(buildTimeLinesGroupForOrder(criterion, byOrder)); - } - return result; - } - - private List buildTimeLinesForOrder(Order order, - Criterion criterion, - List> allocations) { - List result = new ArrayList(); - result.addAll(buildTimeLinesForEachTask(criterion, - onlyGeneric(allocations))); - result.addAll(buildTimeLinesForEachResource(criterion, - onlySpecific(allocations), getCurrentTimeLineRole(order))); - Collections.sort(result, LoadTimeLine.byStartAndEndDate()); - return result; - } - - private LoadTimeLine buildTimeLinesForOtherOrders(Criterion criterion, - Map>> byOrder) { - List> allocations = getAllSortedValues(byOrder); - if (allocations.isEmpty()) { - return null; - } - - LoadTimeLine group = new LoadTimeLine(buildTimeLine(criterion, - "Other projects", "global-generic", allocations, - getCurrentTimeLineRole(null)), - buildTimeLinesGroupForOrder( - criterion, byOrder)); - return group; - } - - private List buildTimeLinesGroupForOrder(Criterion criterion, - Map>> byOrder) { - List result = new ArrayList(); - for (Order order : byOrder.keySet()) { - if (byOrder.get(order) == null) { - // no allocations found for order - continue; - } - TimeLineRole role = getCurrentTimeLineRole(order); - result.add(new LoadTimeLine( - buildTimeLine(criterion, order.getName(), "global-generic", - byOrder.get(order), role), buildTimeLinesForOrder( - order, criterion, byOrder.get(order)))); - } - return result; - } - - private List buildTimeLinesForEachTask(Criterion criterion, - List allocations) { - Map> byTask = ResourceAllocation - .byTask(allocations); - - List secondLevel = new ArrayList(); - for (Entry> entry : byTask - .entrySet()) { - Task task = entry.getKey(); - - Map, List> mapSameCriteria = getAllocationsWithSameCriteria((entry - .getValue())); - for (Entry, List> entrySameCriteria : mapSameCriteria - .entrySet()) { - Set criterions = entrySameCriteria.getKey(); - List genericAllocations = entrySameCriteria - .getValue(); - List> resourceAllocations = new ArrayList>( - genericAllocations); - TimeLineRole role = getCurrentTimeLineRole(task); - - /** - * Each resource line has the same role than its allocated task, - * so that link with the resource allocation screen - */ - LoadTimeLine timeLine = new LoadTimeLine(buildTimeLine( - criterions, task, criterion, "global-generic", - resourceAllocations, role), - buildTimeLinesForEachResource(criterion, - genericAllocations, role)); - if (!timeLine.isEmpty()) { - secondLevel.add(timeLine); - } - } - } - return secondLevel; - } - private Map, List> getAllocationsWithSameCriteria( List genericAllocations) { return GenericResourceAllocation.byCriterions(genericAllocations); } - private List buildTimeLinesForEachResource( - Criterion criterion, - List> allocations, - TimeLineRole role) { - Map>> byResource = ResourceAllocation - .byResource(allocations); - - List secondLevel = new ArrayList(); - for (Entry>> entry : byResource - .entrySet()) { - Resource resource = entry.getKey(); - List> resourceAllocations = entry.getValue(); - String descriptionTimeLine = resource.getShortDescription(); - - LoadTimeLine timeLine = buildTimeLine(resource, - descriptionTimeLine, resourceAllocations, "generic", role); - if (!timeLine.isEmpty()) { - secondLevel.add(timeLine); - } - - } - return secondLevel; - } - - private LoadTimeLine createMain(Criterion criterion, - List> orderedAllocations, - TimeLineRole role) { - return new LoadTimeLine(criterion.getType().getName() + ": " + criterion.getName(), - createPeriods(criterion, orderedAllocations), "global-generic", role); - } - - private List createPeriods(Criterion criterion, - List> value) { - if (initDateFilter != null || endDateFilter != null) { - return PeriodsBuilder.build(LoadPeriodGenerator.onCriterion( - criterion, resourcesSearchModel), - value, asDate(initDateFilter), asDate(endDateFilter)); - } - return PeriodsBuilder.build(LoadPeriodGenerator.onCriterion(criterion, - resourcesSearchModel), value); - } - - private List groupsFor(List allResources) { - return buildGroupsFor(eachWithAllocations(allResources)); - } - - private Map>> eachWithAllocations( - List allResources) { - Map>> map = new LinkedHashMap>>(); - for (Resource resource : allResources) { - map.put(resource, ResourceAllocation - .sortedByStartDate(doReplacementsIfNeeded( - resourceAllocationDAO.findAllocationsRelatedTo( - getCurrentScenario(), - resource, initDateFilter, endDateFilter), - and(onInterval(), relatedToResource(resource))))); - } - return map; - } - - private IAllocationCriteria relatedToResource(Resource resource) { - return new RelatedWithResource(resource); - } - - private List buildGroupsFor( - Map>> map) { - List result = new ArrayList(); - for (Entry>> each : map - .entrySet()) { - LoadTimeLine l = buildGroupFor(each.getKey(), each.getValue()); - if (!l.isEmpty()) { - result.add(l); - } - } - return result; - } - - private LoadTimeLine buildGroupFor(Resource resource, - List> sortedByStartDate) { - TimeLineRole role = getCurrentTimeLineRole(resource); - LoadTimeLine result = new LoadTimeLine(buildTimeLine(resource, resource - .getName(), sortedByStartDate, "resource", role), - buildSecondLevel(resource, sortedByStartDate)); - return result; - } - - private List buildSecondLevel(Resource resource, - List> sortedByStartDate) { - List result = new ArrayList(); - Map>> byOrder = byOrder(sortedByStartDate); - - if (filter()) { - if (byOrder.get(filterBy.getOrder()) != null) { - // build time lines for current order - result.addAll(buildTimeLinesForOrder(resource, - byOrder.get(filterBy.getOrder()))); - } - byOrder.remove(filterBy.getOrder()); - // 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>> byOrder) { - List> resourceAllocations = getAllSortedValues(byOrder); - if (resourceAllocations.isEmpty()) { - return null; - } - TimeLineRole role = getCurrentTimeLineRole(null); - LoadTimeLine group = new LoadTimeLine(buildTimeLine(resource, - _("Other projects"), resourceAllocations, "resource", role), - buildTimeLinesGroupForOrder(resource, byOrder)); - return group; - } - - private List buildTimeLinesGroupForOrder(Resource resource, - Map>> byOrder) { - List result = new ArrayList(); - for (Order order : byOrder.keySet()) { - TimeLineRole role = getCurrentTimeLineRole(order); - result.add(new LoadTimeLine(buildTimeLine(resource, - order.getName(), byOrder.get(order), "resource", role), - buildTimeLinesForOrder(resource, byOrder.get(order)))); - } - Collections.sort(result, LoadTimeLine.byStartAndEndDate()); - return result; - } - - private List> getAllSortedValues( - Map>> byOrder) { - List> resourceAllocations = new ArrayList>(); - for (List> listAllocations : byOrder.values()) { - resourceAllocations.addAll(listAllocations); - } - return ResourceAllocation.sortedByStartDate(resourceAllocations); - } - - private void initializeIfNeeded( - Map>> result, Order order) { - if (!result.containsKey(order)) { - result.put(order, new ArrayList>()); - } - } - private Map>> byOrder( Collection> allocations) { Map>> result = new HashMap>>(); @@ -795,244 +1004,25 @@ public class ResourceLoadModel implements IResourceLoadModel { return result; } - private List buildTimeLinesForOrder(Resource resource, - List> sortedByStartDate) { - List result = new ArrayList(); - result.addAll(buildTimeLinesForEachTask(resource, - onlySpecific(sortedByStartDate))); - result.addAll(buildTimeLinesForEachCriterion(resource, - onlyGeneric(sortedByStartDate))); - Collections.sort(result, LoadTimeLine.byStartAndEndDate()); - return result; + private void initializeIfNeeded( + Map>> result, Order order) { + if (!result.containsKey(order)) { + result.put(order, new ArrayList>()); + } } - private List onlyGeneric( + private static List onlyGeneric( Collection> sortedByStartDate) { return ResourceAllocation.getOfType(GenericResourceAllocation.class, sortedByStartDate); } - private List onlySpecific( + private static List onlySpecific( List> sortedByStartDate) { return ResourceAllocation.getOfType(SpecificResourceAllocation.class, sortedByStartDate); } - private List buildTimeLinesForEachCriterion( - Resource resource, List sortdByStartDate) { - Map, List> byCriterions = GenericResourceAllocation - .byCriterions(sortdByStartDate); - - List result = new ArrayList(); - for (Entry, List> entry : byCriterions - .entrySet()) { - - Map>> byTask = ResourceAllocation - .byTask(new ArrayList>(entry - .getValue())); - - for (Entry>> entryTask : byTask - .entrySet()) { - - Task task = entryTask.getKey(); - List resouceAllocations = onlyGeneric(entryTask - .getValue()); - TimeLineRole role = getCurrentTimeLineRole(task); - LoadTimeLine timeLine = buildTimeLine(entry.getKey(), task, - resource, "generic", resouceAllocations, role); - if (!timeLine.isEmpty()) { - result.add(timeLine); - } - - } - } - return result; - } - - private List buildTimeLinesForEachTask(Resource resource, - List sortedByStartDate) { - - List> listOnlySpecific = new ArrayList>( - sortedByStartDate); - Map>> byTask = ResourceAllocation - .byTask(listOnlySpecific); - - List secondLevel = new ArrayList(); - for (Entry>> entry : byTask.entrySet()) { - Task task = entry.getKey(); - TimeLineRole role = getCurrentTimeLineRole(task); - LoadTimeLine timeLine = buildTimeLine(resource, task.getName(), - entry.getValue(), "specific", role); - if (!timeLine.isEmpty()) { - secondLevel.add(timeLine); - } - - } - return secondLevel; - } - - public static String getName(Collection criterions, - Task task) { - String prefix = task.getName(); - return (prefix + " :: " + Criterion.getCaptionFor(criterions)); - } - - private LoadTimeLine buildTimeLine(Resource resource, String name, - List> sortedByStartDate, - String type, - TimeLineRole role) { - List loadPeriods; - if(initDateFilter != null || endDateFilter != null) { - loadPeriods = PeriodsBuilder.build( - LoadPeriodGenerator.onResource(resource), - sortedByStartDate, asDate(initDateFilter), - asDate(endDateFilter)); - } - else { - loadPeriods = PeriodsBuilder - .build(LoadPeriodGenerator.onResource(resource), sortedByStartDate); - } - return new LoadTimeLine(name, loadPeriods, type, role); - } - - private LoadTimeLine buildTimeLine(Criterion criterion, String name, - String type, List> allocations, - TimeLineRole role) { - List generics = onlyGeneric(allocations); - return new LoadTimeLine(name, createPeriods(criterion, generics), type, - role); - } - - private LoadTimeLine buildTimeLine(Collection criterions, - Task task, Criterion criterion, String type, - List> allocations, - TimeLineRole role) { - return buildTimeLine(criterion, getName(criterions, task), type, - allocations, - role); - } - - private LoadTimeLine buildTimeLine(Collection criterions, - Task task, Resource resource, String type, - List allocationsSortedByStartDate, - TimeLineRole role) { - LoadPeriodGeneratorFactory periodGeneratorFactory = LoadPeriodGenerator - .onResourceSatisfying(resource, criterions); - List loadPeriods; - if(initDateFilter != null || endDateFilter != null) { - loadPeriods = PeriodsBuilder.build(periodGeneratorFactory, - allocationsSortedByStartDate, asDate(initDateFilter), - asDate(endDateFilter)); - } - else { - loadPeriods = PeriodsBuilder - .build(periodGeneratorFactory, allocationsSortedByStartDate); - } - - return new LoadTimeLine(getName(criterions, task), loadPeriods, - type, role); - } - - @Override - public void setResourcesToShow(List resourcesList) { - this.resourcesToShowList.clear(); - this.resourcesToShowList.addAll(Resource.sortByName(resourcesList)); - - } - - @Override - public void clearResourcesToShow() { - resourcesToShowList.clear(); - } - - private List getResourcesToShowReattached() { - List list = new ArrayList(); - for(Resource worker : resourcesToShowList) { - try { - //for some reason, resourcesDAO.reattach(worker) doesn't work - //and we have to retrieve them again with find - list.add(resourcesDAO.find(worker.getId())); - } - catch(InstanceNotFoundException e) { - //maybe it was removed by another transaction - //we just ignore the exception to not show the Resource - } - } - return list; - } - - @Override - public void clearCriteriaToShow() { - criteriaToShowList.clear(); - } - - @Override - public void setCriteriaToShow(List criteriaList) { - criteriaToShowList.clear(); - criteriaToShowList.addAll(criteriaList); - } - - @Override - public void setEndDateFilter(LocalDate value) { - endDateFilter = value; - } - - @Override - public void setInitDateFilter(LocalDate value) { - initDateFilter = value; - } - - @Override - public LocalDate getEndDateFilter() { - return endDateFilter; - } - - @Override - public LocalDate getInitDateFilter() { - return initDateFilter; - } - - @Transactional(readOnly = true) - public List getDayAssignments() { - if(filterByResources) { - return dayAssignmentDAO.findByResources(scenarioManager.getCurrent(), - getResources()); - } - else { - List dayAssignments = new ArrayList(); - for (Entry>> entry : allocationsByCriterion - .entrySet()) { - - for (ResourceAllocation allocation : entry.getValue()) { - dayAssignments.addAll(allocation.getAssignments()); - } - } - - return dayAssignments; - } - } - - @Override - @Transactional(readOnly = true) - public List getResources() { - List resources; - if(filterByResources) { - resources = resourcesToShow(); - } - else { - resources = Resource.sortByName(resourcesSearchModel.searchBoth() - .byCriteria(criteriaToShow()).execute()); - } - for (Resource resource : resources) { - resourcesDAO.reattach(resource); - ResourceCalendar calendar = resource.getCalendar(); - baseCalendarDAO.reattach(calendar); - BaseCalendarModel.forceLoadBaseCalendar(calendar); - resource.getAssignments().size(); - } - return resources; - } - @Override @Transactional(readOnly = true) public boolean isExpandResourceLoadViewCharts() { @@ -1049,6 +1039,29 @@ public class ResourceLoadModel implements IResourceLoadModel { } +class PeriodBuilderFactory { + private final LocalDate initDateFilter; + private final LocalDate endDateFilter; + + public PeriodBuilderFactory(LocalDate initDateFilter, LocalDate endDateFilter) { + this.initDateFilter = initDateFilter; + this.endDateFilter = endDateFilter; + } + + public List build(LoadPeriodGeneratorFactory factory, List> sortedByStartDate){ + if (initDateFilter == null && endDateFilter == null) { + return PeriodsBuilder.build(factory, sortedByStartDate); + } else { + return PeriodsBuilder.build(factory, sortedByStartDate, asDate(initDateFilter), asDate(endDateFilter)); + } + } + + private Date asDate(LocalDate date) { + return ResourceLoadModel.asDate(date); + } + +} + class PeriodsBuilder { private final List> sortedByStartDate; diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/resourceload/ResourceLoadParameters.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/resourceload/ResourceLoadParameters.java new file mode 100644 index 000000000..190d31a44 --- /dev/null +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/resourceload/ResourceLoadParameters.java @@ -0,0 +1,215 @@ +/* + * This file is part of NavalPlan + * + * Copyright (C) 2011 Igalia, S.L. + * + * 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.resourceload; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.Callable; + +import org.apache.commons.lang.Validate; +import org.joda.time.LocalDate; +import org.navalplanner.business.orders.entities.Order; +import org.navalplanner.business.resources.entities.Criterion; +import org.navalplanner.business.resources.entities.Resource; +import org.navalplanner.web.planner.order.PlanningStateCreator.PlanningState; + +public class ResourceLoadParameters { + + private PlanningState planningState; + + private boolean filterByResources = true; + + /** + * Contains the resources to be shown when specified manually using the + * Bandbox + */ + private List resourcesToShowList = new ArrayList(); + + /** + * Contains the criteria to be shown when specified manually using the + * Bandbox + */ + private List criteriaToShowList = new ArrayList(); + + private LocalDate initDateFilter; + + private LocalDate endDateFilter; + + private int pageFilterPosition = 0; + private int pageSize = 10; + + public ResourceLoadParameters(PlanningState planningState) { + this.planningState = planningState; + } + + public PlanningState getPlanningState() { + return planningState; + } + + public void setEndDateFilter(LocalDate value) { + endDateFilter = value; + } + + public void setInitDateFilter(LocalDate value) { + initDateFilter = value; + } + + public LocalDate getEndDateFilter() { + return endDateFilter; + } + + public LocalDate getInitDateFilter() { + return initDateFilter; + } + + public boolean thereIsCurrentOrder() { + return planningState != null; + } + + public Order getCurrentOrder() { + Validate.isTrue(thereIsCurrentOrder()); + return planningState.getOrder(); + } + + public void setResourcesToShow(List resourcesList) { + this.resourcesToShowList.clear(); + this.resourcesToShowList.addAll(Resource.sortByName(resourcesList)); + } + + public void clearResourcesToShow() { + resourcesToShowList.clear(); + } + + public void clearCriteriaToShow() { + criteriaToShowList.clear(); + } + + public void setCriteriaToShow(List criteriaList) { + criteriaToShowList.clear(); + criteriaToShowList.addAll(criteriaList); + } + + public Paginator getEntities(Class type, + Callable> allEntities, IReattacher reattacher) { + Validate.isTrue( + type.equals(Resource.class) || type.equals(Criterion.class), + "only " + Resource.class.getSimpleName() + " and " + + Criterion.class.getSimpleName() + " supported"); + if (type.equals(Resource.class)) { + return buildPaginator(listOfType(type, resourcesToShowList), + allEntities, reattacher); + } else { + return buildPaginator(listOfType(type, criteriaToShowList), + allEntities, reattacher); + } + } + + private List listOfType(Class klass, Collection objects) { + List result = new ArrayList(); + for (Object each : objects) { + result.add(klass.cast(each)); + } + return result; + } + + private Paginator buildPaginator(List selected, + Callable> all, + IReattacher reattacher) { + if (selected == null || selected.isEmpty()) { + return paginateAll(all); + } + List reattached = reattach(selected, reattacher); + return new Paginator(reattached, pageSize, reattached); + } + + private Paginator paginateAll(Callable> allCallable) { + List allEntities = call(allCallable); + if (pageFilterPosition == -1) { + return new Paginator(allEntities, pageSize, allEntities); + } + List page = allEntities.subList(pageFilterPosition, + Math.min(pageFilterPosition + pageSize, allEntities.size())); + return new Paginator(page, pageSize, allEntities); + } + + private static T call(Callable all) { + try { + return all.call(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private List reattach(List list, IReattacher reattacher) { + List result = new ArrayList(); + for (T each : list) { + result.add(reattacher.reattach(each)); + } + return result; + } + + public interface IReattacher { + T reattach(T entity); + } + + public static class Paginator { + + private final List forCurrentPage; + + private final int pageSize; + + private final List allEntities; + + private Paginator(List forCurrentPage, int pageSize, + List allEntities) { + this.forCurrentPage = forCurrentPage; + this.pageSize = pageSize; + this.allEntities = allEntities; + } + + public List getForCurrentPage() { + return forCurrentPage; + } + + public List getAll() { + return allEntities; + } + + public int getPageSize() { + return pageSize; + } + } + + public int getPageFilterPosition() { + return pageFilterPosition; + } + + public void setPageFilterPosition(int pageFilterPosition) { + this.pageFilterPosition = pageFilterPosition; + } + + public void setFilterByResources(boolean filterByResources) { + this.filterByResources = filterByResources; + } + + public boolean isFilterByResources() { + return filterByResources; + } + +}