Don't use the returned by queries allocations belonging to the order

Instead those allocations should be retrieved directly from the order
so it works well when the scenario is not the owner one and with newly
added allocations.

FEA: ItEr75S11PreventLooseChanges
This commit is contained in:
Óscar González Fernández 2011-07-21 16:59:50 +02:00
parent 1be0a2a7a5
commit 3ad1c801a6
7 changed files with 324 additions and 82 deletions

View file

@ -105,6 +105,15 @@ public abstract class DayAssignment extends BaseEntity {
public static <T extends DayAssignment> Map<Resource, List<T>> byResourceAndOrdered(
Collection<? extends T> assignments) {
Map<Resource, List<T>> result = byResource(assignments);
for (Entry<Resource, List<T>> entry : result.entrySet()) {
Collections.sort(entry.getValue(), byDayComparator());
}
return result;
}
public static <T extends DayAssignment> Map<Resource, List<T>> byResource(
Collection<? extends T> assignments) {
Map<Resource, List<T>> result = new HashMap<Resource, List<T>>();
for (T assignment : assignments) {
Resource resource = assignment.getResource();
@ -113,9 +122,6 @@ public abstract class DayAssignment extends BaseEntity {
}
result.get(resource).add(assignment);
}
for (Entry<Resource, List<T>> entry : result.entrySet()) {
Collections.sort(entry.getValue(), byDayComparator());
}
return result;
}

View file

@ -129,7 +129,7 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
}
public static <R extends ResourceAllocation<?>> List<R> sortedByStartDate(
Collection<R> allocations) {
Collection<? extends R> allocations) {
List<R> result = new ArrayList<R>(allocations);
Collections.sort(result, byStartDateComparator());
return result;

View file

@ -26,6 +26,7 @@ import static org.navalplanner.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.ConcurrentModificationException;
@ -63,6 +64,16 @@ 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);

View file

