Package org.libreplan.business.planner.entities

Source Code of org.libreplan.business.planner.entities.TaskElement$IDatesHandler

/*
* 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-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.business.planner.entities;

import static java.util.Arrays.asList;
import static org.libreplan.business.workingday.EffortDuration.zero;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.Validate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.validation.constraints.NotNull;
import org.joda.time.LocalDate;
import org.libreplan.business.calendars.entities.BaseCalendar;
import org.libreplan.business.common.BaseEntity;
import org.libreplan.business.common.entities.ProgressType;
import org.libreplan.business.externalcompanies.entities.ExternalCompany;
import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.orders.entities.OrderElement;
import org.libreplan.business.orders.entities.OrderStatusEnum;
import org.libreplan.business.orders.entities.TaskSource;
import org.libreplan.business.planner.entities.DayAssignment.FilterType;
import org.libreplan.business.planner.entities.Dependency.Type;
import org.libreplan.business.resources.daos.IResourcesSearcher;
import org.libreplan.business.scenarios.entities.Scenario;
import org.libreplan.business.util.TaskElementVisitor;
import org.libreplan.business.util.deepcopy.OnCopy;
import org.libreplan.business.util.deepcopy.Strategy;
import org.libreplan.business.workingday.EffortDuration;
import org.libreplan.business.workingday.IntraDayDate;
import org.libreplan.business.workingday.ResourcesPerDay;

/**
* @author Óscar González Fernández <ogonzalez@igalia.com>
* @author Manuel Rego Casasnovas <rego@igalia.com>
*/
public abstract class TaskElement extends BaseEntity {

    private static final Log LOG = LogFactory.getLog(TaskElement.class);

    public static List<Task> justTasks(Collection<? extends TaskElement> tasks) {
        List<Task> result = new ArrayList<Task>();
        for (TaskElement taskElement : tasks) {
            if (taskElement instanceof Task) {
                result.add((Task) taskElement);
            }
        }
        return result;
    }

    public interface IDatesInterceptor {
        public void setStartDate(IntraDayDate previousStart,
                IntraDayDate previousEnd, IntraDayDate newStart);

        public void setNewEnd(IntraDayDate previousEnd, IntraDayDate newEnd);
    }

    private static final IDatesInterceptor EMPTY_INTERCEPTOR = new IDatesInterceptor() {

        @Override
        public void setStartDate(IntraDayDate previousStart,
                IntraDayDate previousEnd, IntraDayDate newStart) {
        }

        @Override
        public void setNewEnd(IntraDayDate previousEnd, IntraDayDate newEnd) {
        }

    };

    public static Comparator<TaskElement> getByStartDateComparator() {
        Comparator<TaskElement> result = new Comparator<TaskElement>() {

            @Override
            public int compare(TaskElement o1, TaskElement o2) {
                return o1.getStartDate().compareTo(o2.getStartDate());
            }
        };
        return result;
    }

    public static Comparator<? super TaskElement> getByEndAndDeadlineDateComparator() {
        return new Comparator<TaskElement>() {

            @Override
            public int compare(TaskElement o1, TaskElement o2) {
                return o1.getBiggestAmongEndOrDeadline().compareTo(
                        o2.getBiggestAmongEndOrDeadline());
            }

        };
    }

    /**
     * @returns the biggest one among the deadline (if exists) or the end date.
     */
    @SuppressWarnings("unchecked")
    public LocalDate getBiggestAmongEndOrDeadline() {
        if (this.getDeadline() != null) {
            return Collections.max(asList(this.getDeadline(),
                    this.getEndAsLocalDate()));
        }
        return this.getEndAsLocalDate();
    }

    protected static <T extends TaskElement> T create(T taskElement,
            TaskSource taskSource) {
        taskElement.setTaskSource(taskSource);
        taskElement.updateDeadlineFromOrderElement();
        taskElement.setName(taskElement.getOrderElement().getName());
        taskElement.updateAdvancePercentageFromOrderElement();
        Order order = taskElement.getOrderElement().getOrder();
        if (order.isScheduleBackwards()) {
            taskElement.setEndDate(order.getDeadline());
        } else {
            taskElement.setStartDate(order.getInitDate());
        }
        return create(taskElement);
    }

    protected static <T extends TaskElement> T createWithoutTaskSource(
            T taskElement) {
        return create(taskElement);
    }

    @OnCopy(Strategy.SHARE)
    private IDatesInterceptor datesInterceptor = EMPTY_INTERCEPTOR;

