org.libreplan.web.planner.consolidations.AdvanceConsolidationModel.java Source code

Java tutorial

Introduction

Here is the source code for org.libreplan.web.planner.consolidations.AdvanceConsolidationModel.java

Source

/*
 * This file is part of LibrePlan
 *
 * Copyright (C) 2009-2010 Fundacin para o Fomento da Calidade Industrial e
 *                         Desenvolvemento Tecnolxico de Galicia
 * Copyright (C) 2010-2012 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.web.planner.consolidations;

import static org.libreplan.web.I18nHelper._;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;

import org.joda.time.LocalDate;
import org.libreplan.business.advance.entities.AdvanceMeasurement;
import org.libreplan.business.advance.entities.DirectAdvanceAssignment;
import org.libreplan.business.advance.entities.IndirectAdvanceAssignment;
import org.libreplan.business.orders.daos.IOrderElementDAO;
import org.libreplan.business.orders.entities.OrderElement;
import org.libreplan.business.planner.daos.ITaskElementDAO;
import org.libreplan.business.planner.entities.ResourceAllocation;
import org.libreplan.business.planner.entities.ResourceAllocation.AllocationsSpecified;
import org.libreplan.business.planner.entities.ResourceAllocation.DetachDayAssignmentOnRemoval;
import org.libreplan.business.planner.entities.Task;
import org.libreplan.business.planner.entities.TaskElement;
import org.libreplan.business.planner.entities.consolidations.CalculatedConsolidatedValue;
import org.libreplan.business.planner.entities.consolidations.CalculatedConsolidation;
import org.libreplan.business.planner.entities.consolidations.ConsolidatedValue;
import org.libreplan.business.planner.entities.consolidations.Consolidation;
import org.libreplan.business.planner.entities.consolidations.NonCalculatedConsolidatedValue;
import org.libreplan.business.planner.entities.consolidations.NonCalculatedConsolidation;
import org.libreplan.business.workingday.EffortDuration;
import org.libreplan.business.workingday.IntraDayDate;
import org.libreplan.web.planner.order.PlanningStateCreator.PlanningState;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.zkoss.ganttz.extensions.IContextWithPlannerTask;

/**
 * Model for UI operations related to {@link Task}.
 *
 * @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
 */