@ -26,7 +26,6 @@ import java.util.List;
import org.navalplanner.business.common.daos.IIntegrationEntityDAO;
import org.navalplanner.business.labels.entities.Label;
import org.navalplanner.business.planner.entities.Task;
import org.navalplanner.business.reports.dtos.HoursWorkedPerResourceDTO;
import org.navalplanner.business.reports.dtos.HoursWorkedPerWorkerInAMonthDTO;
import org.navalplanner.business.resources.entities.Criterion;
@ -42,14 +41,6 @@ import org.navalplanner.business.resources.entities.Worker;
*/
public interface IResourceDAO extends IIntegrationEntityDAO<Resource> {
/**
* Returns all {@link Resource} which are related with tasks
*
* @param tasks
* @return
*/
List<Resource> findResourcesRelatedTo(List<Task> tasks);
/**
* Returns all {@link Machine}
*

View file

@ -24,15 +24,12 @@ package org.navalplanner.business.resources.daos;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.hibernate.Query;
import org.hibernate.criterion.Restrictions;
import org.navalplanner.business.common.daos.IntegrationEntityDAO;
import org.navalplanner.business.labels.entities.Label;
import org.navalplanner.business.planner.entities.Task;
import org.navalplanner.business.reports.dtos.HoursWorkedPerResourceDTO;
import org.navalplanner.business.reports.dtos.HoursWorkedPerWorkerInAMonthDTO;
import org.navalplanner.business.resources.entities.Criterion;
@ -41,7 +38,6 @@ import org.navalplanner.business.resources.entities.Machine;
import org.navalplanner.business.resources.entities.Resource;
import org.navalplanner.business.resources.entities.Worker;
import org.navalplanner.business.scenarios.IScenarioManager;
import org.navalplanner.business.scenarios.entities.Scenario;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
@ -91,46 +87,6 @@ public class ResourceDAO extends IntegrationEntityDAO<Resource> implements
return list;
}
@Override
public List<Resource> findResourcesRelatedTo(List<Task> taskElements) {
if (taskElements.isEmpty()) {
return new ArrayList<Resource>();
}
Set<Resource> result = new LinkedHashSet<Resource>();
result.addAll(findRelatedToSpecific(taskElements));
result.addAll(findRelatedToGeneric(taskElements));
return new ArrayList<Resource>(result);
}
@SuppressWarnings("unchecked")
private List<Resource> findRelatedToGeneric(List<Task> taskElements) {
String query = "SELECT DISTINCT resource FROM GenericResourceAllocation generic"
+ " JOIN generic.genericDayAssignmentsContainers container "
+ " JOIN container.dayAssignments dayAssignment"
+ " JOIN dayAssignment.resource resource"
+ " WHERE generic.task IN(:taskElements)";
return getSession().createQuery(query)
.setParameterList("taskElements",
taskElements).list();
}
@SuppressWarnings("unchecked")
private List<Resource> findRelatedToSpecific(List<Task> taskElements) {
Scenario scenario = scenarioManager.getCurrent();
List<Resource> list = getSession()
.createQuery(
"SELECT DISTINCT specificAllocation.resource "
+ "FROM SpecificResourceAllocation specificAllocation "
+ "JOIN specificAllocation.specificDayAssignmentsContainers container "
+ "WHERE specificAllocation.task IN(:taskElements) "
+ "and container.scenario = :scenario "
+ "and container.dayAssignments IS NOT EMPTY")
.setParameterList("taskElements", taskElements)
.setParameter("scenario", scenario)
.list();
return list;
}
public List<Resource> getResources() {
return list(Resource.class);
}

View file

@ -18,6 +18,8 @@
*/
package org.navalplanner.web.planner.order;
import static org.navalplanner.business.planner.entities.TaskElement.justTasks;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@ -28,6 +30,7 @@ import java.util.Set;
import org.apache.commons.lang.Validate;
import org.hibernate.Hibernate;
import org.joda.time.LocalDate;
import org.navalplanner.business.orders.daos.IOrderDAO;
import org.navalplanner.business.orders.entities.Order;
import org.navalplanner.business.orders.entities.OrderElement;
@ -38,6 +41,9 @@ import org.navalplanner.business.planner.entities.DayAssignment;
import org.navalplanner.business.planner.entities.DerivedAllocation;
import org.navalplanner.business.planner.entities.GenericResourceAllocation;
import org.navalplanner.business.planner.entities.ResourceAllocation;
import org.navalplanner.business.planner.entities.ResourceAllocation.IVisitor;
import org.navalplanner.business.planner.entities.SpecificResourceAllocation;
import org.navalplanner.business.planner.entities.Task;
import org.navalplanner.business.planner.entities.TaskElement;
import org.navalplanner.business.planner.entities.TaskGroup;
import org.navalplanner.business.planner.entities.TaskMilestone;
@ -509,6 +515,93 @@ public class PlanningStateCreator {
}
}
public List<Resource> getResourcesRelatedWithAllocations() {
Set<Resource> result = new HashSet<Resource>();
for (Task each : justTasks(order
.getAllChildrenAssociatedTaskElements())) {
result.addAll(resourcesRelatedWith(each));
}
return new ArrayList<Resource>(result);
}
private Set<Resource> resourcesRelatedWith(Task task) {
Set<Resource> result = new HashSet<Resource>();
for (ResourceAllocation<?> each : task
.getSatisfiedResourceAllocations()) {
result.addAll(resourcesRelatedWith(each));
}
return result;
}
private <T> Collection<Resource> resourcesRelatedWith(
ResourceAllocation<?> allocation) {
return ResourceAllocation.visit(allocation,
new IVisitor<Collection<Resource>>() {
@Override
public Collection<Resource> on(
SpecificResourceAllocation specificAllocation) {
return Collections.singletonList(specificAllocation
.getResource());
}
@Override
public Collection<Resource> on(
GenericResourceAllocation genericAllocation) {
return DayAssignment.byResource(
genericAllocation.getAssignments())
.keySet();
}
});
}
public List<ResourceAllocation<?>> replaceByCurrentOnes(
Collection<? extends ResourceAllocation<?>> allocationsReturnedByQuery,
IAllocationCriteria allocationCriteria) {
Set<TaskElement> orderTasks = new HashSet<TaskElement>(
order.getAllChildrenAssociatedTaskElements());
List<ResourceAllocation<?>> result = allocationsNotInOrder(
allocationsReturnedByQuery, orderTasks);
result.addAll(allocationsInOrderSatisfyingCriteria(orderTasks,
allocationCriteria));
return result;
}
private List<ResourceAllocation<?>> allocationsNotInOrder(
Collection<? extends ResourceAllocation<?>> allocationsReturnedByQuery,
Set<TaskElement> orderTasks) {
List<ResourceAllocation<?>> result = new ArrayList<ResourceAllocation<?>>();
for (ResourceAllocation<?> each : allocationsReturnedByQuery) {
if (!orderTasks.contains(each.getTask())) {
result.add(each);
}
}
return result;
}
private List<ResourceAllocation<?>> allocationsInOrderSatisfyingCriteria(
Collection<? extends TaskElement> tasks,
IAllocationCriteria allocationCriteria) {
List<ResourceAllocation<?>> result = new ArrayList<ResourceAllocation<?>>();
for (Task each : justTasks(tasks)) {
result.addAll(satisfying(allocationCriteria,
each.getSatisfiedResourceAllocations()));
}
return result;
}
private List<ResourceAllocation<?>> satisfying(
IAllocationCriteria criteria,
Collection<ResourceAllocation<?>> allocations) {
List<ResourceAllocation<?>> result = new ArrayList<ResourceAllocation<?>>();
for (ResourceAllocation<?> each : allocations) {
if (criteria.isSatisfiedBy(each)) {
result.add(each);
}
}
return result;
}
}
private class EmptyPlannigState extends PlanningState {
@ -712,4 +805,147 @@ public class PlanningStateCreator {
}
public interface IAllocationCriteria {
boolean isSatisfiedBy(ResourceAllocation<?> resourceAllocation);
}
public static IAllocationCriteria and(final IAllocationCriteria... criteria) {
return new IAllocationCriteria() {
@Override
public boolean isSatisfiedBy(
ResourceAllocation<?> resourceAllocation) {
for (IAllocationCriteria each : criteria) {
if (!each.isSatisfiedBy(resourceAllocation)) {
return false;
}
}
return true;
}
};
}
public static class TaskOnInterval implements IAllocationCriteria {
private final LocalDate startInclusive;
private final LocalDate endInclusive;
public TaskOnInterval(LocalDate startInclusive, LocalDate endInclusive) {
this.startInclusive = startInclusive;
this.endInclusive = endInclusive;
}
@Override
public boolean isSatisfiedBy(ResourceAllocation<?> resourceAllocation) {
if (startInclusive != null
&& resourceAllocation.getEndDate()
.compareTo(startInclusive) < 0) {
return false;
}
if (endInclusive != null
&& resourceAllocation.getStartDate()
.compareTo(endInclusive) > 0) {
return false;
}
return true;
}
}
public static class RelatedWithAnyOf implements
IAllocationCriteria {
private final Collection<? extends Criterion> anyOf;
public RelatedWithAnyOf(
Collection<? extends Criterion> anyOf) {
this.anyOf = anyOf;
}
@Override
public boolean isSatisfiedBy(ResourceAllocation<?> resourceAllocation) {
if (resourceAllocation instanceof GenericResourceAllocation) {
GenericResourceAllocation g = (GenericResourceAllocation) resourceAllocation;
Set<Criterion> allocationCriterions = g.getCriterions();
return someCriterionIn(allocationCriterions);
}
return false;
}
private boolean someCriterionIn(
Collection<? extends Criterion> allocationCriterions) {
for (Criterion each : allocationCriterions) {
if (this.anyOf.contains(each)) {
return true;
}
}
return false;
}
}
public static class SpecificRelatedWithCriterionOnInterval implements
IAllocationCriteria {
private final LocalDate startInclusive;
private final LocalDate endExclusive;
private final Criterion criterion;
public SpecificRelatedWithCriterionOnInterval(
Criterion criterion, LocalDate startInclusive,
LocalDate endInclusive) {
Validate.notNull(criterion);
this.startInclusive = startInclusive;
this.endExclusive = endInclusive != null ? endInclusive.plusDays(1)
: null;
this.criterion = criterion;
}
@Override
public boolean isSatisfiedBy(ResourceAllocation<?> resourceAllocation) {
if (resourceAllocation instanceof SpecificResourceAllocation) {
SpecificResourceAllocation s = (SpecificResourceAllocation) resourceAllocation;
return s.interferesWith(criterion, startInclusive, endExclusive);
}
return false;
}
}
public static class RelatedWithResource implements IAllocationCriteria {
private final Resource resource;
public RelatedWithResource(Resource resource) {
Validate.notNull(resource);
this.resource = resource;
}
@Override
public boolean isSatisfiedBy(ResourceAllocation<?> resourceAllocation) {
return ResourceAllocation.visit(resourceAllocation,
new IVisitor<Boolean>() {
@Override
public Boolean on(
SpecificResourceAllocation specificAllocation) {
return specificAllocation.getResource().equals(
resource);
}
@Override
public Boolean on(
GenericResourceAllocation genericAllocation) {
return DayAssignment.byResource(
genericAllocation.getAssignments())
.containsKey(resource);
}
});
}
}
}