    private IntraDayDate startDate;

    private IntraDayDate endDate;

    private LocalDate deadline;

    private String name;

    private String notes;

    private TaskGroup parent;

    private Set<Dependency> dependenciesWithThisOrigin = new HashSet<Dependency>();

    private Set<Dependency> dependenciesWithThisDestination = new HashSet<Dependency>();

    @OnCopy(Strategy.SHARE)
    private BaseCalendar calendar;

    private TaskSource taskSource;

    private BigDecimal advancePercentage = BigDecimal.ZERO;

    private Boolean simplifiedAssignedStatusCalculationEnabled = false;

    private Boolean updatedFromTimesheets = false;

    public void initializeDatesIfNeeded() {
        if (getIntraDayEndDate() == null || getIntraDayStartDate() == null) {
            initializeDates();
        }
    }

    protected abstract void initializeDates();

    public void updateDeadlineFromOrderElement() {
        Date newDeadline = this.taskSource.getOrderElement().getDeadline();
        setDeadline(newDeadline == null ? null : new LocalDate(newDeadline));
    }

    public void setDatesInterceptor(IDatesInterceptor datesIntercerptor) {
        Validate.notNull(datesIntercerptor);
        this.datesInterceptor = datesIntercerptor;
    }

    public Integer getWorkHours() {
        if (taskSource == null) {
            return 0;
        }
        return taskSource.getTotalHours();
    }

    protected void copyPropertiesFrom(TaskElement task) {
        this.name = task.getName();
        this.notes = task.getNotes();
        this.startDate = task.startDate;
        this.taskSource = task.getTaskSource();
    }

    public TaskSource getTaskSource() {
        return taskSource;
    }

    protected void setTaskSource(TaskSource taskSource) {
        this.taskSource = taskSource;
    }

    protected void copyDependenciesTo(TaskElement result) {
        for (Dependency dependency : getDependenciesWithThisOrigin()) {
            Dependency.create(result, dependency.getDestination(),
                    dependency.getType());
        }
        for (Dependency dependency : getDependenciesWithThisDestination()) {
            Dependency.create(dependency.getOrigin(), result,
                    dependency.getType());
        }
    }

    protected void copyParenTo(TaskElement result) {
        if (this.getParent() != null) {
            this.getParent().addTaskElement(result);
        }
    }

    public TaskGroup getParent() {
        return parent;
    }

    public String getName() {
        return name;
    }

    public String getCode() {
        return getOrderElement().getCode();
    }

    public String getProjectCode() {
        return getOrderElement().getOrder().getCode();
    }

    public void setName(String name) {
        this.name = name;
        if (taskSource != null && taskSource.getOrderElement() != null) {
            taskSource.getOrderElement().setName(name);
        }
    }

    public String getNotes() {
        return notes;
    }

    public void setNotes(String notes) {
        this.notes = notes;
    }

    public OrderElement getOrderElement() {
        if (getTaskSource() == null) {
            return null;
        }
        return getTaskSource().getOrderElement();
    }

    public Set<Dependency> getDependenciesWithThisOrigin() {
        return Collections.unmodifiableSet(dependenciesWithThisOrigin);
    }

    public Set<Dependency> getDependenciesWithThisDestination() {
        return Collections.unmodifiableSet(dependenciesWithThisDestination);
    }

    public Set<Dependency> getDependenciesWithThisDestinationAndAllParents() {
        Set<Dependency> result = new HashSet<Dependency>(
                getDependenciesWithThisDestination());
        if (parent != null) {
            result.addAll(parent
                    .getDependenciesWithThisDestinationAndAllParents());
        }
        return result;
    }

    public Date getStartDate() {
        return startDate != null ? startDate.getDate().toDateTimeAtStartOfDay()
                .toDate() : null;
    }

    @NotNull
    public IntraDayDate getIntraDayStartDate() {
        return startDate;
    }

    public LocalDate getStartAsLocalDate() {
        return startDate == null ? null : startDate.getDate();
    }

    public LocalDate getEndAsLocalDate() {
        return endDate == null ? null : endDate.getDate();
    }

    public void setStartDate(Date startDate) {
        setIntraDayStartDate(IntraDayDate.startOfDay(LocalDate
                .fromDateFields(startDate)));
    }

