Bug #1428: Fix bug

Provide a IAssignedEffortForResource that takes into account the
allocations being done.

mb:e98367a8-015e-492e-bffd-56ebbaca7720
This commit is contained in:
Óscar González Fernández 2012-05-11 11:29:27 +02:00 committed by Manuel Rego Casasnovas
parent 628f192be4
commit 7afcef6525
10 changed files with 144 additions and 51 deletions

View file

@ -19,6 +19,7 @@
package org.libreplan.business.planner.entities;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@ -38,11 +39,67 @@ public class AssignedEffortForResource {
LocalDate day);
}
public static IAssignedEffortForResource discount(
public static IAssignedEffortForResource effortDiscounting(
Collection<? extends BaseEntity> allocations) {
return new AssignedEffortDiscounting(allocations);
}
public static IAssignedEffortForResource sum(
final IAssignedEffortForResource... assignedEffortForResources) {
return new IAssignedEffortForResource() {
@Override
public EffortDuration getAssignedDurationAt(Resource resource,
LocalDate day) {
EffortDuration result = EffortDuration.zero();
for (IAssignedEffortForResource each : assignedEffortForResources) {
EffortDuration e = each
.getAssignedDurationAt(resource, day);
if (e != null) {
result = result.plus(e);
}
}
return result;
}
};
}
public static IAssignedEffortForResource sum(
Collection<? extends IAssignedEffortForResource> assignedEffortForResources) {
return sum(assignedEffortForResources
.toArray(new IAssignedEffortForResource[0]));
}
public static WithTheLoadOf withTheLoadOf(
Collection<? extends ResourceAllocation<?>> allocations) {
return new WithTheLoadOf(allocations);
}
public static class WithTheLoadOf implements IAssignedEffortForResource {
private final Set<? extends ResourceAllocation<?>> allocations;
private final IAssignedEffortForResource implementation;
public WithTheLoadOf(
Collection<? extends ResourceAllocation<?>> allocations) {
this.allocations = new HashSet<ResourceAllocation<?>>(allocations);
this.implementation = sum(this.allocations);
}
@Override
public EffortDuration getAssignedDurationAt(Resource resource,
LocalDate day) {
return implementation.getAssignedDurationAt(resource, day);
}
public WithTheLoadOf withoutConsidering(ResourceAllocation<?> allocation) {
Set<ResourceAllocation<?>> copy = new HashSet<ResourceAllocation<?>>(
this.allocations);
copy.remove(allocation);
return new WithTheLoadOf(copy);
}
}
private static class AssignedEffortDiscounting implements
IAssignedEffortForResource {

View file

@ -105,7 +105,7 @@ public class DerivedAllocationGenerator {
List<? extends DayAssignment> dayAssignments) {
List<DerivedDayAssignment> result = new ArrayList<DerivedDayAssignment>();
EffortDistributor distributor = new EffortDistributor(resourcesFound,
AssignedEffortForResource.discount(Collections.singletonList(parent)));
AssignedEffortForResource.effortDiscounting(Collections.singletonList(parent)));
for (DayAssignment each : dayAssignments) {
int durationInSeconds = alpha.multiply(
new BigDecimal(each.getDuration().getSeconds())).intValue();

View file

@ -67,7 +67,7 @@ public class GenericDayAssignment extends DayAssignment {
@Override
ParentState setParent(
GenericResourceAllocation genericResourceAllocation) {
if (parent != null) {
if (parent != null && parent != genericResourceAllocation) {
throw new IllegalStateException(
"the allocation cannot be changed once it has been set");
}

View file

@ -238,19 +238,18 @@ public class GenericResourceAllocation extends
}
private IAssignedEffortForResource assignedEffortCalculatorOverriden = null;
private IAssignedEffortForResource assignedEffortForResource = null;
public void discountAssignedHoursForResourceFrom(
Collection<? extends ResourceAllocation<?>> allocations) {
assignedEffortCalculatorOverriden = AssignedEffortForResource
.discount(allocations);
public void customAssignedEffortForResource(
IAssignedEffortForResource assignedEffortForResource) {
this.assignedEffortForResource = assignedEffortForResource;
}
private IAssignedEffortForResource getAssignedEffortForResource() {
if (assignedEffortCalculatorOverriden != null) {
return assignedEffortCalculatorOverriden;
if (assignedEffortForResource != null) {
return assignedEffortForResource;
}
return AssignedEffortForResource.discount(Collections
return AssignedEffortForResource.effortDiscounting(Collections
.singletonList(this));
}

View file

@ -53,6 +53,7 @@ import org.libreplan.business.calendars.entities.ThereAreHoursOnWorkHoursCalcula
import org.libreplan.business.calendars.entities.ThereAreHoursOnWorkHoursCalculator.CapacityResult;
import org.libreplan.business.common.BaseEntity;
import org.libreplan.business.common.Registry;
import org.libreplan.business.planner.entities.AssignedEffortForResource.IAssignedEffortForResource;
import org.libreplan.business.planner.entities.DerivedAllocationGenerator.IWorkerFinder;
import org.libreplan.business.planner.entities.allocationalgorithms.AllocationModification;
import org.libreplan.business.planner.entities.allocationalgorithms.AllocatorForTaskDurationAndSpecifiedResourcesPerDay;
@ -84,7 +85,7 @@ import org.libreplan.business.workingday.ResourcesPerDay;
* Resources are allocated to planner tasks.
*/
public abstract class ResourceAllocation<T extends DayAssignment> extends
BaseEntity {
BaseEntity implements IAssignedEffortForResource {
private static final Log LOG = LogFactory.getLog(ResourceAllocation.class);
@ -1987,6 +1988,12 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
return getAssignedDuration(assignments, start, endExclusive);
}
@Override
public EffortDuration getAssignedDurationAt(Resource resource, LocalDate day) {
IntraDayDate start = IntraDayDate.startOfDay(day);
return getAssignedEffort(resource, start, start.nextDayAtStart());
}
private List<DayAssignment> getAssingments(final Resource resource,
LocalDate startInclusive, LocalDate endExclusive) {
return filter(getAssignments(startInclusive, endExclusive),

View file

@ -67,12 +67,12 @@ public class SpecificDayAssignment extends DayAssignment {
@Override
ParentState setParent(
SpecificResourceAllocation genericResourceAllocation) {
if (parent != null) {
SpecificResourceAllocation specificResourceAllocation) {
if (parent != null && parent != specificResourceAllocation) {
throw new IllegalStateException(
"the allocation cannot be changed once it has been set");
}
this.parent = genericResourceAllocation;
this.parent = specificResourceAllocation;
return this;
}

View file

@ -143,8 +143,13 @@ public abstract class UntilFillingHoursAllocator {
current = nextDay(current);
}
}
return adjustFinish(resourcesPerDayModification, taken,
IntraDayDate finish = adjustFinish(resourcesPerDayModification, taken,
biggestLastAssignment, current);
// we have to do it now, so the other allocations take into account. At
// the end it's done again with the right end date.
setNewDataForAllocation(resourcesPerDayModification, resultAssignments
.get(resourcesPerDayModification), finish);
return finish;
}
private IntraDayDate adjustFinish(
@ -231,21 +236,21 @@ public abstract class UntilFillingHoursAllocator {
private void setAssignmentsForEachAllocation(IntraDayDate resultDate) {
for (Entry<ResourcesPerDayModification, List<DayAssignment>> entry : resultAssignments
.entrySet()) {
setNewDataForAllocation(entry, resultDate);
setNewDataForAllocation(entry.getKey(), entry.getValue(),
resultDate);
}
}
private <T extends DayAssignment> void setNewDataForAllocation(
Entry<ResourcesPerDayModification, List<DayAssignment>> entry,
ResourcesPerDayModification modification,
List<T> value,
IntraDayDate resultDate) {
@SuppressWarnings("unchecked")
ResourceAllocation<T> allocation = (ResourceAllocation<T>) entry
.getKey().getBeingModified();
ResourcesPerDay resourcesPerDay = entry.getKey().getGoal();
@SuppressWarnings("unchecked")
List<T> value = (List<T>) entry.getValue();
setNewDataForAllocation(allocation, resultDate, resourcesPerDay,
value);
ResourceAllocation<T> allocation = (ResourceAllocation<T>) modification
.getBeingModified();
ResourcesPerDay resourcesPerDay = modification.getGoal();
setNewDataForAllocation(allocation, resultDate,
resourcesPerDay, value);
}
protected Direction getDirection() {

View file

@ -42,10 +42,14 @@ import org.libreplan.business.calendars.entities.ThereAreHoursOnWorkHoursCalcula
import org.libreplan.business.calendars.entities.ThereAreHoursOnWorkHoursCalculator.ResourcesPerDayIsZero;
import org.libreplan.business.calendars.entities.ThereAreHoursOnWorkHoursCalculator.ThereAreNoValidPeriods;
import org.libreplan.business.calendars.entities.ThereAreHoursOnWorkHoursCalculator.ValidPeriodsDontHaveCapacity;
import org.libreplan.business.planner.entities.AssignedEffortForResource;
import org.libreplan.business.planner.entities.AssignedEffortForResource.IAssignedEffortForResource;
import org.libreplan.business.planner.entities.AssignedEffortForResource.WithTheLoadOf;
import org.libreplan.business.planner.entities.AssignmentFunction;
import org.libreplan.business.planner.entities.AssignmentFunction.AssignmentFunctionName;
import org.libreplan.business.planner.entities.CalculatedValue;
import org.libreplan.business.planner.entities.DerivedAllocation;
import org.libreplan.business.planner.entities.GenericResourceAllocation;
import org.libreplan.business.planner.entities.ResourceAllocation;
import org.libreplan.business.planner.entities.Task;
import org.libreplan.business.planner.entities.Task.ModifiedAllocation;
@ -187,10 +191,43 @@ public abstract class AllocationRow {
List<ResourcesPerDayModification> result = new ArrayList<ResourcesPerDayModification>();
for (AllocationRow each : rows) {
ResourcesPerDayModification modification = each
.toResourcesPerDayModification(task, requestedToRemove);
.toResourcesPerDayModification(task);
result.add(modification);
each.setTemporal(modification.getBeingModified());
}
setCustomAssignedEffortForResource(rows, requestedToRemove);
return result;
}
private static void setCustomAssignedEffortForResource(
Collection<? extends AllocationRow> rows,
Collection<? extends ResourceAllocation<?>> requestedToRemove) {
List<ResourceAllocation<?>> allocationsToDiscount = getToDiscount(rows);
allocationsToDiscount.addAll(requestedToRemove);
final IAssignedEffortForResource effortForResource = AssignedEffortForResource
.effortDiscounting(allocationsToDiscount);
List<ResourceAllocation<?>> beingModified = AllocationRow
.getTemporalFrom(rows);
final WithTheLoadOf withTheLoadOf = AssignedEffortForResource
.withTheLoadOf(beingModified);
for (GenericResourceAllocation each : ResourceAllocation.getOfType(GenericResourceAllocation.class, beingModified)) {
IAssignedEffortForResource custom = AssignedEffortForResource.sum(
withTheLoadOf.withoutConsidering(each), effortForResource);
each.customAssignedEffortForResource(custom);
}
}
private static List<ResourceAllocation<?>> getToDiscount(
Collection<? extends AllocationRow> rows) {
List<ResourceAllocation<?>> result = new ArrayList<ResourceAllocation<?>>();
for (AllocationRow each : rows) {
if (each.getOrigin() != null) {
result.add(each.getOrigin());
}
}
return result;
}
@ -209,11 +246,12 @@ public abstract class AllocationRow {
Collection<? extends ResourceAllocation<?>> requestedToRemove) {
List<EffortModification> result = new ArrayList<EffortModification>();
for (AllocationRow each : currentRows) {
EffortModification hoursModification = each.toHoursModification(
task, requestedToRemove);
EffortModification hoursModification = each
.toHoursModification(task);
result.add(hoursModification);
each.setTemporal(hoursModification.getBeingModified());
}
setCustomAssignedEffortForResource(currentRows, requestedToRemove);
return result;
}
@ -242,7 +280,7 @@ public abstract class AllocationRow {
}
public static List<ResourceAllocation<?>> getTemporalFrom(
List<AllocationRow> rows) {
Collection<? extends AllocationRow> rows) {
List<ResourceAllocation<?>> result = new ArrayList<ResourceAllocation<?>>();
for (AllocationRow each : rows) {
if (each.temporal != null) {
@ -379,11 +417,9 @@ public abstract class AllocationRow {
}
public abstract ResourcesPerDayModification toResourcesPerDayModification(
Task task,
Collection<? extends ResourceAllocation<?>> requestedToRemove);
Task task);
public abstract EffortModification toHoursModification(Task task,
Collection<? extends ResourceAllocation<?>> requestedToRemove);
public abstract EffortModification toHoursModification(Task task);
public boolean isCreating() {
return origin == null;

View file

@ -124,35 +124,26 @@ public class GenericAllocationRow extends AllocationRow {
}
@Override
public ResourcesPerDayModification toResourcesPerDayModification(Task task,
Collection<? extends ResourceAllocation<?>> requestedToRemove) {
GenericResourceAllocation newGeneric = createGenericAllocation(task,
requestedToRemove);
public ResourcesPerDayModification toResourcesPerDayModification(Task task) {
GenericResourceAllocation newGeneric = createGenericAllocation(task);
return ResourcesPerDayModification
.create(newGeneric, getResourcesPerDayEditedValue(), this.resources);
}
private GenericResourceAllocation createGenericAllocation(Task task,
Collection<? extends ResourceAllocation<?>> allocationsRemoved) {
private GenericResourceAllocation createGenericAllocation(Task task) {
GenericResourceAllocation result = GenericResourceAllocation.create(
task, resourceType, criterions);
GenericResourceAllocation origin = (GenericResourceAllocation) getOrigin();
Set<ResourceAllocation<?>> discountFrom = new HashSet<ResourceAllocation<?>>(
allocationsRemoved);
if (origin != null) {
result.overrideConsolidatedDayAssignments(origin);
discountFrom.add(origin);
result.setAssignmentFunctionWithoutApply(origin.getAssignmentFunction());
}
result.discountAssignedHoursForResourceFrom(discountFrom);
return result;
}
@Override
public EffortModification toHoursModification(Task task,
Collection<? extends ResourceAllocation<?>> requestedToRemove) {
return EffortModification.create(
createGenericAllocation(task, requestedToRemove),
public EffortModification toHoursModification(Task task) {
return EffortModification.create(createGenericAllocation(task),
getEffortFromInput(), resources);
}

View file

@ -116,8 +116,7 @@ public class SpecificAllocationRow extends AllocationRow {
}
@Override
public ResourcesPerDayModification toResourcesPerDayModification(Task task,
Collection<? extends ResourceAllocation<?>> requestedToRemove) {
public ResourcesPerDayModification toResourcesPerDayModification(Task task) {
return ResourcesPerDayModification.create(createSpecific(task),
getResourcesPerDayEditedValue());
}
@ -135,8 +134,7 @@ public class SpecificAllocationRow extends AllocationRow {
}
@Override
public EffortModification toHoursModification(Task task,
Collection<? extends ResourceAllocation<?>> requestedToRemove) {
public EffortModification toHoursModification(Task task) {
return EffortModification.create(createSpecific(task),
getEffortFromInput());
}