/* * This file is part of LibrePlan * * Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e * Desenvolvemento Tecnolóxico de Galicia * Copyright (C) 2010-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 <http://www.gnu.org/licenses/>. */ package org.libreplan.business.hibernate.notification; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import java.util.concurrent.Callable; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.joda.time.LocalDate; import org.libreplan.business.advance.entities.DirectAdvanceAssignment; import org.libreplan.business.calendars.entities.CalendarAvailability; import org.libreplan.business.calendars.entities.CalendarData; import org.libreplan.business.calendars.entities.CalendarException; import org.libreplan.business.common.AdHocTransactionService; import org.libreplan.business.common.IAdHocTransactionService; import org.libreplan.business.costcategories.daos.ICostCategoryDAO; import org.libreplan.business.costcategories.entities.CostCategory; import org.libreplan.business.externalcompanies.daos.IExternalCompanyDAO; import org.libreplan.business.externalcompanies.entities.ExternalCompany; import org.libreplan.business.labels.daos.ILabelDAO; import org.libreplan.business.labels.daos.ILabelTypeDAO; import org.libreplan.business.labels.entities.Label; import org.libreplan.business.labels.entities.LabelType; import org.libreplan.business.orders.daos.IOrderDAO; import org.libreplan.business.orders.entities.Order; import org.libreplan.business.planner.chart.ResourceLoadChartData; import org.libreplan.business.planner.daos.IDayAssignmentDAO; import org.libreplan.business.planner.daos.ITaskElementDAO; import org.libreplan.business.planner.entities.DayAssignment; import org.libreplan.business.planner.entities.GenericResourceAllocation; import org.libreplan.business.planner.entities.ICostCalculator; import org.libreplan.business.planner.entities.ResourceAllocation; import org.libreplan.business.planner.entities.SpecificResourceAllocation; import org.libreplan.business.planner.entities.Task; import org.libreplan.business.planner.entities.TaskElement; import org.libreplan.business.planner.entities.TaskGroup; import org.libreplan.business.resources.daos.ICriterionDAO; import org.libreplan.business.resources.daos.ICriterionTypeDAO; import org.libreplan.business.resources.daos.IResourceDAO; import org.libreplan.business.resources.daos.IWorkerDAO; import org.libreplan.business.resources.entities.Criterion; import org.libreplan.business.resources.entities.CriterionType; import org.libreplan.business.resources.entities.Machine; import org.libreplan.business.resources.entities.Resource; import org.libreplan.business.resources.entities.VirtualWorker; import org.libreplan.business.resources.entities.Worker; import org.libreplan.business.scenarios.IScenarioManager; import org.libreplan.business.workreports.daos.IWorkReportLineDAO; import org.libreplan.business.workreports.entities.WorkReportLine; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; /** * @author Óscar González Fernández * @author Vova Perebykivskyi <vova@libreplan-enterprise.com> */ @Component @Scope(BeanDefinition.SCOPE_SINGLETON) public class PredefinedDatabaseSnapshots { private static final Log LOG = LogFactory.getLog(PredefinedDatabaseSnapshots.class); @Autowired private IAdHocTransactionService transactionService; @Autowired private ISnapshotRefresherService snapshotRefresherService; @Autowired private ICriterionTypeDAO criterionTypeDAO; @Autowired private ICriterionDAO criterionDAO; @Autowired private ILabelTypeDAO labelTypeDAO; @Autowired private ILabelDAO labelDAO; @Autowired private IWorkerDAO workerDAO; @Autowired private ICostCategoryDAO costCategoryDAO; @Autowired private IResourceDAO resourceDAO; @Autowired private IExternalCompanyDAO externalCompanyDAO; @Autowired private IOrderDAO orderDAO; @Autowired private IDayAssignmentDAO dayAssignmentDAO; @Autowired private IScenarioManager scenarioManager; @Autowired private IWorkReportLineDAO workReportLineDAO; @Autowired private ICostCalculator hoursCostCalculator; @Autowired private ITaskElementDAO taskElementDAO; private IAutoUpdatedSnapshot<SortedMap<CriterionType, List<Criterion>>> criterionsMap; private IAutoUpdatedSnapshot<Map<LabelType, List<Label>>> labelsMap; private IAutoUpdatedSnapshot<List<Worker>> listWorkers; private IAutoUpdatedSnapshot<List<CostCategory>> listCostCategories; private IAutoUpdatedSnapshot<List<Criterion>> listCriterion; private IAutoUpdatedSnapshot<Map<Class<?>, List<Resource>>> mapResources; private IAutoUpdatedSnapshot<List<ExternalCompany>> externalCompanies; private IAutoUpdatedSnapshot<List<String>> customerReferences; private IAutoUpdatedSnapshot<List<String>> ordersCodes; private IAutoUpdatedSnapshot<ResourceLoadChartData> resourceLoadChartData; private IAutoUpdatedSnapshot<List<WorkReportLine>> workReportLines; private IAutoUpdatedSnapshot<Map<TaskElement,SortedMap<LocalDate, BigDecimal>>> estimatedCostPerTask; private IAutoUpdatedSnapshot<Map<TaskElement,SortedMap<LocalDate, BigDecimal>>> advanceCostPerTask; private boolean snapshotsRegistered = false; public SortedMap<CriterionType, List<Criterion>> snapshotCriterionsMap() { return criterionsMap.getValue(); } public Map<LabelType, List<Label>> snapshotLabelsMap() { return labelsMap.getValue(); } public List<Worker> snapshotListWorkers() { return listWorkers.getValue(); } public List<CostCategory> snapshotListCostCategories() { return listCostCategories.getValue(); } public List<Criterion> snapshotListCriterion() { return listCriterion.getValue(); } public Map<Class<?>, List<Resource>> snapshotMapResources() { return mapResources.getValue(); } public List<ExternalCompany> snapshotExternalCompanies() { return externalCompanies.getValue(); } public List<String> snapshotCustomerReferences() { return customerReferences.getValue(); } public List<String> snapshotOrdersCodes() { return ordersCodes.getValue(); } public ResourceLoadChartData snapshotResourceLoadChartData() { return resourceLoadChartData.getValue(); } public List<WorkReportLine> snapshotWorkReportLines() { return workReportLines.getValue(); } public Map<TaskElement,SortedMap<LocalDate, BigDecimal>> snapshotEstimatedCostPerTask() { return estimatedCostPerTask.getValue(); } public Map<TaskElement,SortedMap<LocalDate, BigDecimal>> snapshotAdvanceCostPerTask() { return advanceCostPerTask.getValue(); } public void registerSnapshots() { if ( snapshotsRegistered ) { LOG.warn("snapshots have already been registered"); return; } snapshotsRegistered = true; criterionsMap = snapshot("criterions map", calculateCriterionsMap(), CriterionType.class, Criterion.class); labelsMap = snapshot("labels map", calculateLabelsMap(), LabelType.class, Label.class); listWorkers = snapshot("workers", calculateWorkers(), Worker.class); listCostCategories = snapshot("list cost categories", calculateListCostCategories(), CostCategory.class); listCriterion = snapshot("list criterions", calculateListCriterion(), Criterion.class); mapResources = snapshot( "map resources", calculateMapResources(), Resource.class, Worker.class, Machine.class, VirtualWorker.class); externalCompanies = snapshot("external companies", calculateExternalCompanies(), ExternalCompany.class); customerReferences = snapshot("customer references", calculateCustomerReferences(), Order.class); ordersCodes = snapshot("order codes", calculateOrdersCodes(), Order.class); resourceLoadChartData = snapshot( "resource load grouped by date", calculateResourceLoadChartData(), CalendarAvailability.class, CalendarException.class, CalendarData.class, TaskElement.class, SpecificResourceAllocation.class, GenericResourceAllocation.class, ResourceAllocation.class); workReportLines = snapshot("work report lines", calculateWorkReportLines(), WorkReportLine.class); estimatedCostPerTask = snapshot( "estimated cost per task", calculateEstimatedCostPerTask(), TaskElement.class, Task.class, TaskGroup.class, DayAssignment.class); advanceCostPerTask = snapshot( "advance cost per task", calculateAdvanceCostPerTask(), TaskElement.class, Task.class, TaskGroup.class, DirectAdvanceAssignment.class); } private <T> IAutoUpdatedSnapshot<T> snapshot(String name, Callable<T> callable, Class<?>... reloadOnChangesOf) { return snapshotRefresherService .takeSnapshot(name, callableOnReadOnlyTransaction(callable), ReloadOn.onChangeOf(reloadOnChangesOf)); } @SuppressWarnings("unchecked") private <T> Callable<T> callableOnReadOnlyTransaction(Callable<T> callable) { return AdHocTransactionService.readOnlyProxy(transactionService, Callable.class, callable); } private Callable<SortedMap<CriterionType, List<Criterion>>> calculateCriterionsMap() { return () -> { SortedMap<CriterionType, List<Criterion>> result = new TreeMap<>(getComparatorByName()); for (CriterionType criterionType : criterionTypeDAO.getSortedCriterionTypes()) { if ( criterionType.isEnabled() ) { List<Criterion> criterions = criterionType.getSortCriterions(); result.put(criterionType, criterions); } } return result; }; } private Comparator<CriterionType> getComparatorByName(){ return (arg0, arg1) -> arg0.getName().compareTo(arg1.getName()); } private Callable<Map<LabelType, List<Label>>> calculateLabelsMap() { return () -> { Map<LabelType, List<Label>> result = new HashMap<>(); for (LabelType labelType : labelTypeDAO.getAll()) { List<Label> labels = new ArrayList<>(labelDAO.findByType(labelType)); result.put(labelType, labels); } return result; }; } private Callable<List<Worker>> calculateWorkers() { return () -> workerDAO.getAll(); } private Callable<List<CostCategory>> calculateListCostCategories() { return () -> costCategoryDAO.findActive(); } private Callable<List<Criterion>> calculateListCriterion() { return criterionDAO::getAll; } private Callable<Map<Class<?>, List<Resource>>> calculateMapResources() { return () -> { Map<Class<?>, List<Resource>> result = new HashMap<>(); result.put(Worker.class, Resource.sortByName(new ArrayList<>(resourceDAO.getRealWorkers()))); result.put(Machine.class, Resource.sortByName(new ArrayList<>(resourceDAO.getMachines()))); result.put(VirtualWorker.class, Resource.sortByName(new ArrayList<>(resourceDAO.getVirtualWorkers()))); return result; }; } private Callable<List<ExternalCompany>> calculateExternalCompanies() { return () -> externalCompanyDAO.getExternalCompaniesAreClient(); } private Callable<List<String>> calculateCustomerReferences() { return () -> { List<String> result = new ArrayList<>(); for (Order order : orderDAO.getOrdersWithNotEmptyCustomersReferences()) { result.add(order.getCustomerReference()); } return result; }; } private Callable<List<String>> calculateOrdersCodes() { return () -> { List<String> result = new ArrayList<>(); for (Order order : orderDAO.getOrders()) { result.add(order.getCode()); } return result; }; } private Callable<ResourceLoadChartData> calculateResourceLoadChartData() { return () -> { List<DayAssignment> dayAssignments = dayAssignmentDAO.getAllFor(scenarioManager.getCurrent(), null, null); List<Resource> resources = resourceDAO.list(Resource.class); return new ResourceLoadChartData(dayAssignments, resources); }; } private Callable<List<WorkReportLine>> calculateWorkReportLines() { return () -> workReportLineDAO.list(WorkReportLine.class); } private Callable<Map<TaskElement, SortedMap<LocalDate, BigDecimal>>> calculateEstimatedCostPerTask() { return () -> { Map<TaskElement, SortedMap<LocalDate, BigDecimal>> map = new HashMap<>(); taskElementDAO. list(TaskElement.class) .stream() .filter(task -> task instanceof Task) .forEach(task -> map.put(task, hoursCostCalculator.getEstimatedCost((Task) task))); return map; }; } private Callable<Map<TaskElement, SortedMap<LocalDate, BigDecimal>>> calculateAdvanceCostPerTask() { return () -> { Map<TaskElement, SortedMap<LocalDate, BigDecimal>> map = new HashMap<>(); for (TaskElement task : taskElementDAO.list(TaskElement.class)) { if ( task instanceof Task ) { map.put(task, hoursCostCalculator.getAdvanceCost((Task)task)); } } return map; }; } }