    public void setIntraDayStartDate(IntraDayDate startDate) {
        if (startDate == null) {
            LOG.error(doNotProvideNullsDiscouragingMessage());
        }
        IntraDayDate previousStart = getIntraDayStartDate();
        IntraDayDate previousEnd = getIntraDayEndDate();
        this.startDate = startDate;
        datesInterceptor.setStartDate(previousStart, previousEnd,
                getIntraDayStartDate());
    }

    @NotNull
    public Date getEndDate() {
        return endDate != null ? endDate.toDateTimeAtStartOfDay().toDate()
                : null;
    }

    public void setEndDate(Date endDate) {
        setIntraDayEndDate(endDate != null ? IntraDayDate.create(
                LocalDate.fromDateFields(endDate), EffortDuration.zero())
                : null);
    }

    public void setIntraDayEndDate(IntraDayDate endDate) {
        if (endDate == null) {
            LOG.error(doNotProvideNullsDiscouragingMessage());
        }
        IntraDayDate previousEnd = getIntraDayEndDate();
        this.endDate = endDate;
        datesInterceptor.setNewEnd(previousEnd, this.endDate);
    }

    private String doNotProvideNullsDiscouragingMessage() {
        return "The provided date shouldn't be null.\n"
                + "Providing null values to start or end dates is not safe.\n"
                + "In a near future an exception will be thrown if you provide a null value to a start or end date.\n"
                + "Please detect the caller and fix it";
    }

    @NotNull
    public IntraDayDate getIntraDayEndDate() {
        return endDate;
    }

    public IDatesHandler getDatesHandler(Scenario scenario,
            IResourcesSearcher resourcesSearcher) {
        return noNullDates(createDatesHandler(scenario, resourcesSearcher));
    }

    private IDatesHandler noNullDates(final IDatesHandler decorated) {
        return new IDatesHandler() {

            @Override
            public void resizeTo(IntraDayDate endDate) {
                Validate.notNull(endDate);
                decorated.resizeTo(endDate);
            }

            @Override
            public void moveTo(IntraDayDate newStartDate) {
                Validate.notNull(newStartDate);
                decorated.moveTo(newStartDate);
            }

            @Override
            public void moveEndTo(IntraDayDate newEnd) {
                Validate.notNull(newEnd);
                decorated.moveEndTo(newEnd);
            }
        };
    }

    protected abstract IDatesHandler createDatesHandler(Scenario scenario,
            IResourcesSearcher resourcesSearcher);

    public interface IDatesHandler {

        /**
         * Sets the startDate to newStartDate. It can update the endDate
         *
         * @param scenario
         * @param newStartDate
         */
        void moveTo(IntraDayDate newStartDate);

        void moveEndTo(IntraDayDate newEnd);

        void resizeTo(IntraDayDate endDate);
    }

    protected abstract boolean canBeResized();

    /**
     * @return if this task can be resized by an explicit action
     */
    public abstract boolean canBeExplicitlyResized();

    public LocalDate getDeadline() {
        return deadline;
    }

    public void setDeadline(LocalDate deadline) {
        this.deadline = deadline;
        if (taskSource != null && taskSource.getOrderElement() != null) {
            taskSource.getOrderElement().setDeadline(
                    (deadline == null)? null : deadline.toDateMidnight().toDate());
        }
    }

    public void add(Dependency dependency) {
        if (this.equals(dependency.getOrigin())) {
            dependenciesWithThisOrigin.add(dependency);
        }
        if (this.equals(dependency.getDestination())) {
            dependenciesWithThisDestination.add(dependency);
        }
    }

    private void removeDependenciesWithThisOrigin(TaskElement origin, Type type) {
        ArrayList<Dependency> toBeRemoved = new ArrayList<Dependency>();
        for (Dependency dependency : dependenciesWithThisDestination) {
            if (dependency.getOrigin().equals(origin)
                    && dependency.getType().equals(type)) {
                toBeRemoved.add(dependency);
            }
        }
        dependenciesWithThisDestination.removeAll(toBeRemoved);
    }

    public void removeDependencyWithDestination(TaskElement destination, Type type) {
        ArrayList<Dependency> toBeRemoved = new ArrayList<Dependency>();
        for (Dependency dependency : dependenciesWithThisOrigin) {
            if (dependency.getDestination().equals(destination)
                    && dependency.getType().equals(type)) {
                toBeRemoved.add(dependency);
            }
        }
        destination.removeDependenciesWithThisOrigin(this, type);
        dependenciesWithThisOrigin.removeAll(toBeRemoved);
    }

    public abstract boolean isLeaf();