View file

@ -21,7 +21,9 @@
package org.navalplanner.web.resourceload;
import static org.navalplanner.business.planner.entities.TaskElement.justTasks;
import static org.navalplanner.web.I18nHelper._;
import static org.navalplanner.web.planner.order.PlanningStateCreator.and;
import java.util.ArrayList;
import java.util.Calendar;
@ -68,7 +70,12 @@ import org.navalplanner.business.users.entities.OrderAuthorizationType;
import org.navalplanner.business.users.entities.User;
import org.navalplanner.business.users.entities.UserRole;
import org.navalplanner.web.calendars.BaseCalendarModel;
import org.navalplanner.web.planner.order.PlanningStateCreator.IAllocationCriteria;
import org.navalplanner.web.planner.order.PlanningStateCreator.PlanningState;
import org.navalplanner.web.planner.order.PlanningStateCreator.RelatedWithAnyOf;
import org.navalplanner.web.planner.order.PlanningStateCreator.RelatedWithResource;
import org.navalplanner.web.planner.order.PlanningStateCreator.SpecificRelatedWithCriterionOnInterval;
import org.navalplanner.web.planner.order.PlanningStateCreator.TaskOnInterval;
import org.navalplanner.web.security.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
@ -262,17 +269,43 @@ public class ResourceLoadModel implements IResourceLoadModel {
}
}
private IAllocationCriteria onInterval() {
return new TaskOnInterval(initDateFilter, endDateFilter);
}
private Map<Criterion, List<GenericResourceAllocation>> findAllocationsGroupedByCriteria(
List<Criterion> relatedWith) {
return resourceAllocationDAO
.findGenericAllocationsBySomeCriterion(
relatedWith, asDate(initDateFilter), asDate(endDateFilter));
Map<Criterion, List<GenericResourceAllocation>> result = resourceAllocationDAO
.findGenericAllocationsBySomeCriterion(relatedWith,
asDate(initDateFilter), asDate(endDateFilter));
return doReplacementsIfNeeded(result,
and(onInterval(), new RelatedWithAnyOf(relatedWith)));
}
private Map<Criterion, List<GenericResourceAllocation>> findAllocationsGroupedByCriteria() {
return resourceAllocationDAO
.findGenericAllocationsByCriterion(
asDate(initDateFilter), asDate(endDateFilter));
return doReplacementsIfNeeded(
resourceAllocationDAO.findGenericAllocationsByCriterion(
asDate(initDateFilter), asDate(endDateFilter)),
onInterval());
}
private Map<Criterion, List<GenericResourceAllocation>> doReplacementsIfNeeded(
Map<Criterion, List<GenericResourceAllocation>> map,
IAllocationCriteria criteria) {
if (filterBy == null) {
return map;
}
Map<Criterion, List<GenericResourceAllocation>> result = new HashMap<Criterion, List<GenericResourceAllocation>>();
for (Entry<Criterion, List<GenericResourceAllocation>> each : map
.entrySet()) {
List<ResourceAllocation<?>> replaced = filterBy
.replaceByCurrentOnes(each.getValue(), criteria);
if (!replaced.isEmpty()) {
result.put(each.getKey(), ResourceAllocation.getOfType(
GenericResourceAllocation.class, replaced));
}
}
return result;
}
private Map<Criterion, List<ResourceAllocation<?>>> withAssociatedSpecific(
@ -282,14 +315,29 @@ public class ResourceLoadModel implements IResourceLoadModel {
.entrySet()) {
List<ResourceAllocation<?>> both = new ArrayList<ResourceAllocation<?>>();
both.addAll(each.getValue());
both.addAll(resourceAllocationDAO.findSpecificAllocationsRelatedTo(
each.getKey(), asDate(initDateFilter),
asDate(endDateFilter)));
both.addAll(doReplacementsIfNeeded(resourceAllocationDAO
.findSpecificAllocationsRelatedTo(each.getKey(),
asDate(initDateFilter), asDate(endDateFilter)),
and(onInterval(), specificRelatedTo(each.getKey()))));
result.put(each.getKey(), both);
}
return result;
}
private IAllocationCriteria specificRelatedTo(Criterion key) {
return new SpecificRelatedWithCriterionOnInterval(key,
initDateFilter, endDateFilter);
}
private Collection<? extends ResourceAllocation<?>> doReplacementsIfNeeded(
Collection<? extends ResourceAllocation<?>> allocations,
IAllocationCriteria criteria) {
if (filterBy == null) {
return allocations;
}
return filterBy.replaceByCurrentOnes(allocations, criteria);
}
private <R extends ResourceAllocation<?>> Map<Criterion, List<R>> onlyForThePagesShown(
List<Criterion> criteriaReallyShown,
Map<Criterion, List<R>> allocationsByCriteria) {
@ -405,19 +453,8 @@ public class ResourceLoadModel implements IResourceLoadModel {
}
private List<Resource> resourcesForActiveTasks() {
return Resource.sortByName(resourcesDAO
.findResourcesRelatedTo(justTasks(filterBy.getOrder()
.getAllChildrenAssociatedTaskElements())));
}
private 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;
return Resource.sortByName(filterBy
.getResourcesRelatedWithAllocations());
}
private List<Resource> allResources() {
@ -641,13 +678,18 @@ public class ResourceLoadModel implements IResourceLoadModel {
Map<Resource, List<ResourceAllocation<?>>> map = new LinkedHashMap<Resource, List<ResourceAllocation<?>>>();
for (Resource resource : allResources) {
map.put(resource, ResourceAllocation
.sortedByStartDate(resourceAllocationDAO
.findAllocationsRelatedTo(resource, initDateFilter,
endDateFilter)));
.sortedByStartDate(doReplacementsIfNeeded(
resourceAllocationDAO.findAllocationsRelatedTo(
resource, initDateFilter, endDateFilter),
and(onInterval(), relatedToResource(resource)))));
}
return map;
}
private IAllocationCriteria relatedToResource(Resource resource) {
return new RelatedWithResource(resource);
}
private List<LoadTimeLine> buildGroupsFor(
Map<Resource, List<ResourceAllocation<?>>> map) {
List<LoadTimeLine> result = new ArrayList<LoadTimeLine>();