@Service
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class AdvanceConsolidationModel implements IAdvanceConsolidationModel {

    @Autowired
    private ITaskElementDAO taskElementDAO;

    @Autowired
    private IOrderElementDAO orderElementDAO;

    private Task task;

    private IContextWithPlannerTask<TaskElement> context;

    private Consolidation consolidation;

    private DirectAdvanceAssignment spreadAdvance;

    private boolean isUnitType = false;

    private OrderElement orderElement;

    private List<AdvanceConsolidationDTO> consolidationDTOs = new ArrayList<>();

    private void initConsolidatedDates() {
        consolidationDTOs = AdvanceConsolidationDTO.sortByDate(getConsolidationDTOs());
        initLastConsolidatedDate();
        initLastConsolidatedAndSavedDate();
    }

    private boolean containsAdvance(AdvanceMeasurement advanceMeasurement) {
        for (AdvanceConsolidationDTO dto : consolidationDTOs) {
            if (dto.getDate().compareTo(advanceMeasurement.getDate().toDateTimeAtStartOfDay().toDate()) == 0) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void initLastConsolidatedDate() {
        // Init the lastConsolidatedDate
        LocalDate consolidatedUntil = (task.getConsolidation() == null) ? null
                : task.getConsolidation().getConsolidatedUntil();

        AdvanceConsolidationDTO.lastConsolidatedDate = (consolidatedUntil == null) ? null
                : consolidatedUntil.toDateTimeAtStartOfDay().toDate();
    }

    private void initLastConsolidatedAndSavedDate() {
        // Init the lastConsolidatedAndSaveDate
        int i = 0;
        AdvanceConsolidationDTO.lastConsolidatedAndSavedDate = null;
        while ((i < consolidationDTOs.size()) && (!consolidationDTOs.get(i).isSavedConsolidatedValue())) {
            i++;
        }

        if (i < consolidationDTOs.size()) {
            AdvanceConsolidationDTO.lastConsolidatedAndSavedDate = consolidationDTOs.get(i).getDate();
        }
    }

    @Override
    public void cancel() {
    }

    @Override
    @Transactional(readOnly = true)
    public void accept() {
        if (context != null && orderElement != null && isVisibleAdvances()) {
            org.zkoss.ganttz.data.Task ganttTask = context.getTask();

            createConsolidationIfNeeded();

            for (AdvanceConsolidationDTO dto : consolidationDTOs) {
                if (dto.isConsolidated()) {
                    addConsolidationIfIsNeeded(dto);
                } else {
                    deleteConsolidationIfIsNeeded(dto);
                }
            }

            updateConsolidationInAdvanceIfIsNeeded();

            ganttTask.enforceDependenciesDueToPositionPotentiallyModified();
            context.reloadCharts();
        }
    }

    private void createConsolidationIfNeeded() {
        if (consolidation == null && task != null) {
            if (advanceIsCalculated()) {
                IndirectAdvanceAssignment indirectAdvanceAssignment = getIndirectAdvanceAssignment();
                consolidation = CalculatedConsolidation.create(task, indirectAdvanceAssignment);
            } else {
                consolidation = NonCalculatedConsolidation.create(task, spreadAdvance);
            }
            task.setConsolidation(consolidation);
        }
    }

    private IndirectAdvanceAssignment getIndirectAdvanceAssignment() {
        if (orderElement != null) {
            Set<IndirectAdvanceAssignment> indirects = orderElement.getIndirectAdvanceAssignments();
            for (IndirectAdvanceAssignment indirectAdvanceAssignment : indirects) {
                if (indirectAdvanceAssignment.getReportGlobalAdvance()) {
                    return indirectAdvanceAssignment;
                }
            }
        }
        return null;
    }

    private void addConsolidationIfIsNeeded(AdvanceConsolidationDTO dto) {
        if (dto.getConsolidatedValue() == null) {
            ConsolidatedValue consolidatedValue = createNewConsolidatedValue(dto);
            dto.setConsolidatedValue(consolidatedValue);
        }
        addConsolidatedValue(dto.getConsolidatedValue());
    }

    private void addConsolidatedValue(ConsolidatedValue value) {
        if (consolidation == null || task == null || consolidation.getConsolidatedValues().contains(value)) {
            return;
        }
        if (!consolidation.isCalculated()) {
            ((NonCalculatedConsolidation) consolidation)
                    .addConsolidatedValue((NonCalculatedConsolidatedValue) value);
        } else {
            ((CalculatedConsolidation) consolidation).addConsolidatedValue((CalculatedConsolidatedValue) value);
        }

        task.updateAssignmentsConsolidatedValues();

        Set<ResourceAllocation<?>> allResourceAllocations = task.getAllResourceAllocations();
        withDetachOnDayAssignmentRemoval(allResourceAllocations);

        IntraDayDate end = task.getIntraDayEndDate();
        if (value.getDate().compareTo(end.getDate().minusDays(1)) >= 0) {
            reassignExpandingTask(allResourceAllocations);
        } else {
            reassignAll(task.getIntraDayStartDate(), end, allResourceAllocations);
        }

        resetIntendedResourcesPerDayWithNonConsolidated(allResourceAllocations);
    }

    private void resetIntendedResourcesPerDayWithNonConsolidated(
            Set<ResourceAllocation<?>> allResourceAllocations) {
        for (ResourceAllocation<?> resourceAllocation : allResourceAllocations) {
            resourceAllocation.resetIntendedIntendedResourcesPerDayWithNonConsolidated();
        }
    }

    private void withDetachOnDayAssignmentRemoval(Collection<? extends ResourceAllocation<?>> allocations) {
        for (ResourceAllocation<?> each : allocations) {
            each.setOnDayAssignmentRemoval(new DetachDayAssignmentOnRemoval());
        }
    }

    private void reassignAll(IntraDayDate start, IntraDayDate end,
            Collection<? extends ResourceAllocation<?>> allocations) {

        for (ResourceAllocation<?> each : allocations) {
            EffortDuration pendingEffort = consolidation.getNotConsolidated(each.getIntendedTotalAssignment());
            reassign(each, start, end, pendingEffort);
        }
    }

    private void reassign(ResourceAllocation<?> resourceAllocation, IntraDayDate start, IntraDayDate end,
            EffortDuration pendingEffort) {

        resourceAllocation.withPreviousAssociatedResources().onInterval(start, end).allocate(pendingEffort);
    }

    private void reassignExpandingTask(Collection<? extends ResourceAllocation<?>> allResourceAllocations) {

        List<IntraDayDate> ends = new ArrayList<>();
        for (ResourceAllocation<?> resourceAllocation : allResourceAllocations) {
            if (!AllocationsSpecified
                    .isZero(resourceAllocation.asResourcesPerDayModification().getGoal().getAmount())) {

                EffortDuration pendingEffort = consolidation
                        .getNotConsolidated(resourceAllocation.getIntendedTotalAssignment());

                IntraDayDate date = ResourceAllocation
                        .allocating(Collections.singletonList(resourceAllocation.asResourcesPerDayModification()))
                        .untilAllocating(pendingEffort);

                ends.add(date);
            }
        }
        if (!ends.isEmpty()) {
            task.setIntraDayEndDate(Collections.max(ends));
        }
    }

    private ConsolidatedValue createNewConsolidatedValue(AdvanceConsolidationDTO dto) {
        if (consolidation != null && task != null) {

            if (consolidation.isCalculated()) {

                return CalculatedConsolidatedValue.create(LocalDate.fromDateFields(dto.getDate()),
                        dto.getPercentage(), task.getIntraDayEndDate());
            } else {
                AdvanceMeasurement measure = dto.getAdvanceMeasurement();

                NonCalculatedConsolidatedValue consolidatedValue = NonCalculatedConsolidatedValue.create(
                        LocalDate.fromDateFields(dto.getDate()), dto.getPercentage(), measure,
                        task.getIntraDayEndDate());

                measure.getNonCalculatedConsolidatedValues().add(consolidatedValue);
                return consolidatedValue;
            }
        }
        return null;
    }

    private void deleteConsolidationIfIsNeeded(AdvanceConsolidationDTO dto) {
        if (dto.getConsolidatedValue() == null || consolidation == null || task == null) {
            return;
        }

        if (!consolidation.getConsolidatedValues().isEmpty()) {
            IntraDayDate endExclusive = consolidation.getConsolidatedValues().last().getTaskEndDate();
            task.setIntraDayEndDate(endExclusive);
        }
        if (!consolidation.isCalculated()) {

            ((NonCalculatedConsolidation) consolidation).getNonCalculatedConsolidatedValues()
                    .remove(dto.getConsolidatedValue());

            dto.getAdvanceMeasurement().getNonCalculatedConsolidatedValues().remove(dto.getConsolidatedValue());
        } else {
            ((CalculatedConsolidation) consolidation).getCalculatedConsolidatedValues()
                    .remove(dto.getConsolidatedValue());
        }

        task.updateAssignmentsConsolidatedValues();

        Set<ResourceAllocation<?>> allResourceAllocations = task.getAllResourceAllocations();
        withDetachOnDayAssignmentRemoval(allResourceAllocations);

        reassignAll(task.getIntraDayStartDate(), task.getIntraDayEndDate(), allResourceAllocations);

        resetIntendedResourcesPerDayWithNonConsolidated(allResourceAllocations);
    }

    private void updateConsolidationInAdvanceIfIsNeeded() {
        if (consolidation != null) {
            if (consolidation.isEmpty()) {
                removeConsolidationInAdvance();
            } else {
                addConsolidationInAdvance();
            }
        }
    }

    private void removeConsolidationInAdvance() {
        if (advanceIsCalculated()) {
            IndirectAdvanceAssignment indirectAdvanceAssignment = getIndirectAdvanceAssignment();
            indirectAdvanceAssignment.getCalculatedConsolidation().remove(consolidation);
            ((CalculatedConsolidation) consolidation).setIndirectAdvanceAssignment(null);
        } else {
            spreadAdvance.getNonCalculatedConsolidation().remove(consolidation);
            ((NonCalculatedConsolidation) consolidation).setDirectAdvanceAssignment(null);
        }
    }

    private void addConsolidationInAdvance() {
        if (advanceIsCalculated()) {
            IndirectAdvanceAssignment indirectAdvanceAssignment = getIndirectAdvanceAssignment();
            if (!indirectAdvanceAssignment.getCalculatedConsolidation().contains(consolidation)) {
                indirectAdvanceAssignment.getCalculatedConsolidation().add((CalculatedConsolidation) consolidation);
                ((CalculatedConsolidation) consolidation).setIndirectAdvanceAssignment(indirectAdvanceAssignment);
            }
        } else {
            if (!spreadAdvance.getNonCalculatedConsolidation().contains(consolidation)) {
                spreadAdvance.getNonCalculatedConsolidation().add((NonCalculatedConsolidation) consolidation);
                ((NonCalculatedConsolidation) consolidation).setDirectAdvanceAssignment(spreadAdvance);
            }
        }
    }

    @Override
    @Transactional(readOnly = true)
    public void initAdvancesFor(Task task, IContextWithPlannerTask<TaskElement> context,
            PlanningState planningState) {
        this.context = context;
        initTask(task);
        initOrderElement();
        initConsolidation();
        initAdvanceConsolidationsDTOs();
    }

    private void initTask(Task task) {
        this.task = task;
        taskElementDAO.reattach(this.task);
        orderElement = task.getOrderElement();
        orderElementDAO.reattach(orderElement);
    }

    private void initOrderElement() {
        spreadAdvance = orderElement.getReportGlobalAdvanceAssignment();
        initSpreadAdvance();
    }

    private void initConsolidation() {
        consolidation = task.getConsolidation();
        if (consolidation != null) {
            consolidation.getConsolidatedValues().size();
        }
    }

    private void initAdvanceConsolidationsDTOs() {
        if (spreadAdvance != null) {
            isUnitType = !spreadAdvance.getAdvanceType().getPercentage();
            createAdvanceConsolidationDTOs();
            initConsolidatedDates();
            addNonConsolidatedAdvances();
            setReadOnlyConsolidations();
        }
    }

    private void initSpreadAdvance() {
        if (spreadAdvance != null) {
            if (advanceIsCalculated()) {
                IndirectAdvanceAssignment indirectAdvanceAssignment = getIndirectAdvanceAssignment();
                indirectAdvanceAssignment.getCalculatedConsolidation().size();
            } else {
                spreadAdvance.getNonCalculatedConsolidation().size();
                initAdvanceMeasurements(spreadAdvance.getAdvanceMeasurements());
            }
        }
    }

    private void initAdvanceMeasurements(Set<AdvanceMeasurement> measures) {
        for (AdvanceMeasurement measure : measures) {
            measure.getNonCalculatedConsolidatedValues().size();
        }
    }

    private void createAdvanceConsolidationDTOs() {
        consolidationDTOs = new ArrayList<>();
        if (consolidation != null) {
            if (!consolidation.isCalculated()) {

                SortedSet<NonCalculatedConsolidatedValue> nonCalculatedConsolidatedValues = ((NonCalculatedConsolidation) consolidation)
                        .getNonCalculatedConsolidatedValues();

                for (NonCalculatedConsolidatedValue consolidatedValue : nonCalculatedConsolidatedValues) {

                    consolidationDTOs.add(new AdvanceConsolidationDTO(consolidatedValue.getAdvanceMeasurement(),
                            consolidatedValue));
                }
            } else {

                SortedSet<CalculatedConsolidatedValue> calculatedConsolidatedValuestedValues = ((CalculatedConsolidation) consolidation)
                        .getCalculatedConsolidatedValues();

                for (CalculatedConsolidatedValue consolidatedValue : calculatedConsolidatedValuestedValues) {
                    consolidationDTOs.add(new AdvanceConsolidationDTO(null, consolidatedValue));
                }
            }
        }
    }

    private void addNonConsolidatedAdvances() {
        for (AdvanceMeasurement advance : getAdvances()) {
            if (canBeConsolidateAndShow(advance)) {
                consolidationDTOs.add(new AdvanceConsolidationDTO(advance));
            }
        }
        consolidationDTOs = AdvanceConsolidationDTO.sortByDate(consolidationDTOs);
    }

    private boolean canBeConsolidateAndShow(AdvanceMeasurement advanceMeasurement) {
        return AdvanceConsolidationDTO
                .canBeConsolidateAndShow(advanceMeasurement.getDate().toDateTimeAtStartOfDay().toDate())
                && !containsAdvance(advanceMeasurement);
    }

    @Override
    public String getInfoAdvanceAssignment() {
        return this.spreadAdvance == null || this.orderElement == null ? ""
                : getInfoAdvanceAssignment(this.spreadAdvance);
    }

    private String getInfoAdvanceAssignment(DirectAdvanceAssignment assignment) {
        return assignment == null || assignment.getMaxValue() == null ? ""
                : _("( max: {0} )", assignment.getMaxValue());
    }

    private List<AdvanceMeasurement> getAdvances() {
        return spreadAdvance != null ? new ArrayList<>(spreadAdvance.getAdvanceMeasurements()) : new ArrayList<>();
    }

    @Override
    public boolean isVisibleAdvances() {
        return !isVisibleMessages();
    }

    @Override
    public boolean isVisibleMessages() {
        return getAdvances().isEmpty() || isSubcontracted() || !hasResourceAllocation();
    }

    private boolean advanceIsCalculated() {
        return spreadAdvance != null && spreadAdvance.isFake();
    }

    public String infoMessages() {
        return !getAdvances().isEmpty() ? _("Progress cannot be consolidated.")
                : _("There is not any assigned progress to current task");
    }

    public void setConsolidationDTOs(List<AdvanceConsolidationDTO> consolidationDTOs) {
        this.consolidationDTOs = consolidationDTOs;
    }

    public List<AdvanceConsolidationDTO> getConsolidationDTOs() {
        return spreadAdvance != null && orderElement != null ? consolidationDTOs : new ArrayList<>();
    }

    private boolean hasResourceAllocation() {
        return task != null && task.hasResourceAllocations();
    }

    private boolean isSubcontracted() {
        return task != null && task.isSubcontracted();
    }

    public boolean hasLimitingResourceAllocation() {
        return task != null && task.hasLimitedResourceAllocation();
    }

    @Override
    public void setReadOnlyConsolidations() {
        // Set all advance consolidations as read only
        AdvanceConsolidationDTO.setAllReadOnly(hasLimitingResourceAllocation());
    }

    public boolean isUnitType() {
        return this.isUnitType;
    }

}