    public abstract List<TaskElement> getChildren();

    protected void setParent(TaskGroup taskGroup) {
        this.parent = taskGroup;
    }

    public void detach() {
        detachDependencies();
        detachFromParent();
    }

    public void detachFromParent() {
        if (parent != null) {
            parent.remove(this);
        }
    }

    private void removeDependenciesWithOrigin(TaskElement t) {
        List<Dependency> dependenciesToRemove = getDependenciesWithOrigin(t);
        dependenciesWithThisDestination.removeAll(dependenciesToRemove);
    }

    private void removeDependenciesWithDestination(TaskElement t) {
        List<Dependency> dependenciesToRemove = getDependenciesWithDestination(t);
        dependenciesWithThisOrigin.removeAll(dependenciesToRemove);
    }

    private List<Dependency> getDependenciesWithDestination(TaskElement t) {
        ArrayList<Dependency> result = new ArrayList<Dependency>();
        for (Dependency dependency : dependenciesWithThisOrigin) {
            if (dependency.getDestination().equals(t)) {
                result.add(dependency);
            }
        }
        return result;
    }

    private List<Dependency> getDependenciesWithOrigin(TaskElement t) {
        ArrayList<Dependency> result = new ArrayList<Dependency>();
        for (Dependency dependency : dependenciesWithThisDestination) {
            if (dependency.getOrigin().equals(t)) {
                result.add(dependency);
            }
        }
        return result;
    }

    public void detachDependencies() {
        detachOutcomingDependencies();
        detachIncomingDependencies();
    }

    private void detachIncomingDependencies() {
        Set<TaskElement> tasksToNotify = new HashSet<TaskElement>();
        for (Dependency dependency : dependenciesWithThisDestination) {
            TaskElement origin = dependency.getOrigin();
            if (origin != null) {
                tasksToNotify.add(origin);
            }
        }
        for (TaskElement taskElement : tasksToNotify) {
            this.removeDependenciesWithOrigin(taskElement);
            taskElement.removeDependenciesWithDestination(this);
        }
    }

    private void detachOutcomingDependencies() {
        Set<TaskElement> tasksToNotify = new HashSet<TaskElement>();
        for (Dependency dependency : dependenciesWithThisOrigin) {
            TaskElement destination = dependency.getDestination();
            if (destination != null) {
                tasksToNotify.add(destination);
            }
        }
        for (TaskElement taskElement : tasksToNotify) {
            this.removeDependenciesWithDestination(taskElement);
            taskElement.removeDependenciesWithOrigin(this);
        }
    }

    public void setCalendar(BaseCalendar calendar) {
        this.calendar = calendar;
    }

    public BaseCalendar getOwnCalendar() {
        return calendar;
    }

    public BaseCalendar getCalendar() {
        if (calendar == null) {
            OrderElement orderElement = getOrderElement();
            return orderElement != null ? orderElement.getOrder().getCalendar()
                    : null;
        }
        return calendar;
    }

    public abstract Set<ResourceAllocation<?>> getSatisfiedResourceAllocations();

    public abstract Set<ResourceAllocation<?>> getAllResourceAllocations();

    public SortedMap<LocalDate, EffortDuration> getDurationsAssignedByDay() {
        SortedMap<LocalDate, EffortDuration> result = new TreeMap<LocalDate, EffortDuration>();
        for (ResourceAllocation<?> resourceAllocation : getSatisfiedResourceAllocations()) {
            for (DayAssignment each : resourceAllocation
                    .getAssignments()) {
                addToResult(result, each.getDay(), each.getDuration());
            }
        }
        return result;
    }

    private void addToResult(SortedMap<LocalDate, EffortDuration> result,
            LocalDate date, EffortDuration duration) {
        EffortDuration current = result.get(date) != null ? result.get(date)
                : zero();
        result.put(date, current.plus(duration));
    }

    public List<DayAssignment> getDayAssignments(DayAssignment.FilterType filter) {
        List<DayAssignment> dayAssignments = new ArrayList<DayAssignment>();
        Set<ResourceAllocation<?>> resourceAllocations = getSatisfiedResourceAllocations();
        for (ResourceAllocation<?> resourceAllocation : resourceAllocations) {
            dayAssignments.addAll(resourceAllocation.getAssignments());
            Set<DerivedAllocation> derivedAllocations = resourceAllocation
                    .getDerivedAllocations();
            for (DerivedAllocation each : derivedAllocations) {
                dayAssignments.addAll(each.getAssignments());
            }
        }
        return DayAssignment.filter(dayAssignments, filter);
    }

