/*
* 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.web.planner.allocation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.Validate;
import org.joda.time.LocalDate;
import org.libreplan.business.planner.entities.AggregateOfResourceAllocations;
import org.libreplan.business.planner.entities.CalculatedValue;
import org.libreplan.business.planner.entities.GenericResourceAllocation;
import org.libreplan.business.planner.entities.ResourceAllocation;
import org.libreplan.business.planner.entities.ResourceAllocation.Direction;
import org.libreplan.business.planner.entities.SpecificResourceAllocation;
import org.libreplan.business.planner.entities.Task;
import org.libreplan.business.planner.entities.Task.ModifiedAllocation;
import org.libreplan.business.scenarios.entities.Scenario;
import org.libreplan.business.workingday.IntraDayDate;
/**
* @author Óscar González Fernández <ogonzalez@igalia.com>
*
*/
public class AllocationResult {
public static AllocationResult create(Task task,
CalculatedValue calculatedValue, List<AllocationRow> rows,
Integer newWorkableDays) {
List<ResourceAllocation<?>> newAllocations = AllocationRow
.getNewFrom(rows);
List<ModifiedAllocation> modified = AllocationRow.getModificationsDone(rows);
return new AllocationResult(task, newWorkableDays, calculatedValue,
createAggregate(newAllocations, modified), newAllocations,
modified);
}
private static AggregateOfResourceAllocations createAggregate(
List<ResourceAllocation<?>> newAllocations,
List<ModifiedAllocation> modified) {
List<ResourceAllocation<?>> all = new ArrayList<ResourceAllocation<?>>();
all.addAll(newAllocations);
all.addAll(ModifiedAllocation.modified(modified));
return AggregateOfResourceAllocations.createFromSatisfied(all);
}
public static AllocationResult createCurrent(Scenario scenario, Task task) {
Set<ResourceAllocation<?>> resourceAllocations = task
.getSatisfiedResourceAllocations();
List<ModifiedAllocation> modifiedAllocations = ModifiedAllocation.copy(
scenario, resourceAllocations);
AggregateOfResourceAllocations aggregate = AggregateOfResourceAllocations
.createFromSatisfied(ModifiedAllocation
.modified(modifiedAllocations));
return new AllocationResult(task, task.getSpecifiedWorkableDays(),
task.getCalculatedValue(), aggregate,
Collections.<ResourceAllocation<?>> emptyList(),
modifiedAllocations);
}
private final AggregateOfResourceAllocations aggregate;
private final CalculatedValue calculatedValue;
private final Task task;
private final List<ResourceAllocation<?>> newAllocations;
private final List<Task.ModifiedAllocation> modified;
/**
* The number of workable days with wich the allocation has been done. Can
* be <code>null</code>
*/
private final Integer newWorkableDays;
private AllocationResult(Task task, Integer newWorkableDays,
CalculatedValue calculatedValue,
AggregateOfResourceAllocations aggregate,
List<ResourceAllocation<?>> newAllocations,
List<Task.ModifiedAllocation> modified) {
Validate.notNull(aggregate);
Validate.notNull(calculatedValue);
Validate.notNull(task);
this.task = task;
this.newWorkableDays = newWorkableDays;
this.calculatedValue = calculatedValue;
this.aggregate = aggregate;
this.newAllocations = newAllocations;
this.modified = modified;
}
public AggregateOfResourceAllocations getAggregate() {
return aggregate;
}
private List<ResourceAllocation<?>> getNew() {
return newAllocations;
}
private List<Task.ModifiedAllocation> getModified() {
return modified;
}
public CalculatedValue getCalculatedValue() {
return calculatedValue;
}
public void applyTo(Scenario scenario, Task task) {
List<ModifiedAllocation> modified = getModified();
if (aggregate.isEmpty()) {
return;
}
task.mergeAllocation(scenario, getIntraDayStart(), getIntraDayEnd(),
newWorkableDays,
getCalculatedValue(), getNew(), modified,
getNotModified(originals(modified)));
}
private List<ResourceAllocation<?>> originals(
List<ModifiedAllocation> modified) {
List<ResourceAllocation<?>> result = new ArrayList<ResourceAllocation<?>>();
for (ModifiedAllocation modifiedAllocation : modified) {
result.add(modifiedAllocation.getOriginal());
}
return result;
}
private Set<ResourceAllocation<?>> getNotModified(
List<ResourceAllocation<?>> modified) {
Set<ResourceAllocation<?>> all = new HashSet<ResourceAllocation<?>>(
task.getSatisfiedResourceAllocations());
all.removeAll(modified);
return all;
}
public List<ResourceAllocation<?>> getAllSortedByStartDate() {
return aggregate.getAllocationsSortedByStartDate();
}
public Task getTask() {
return task;
}
public List<GenericResourceAllocation> getGenericAllocations() {
return onlyGeneric(getAllSortedByStartDate());
}
private List<GenericResourceAllocation> onlyGeneric(
List<ResourceAllocation<?>> allocations) {
List<GenericResourceAllocation> result = new ArrayList<GenericResourceAllocation>();
for (ResourceAllocation<?> resourceAllocation : allocations) {
if (resourceAllocation instanceof GenericResourceAllocation) {
result.add((GenericResourceAllocation) resourceAllocation);
}
}
return result;
}
public List<SpecificResourceAllocation> getSpecificAllocations() {
return onlySpecific(getAllSortedByStartDate());
}
private List<SpecificResourceAllocation> onlySpecific(
List<ResourceAllocation<?>> allocations) {
List<SpecificResourceAllocation> result = new ArrayList<SpecificResourceAllocation>();
for (ResourceAllocation<?> r : allocations) {
if (r instanceof SpecificResourceAllocation) {
result.add((SpecificResourceAllocation) r);
}
}
return result;
}
public LocalDate getStart() {
return task.getStartAsLocalDate();
}
private boolean isForwardsScheduled() {
return Direction.FORWARD.equals(task.getAllocationDirection());
}
public IntraDayDate getIntraDayStart() {
if (isForwardsScheduled() || aggregate.isEmpty()) {
return task.getIntraDayStartDate();
} else {
return aggregate.getStart();
}
}
public IntraDayDate getIntraDayEnd() {
if (!isForwardsScheduled() || aggregate.isEmpty()) {
return task.getIntraDayEndDate();
} else {
return aggregate.getEnd();
}
}
}