    public boolean isSubcontracted() {
        // Just Task could be subcontracted
        return false;
    }

    public String getSubcontractionName() {
        return "";
    }

    public boolean isSubcontractedAndWasAlreadySent() {
        // Just Task could be subcontracted
        return false;
    }

    public boolean isLimiting() {
        return false;
    }

    public boolean isLimitingAndHasDayAssignments() {
        return false;
    }

    public boolean hasConsolidations() {
        // Just Task could be consolidated
        return false;
    }

    public TaskElement getTopMost() {
        TaskElement result = this;
        while (result.getParent() != null) {
            result = result.getParent();
        }
        return result;
    }

    public abstract boolean isMilestone();

    public Boolean isSimplifiedAssignedStatusCalculationEnabled() {
        return simplifiedAssignedStatusCalculationEnabled;
    }

    public void setSimplifiedAssignedStatusCalculationEnabled(Boolean enabled) {
        this.simplifiedAssignedStatusCalculationEnabled = enabled;
    }

    public String getAssignedStatus() {
        if(isSimplifiedAssignedStatusCalculationEnabled()) {
            //simplified calculation has only two states:
            //unassigned, when hours allocated is zero, and
            //assigned otherwise
            if (getSumOfAssignedEffort().isZero()) {
                return "unassigned";
            }
            return "assigned";
        }
        Set<ResourceAllocation<?>> resourceAllocations = getSatisfiedResourceAllocations();
        if (resourceAllocations.isEmpty()) {
            return "unassigned";
        }
        for (ResourceAllocation<?> resourceAllocation : resourceAllocations) {
            final ResourcesPerDay resourcesPerDay = resourceAllocation.getResourcesPerDay();
            if (resourcesPerDay != null && resourcesPerDay.isZero()) {
                return "partially-assigned";
            }
        }
        return "assigned";
    }

    public Boolean belongsClosedProject() {
        EnumSet<OrderStatusEnum> CLOSED = EnumSet.of(OrderStatusEnum.CANCELLED,
                OrderStatusEnum.FINISHED, OrderStatusEnum.STORED);

        Order order = getOrderElement().getOrder();
        if(CLOSED.contains(order.getState())) {
            return true;
        }

        return false;
    }

    public abstract boolean hasLimitedResourceAllocation();

    public void removePredecessorsDayAssignmentsFor(Scenario scenario) {
        for (ResourceAllocation<?> each : getAllResourceAllocations()) {
            each.removePredecessorsDayAssignmentsFor(scenario);
        }
    }

    public void removeDayAssignmentsFor(Scenario scenario) {
        for (ResourceAllocation<?> each : getAllResourceAllocations()) {
            each.removeDayAssigmentsFor(scenario);
        }
    }

    public BigDecimal getAdvancePercentage() {
        return (advancePercentage == null) ? BigDecimal.ZERO
                : advancePercentage;
    }

    /**
     * For common tasks it just return the spread progress.
     *
     * It's overridden in {@link TaskGroup} to return different progresses
     * depending on parameter
     */
    public BigDecimal getAdvancePercentage(ProgressType progressType) {
        if (progressType != null
                && progressType.equals(ProgressType.SPREAD_PROGRESS)) {
            return advancePercentage;
        }
        return BigDecimal.ZERO;
    }

    public void setAdvancePercentage(BigDecimal advancePercentage) {
        this.advancePercentage = advancePercentage;
        this.resetStatus();
    }

    private EffortDuration sumOfAssignedEffort = EffortDuration.zero();

    public void setSumOfAssignedEffort(EffortDuration sumOfAssignedEffort) {
        this.sumOfAssignedEffort = sumOfAssignedEffort;
    }

    public EffortDuration getSumOfAssignedEffort() {
        if (this.getParent() == null) {
            //it's an order, we use the cached value
            return sumOfAssignedEffort;
        }
        else {
            return getSumOfAssignedEffortCalculated();
        }
    }

    private EffortDuration getSumOfAssignedEffortCalculated() {
        EffortDuration result = EffortDuration.zero();
        for(ResourceAllocation<?> allocation : getAllResourceAllocations()) {
            result = result.plus(allocation.getAssignedEffort());
        }
        return result;
    }

    public String toString() {
        return super.toString() + " :: " + getName();
    }

    public abstract boolean isTask();

    public List<TaskElement> getAllChildren() {
        List<TaskElement> children = getChildren();
        List<TaskElement> result = new ArrayList<TaskElement>();
        for (TaskElement child : children) {
            result.add(child);
            result.addAll(child.getAllChildren());
        }
        return result;
    }

    public abstract EffortDuration getTheoreticalCompletedTimeUntilDate(Date date);

    public BigDecimal getTheoreticalAdvancePercentageUntilDate(Date date) {
        EffortDuration totalAllocatedTime = AggregateOfDayAssignments.create(
                this.getDayAssignments(FilterType.KEEP_ALL)).getTotalTime();
        EffortDuration totalTheoreticalCompletedTime = this.getTheoreticalCompletedTimeUntilDate(date);
        if (totalAllocatedTime.isZero() || totalTheoreticalCompletedTime.isZero()) {
            return BigDecimal.ZERO;
        }
        Validate.isTrue(totalTheoreticalCompletedTime.getSeconds() <= totalAllocatedTime.getSeconds());
        return totalTheoreticalCompletedTime.dividedByAndResultAsBigDecimal(totalAllocatedTime);
    }

    public abstract boolean isFinished();

    public abstract boolean isInProgress();

    public abstract void acceptVisitor(TaskElementVisitor visitor);

    public abstract void resetStatus();

    public void updateAdvancePercentageFromOrderElement() {
        setAdvancePercentage(getOrderElement().getAdvancePercentage());
    }

    public Boolean isRoot() {
        return (this.getParent() == null);
    }

    public BigDecimal getBudget() {
        if ((taskSource != null) && (taskSource.getOrderElement() != null)) {
            return taskSource.getOrderElement().getBudget();
        }
        return null;
    }

    public BigDecimal getResourcesBudget() {
        if ((taskSource != null) && (taskSource.getOrderElement() != null)) {
            return taskSource.getOrderElement().getResourcesBudget();
        }
        return null;
    }

    public ExternalCompany getSubcontractedCompany() {
        return null;
    }

    public abstract boolean isAnyTaskWithConstraint(PositionConstraintType type);

    public TaskDeadlineViolationStatusEnum getDeadlineViolationStatus() {
        LocalDate deadline = this.getDeadline();
        if (deadline == null) {
            return TaskDeadlineViolationStatusEnum.NO_DEADLINE;
        } else if (this.getEndAsLocalDate().isAfter(deadline)) {
            return TaskDeadlineViolationStatusEnum.DEADLINE_VIOLATED;
        } else {
            return TaskDeadlineViolationStatusEnum.ON_SCHEDULE;
        }
    }

    public static IntraDayDate maxDate(
            Collection<? extends TaskElement> tasksToSave) {
        List<IntraDayDate> endDates = toEndDates(tasksToSave);
        return endDates.isEmpty() ? null : Collections.max(endDates);
    }

    private static List<IntraDayDate> toEndDates(
            Collection<? extends TaskElement> tasksToSave) {
        List<IntraDayDate> result = new ArrayList<IntraDayDate>();
        for (TaskElement taskElement : tasksToSave) {
            IntraDayDate endDate = taskElement.getIntraDayEndDate();
            if (endDate != null) {
                result.add(endDate);
            } else {
                LOG.warn("the task" + taskElement + " has null end date");
            }
        }
        return result;
    }

    public static IntraDayDate minDate(
            Collection<? extends TaskElement> tasksToSave) {
        List<IntraDayDate> startDates = toStartDates(tasksToSave);
        return startDates.isEmpty() ? null : Collections.min(startDates);
    }

    private static List<IntraDayDate> toStartDates(
            Collection<? extends TaskElement> tasksToSave) {
        List<IntraDayDate> result = new ArrayList<IntraDayDate>();
        for (TaskElement taskElement : tasksToSave) {
            IntraDayDate startDate = taskElement.getIntraDayStartDate();
            if (startDate != null) {
                result.add(startDate);
            } else {
                LOG.warn("the task" + taskElement + " has null start date");
            }
        }
        return result;
    }

    public Boolean isUpdatedFromTimesheets() {
        return updatedFromTimesheets;
    }

    public void setUpdatedFromTimesheets(Boolean updatedFromTimesheets) {
        this.updatedFromTimesheets = BooleanUtils.isTrue(updatedFromTimesheets);
    }

}
TOP

Related Classes of org.libreplan.business.planner.entities.TaskElement$IDatesHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.