ItEr35S12CUCreacionUnidadesPlanificacionItEr34S12: OrderElements and TaskElements are now binded by TaskSource. one-to-many relationship between OrderElement and TaskElement removed

This commit is contained in:
Óscar González Fernández 2009-11-16 10:50:09 +01:00
parent 4e9ea978d9
commit de5ce7cafb
19 changed files with 802 additions and 278 deletions

View file

@ -23,7 +23,11 @@ package org.navalplanner.business.orders.daos;
import java.util.List;
import org.navalplanner.business.common.daos.GenericDAOHibernate;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.orders.entities.Order;
import org.navalplanner.business.orders.entities.TaskSource;
import org.navalplanner.business.planner.daos.ITaskSourceDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;
@ -37,9 +41,22 @@ import org.springframework.stereotype.Repository;
public class OrderDAO extends GenericDAOHibernate<Order, Long> implements
IOrderDAO {
@Autowired
private ITaskSourceDAO taskSourceDAO;
@Override
public List<Order> getOrders() {
return list(Order.class);
}
@Override
public void remove(Long id) throws InstanceNotFoundException {
Order order = find(id);
List<TaskSource> sources = order.getTaskSourcesFromBottomToTop();
for (TaskSource each : sources) {
taskSourceDAO.remove(each.getId());
}
super.remove(id);
}
}

View file

@ -87,12 +87,7 @@ public class Order extends OrderLineGroup {
}
public TaskGroup getAssociatedTaskElement() {
Set<TaskElement> taskElements = this.getTaskElements();
if (!taskElements.isEmpty()) {
return (TaskGroup) taskElements.iterator().next();
} else {
return null;
}
return (TaskGroup) super.getAssociatedTaskElement();
}
public List<TaskElement> getAssociatedTasks() {

View file

@ -44,6 +44,7 @@ import org.navalplanner.business.common.BaseEntity;
import org.navalplanner.business.labels.entities.Label;
import org.navalplanner.business.orders.entities.SchedulingState.ITypeChangedListener;
import org.navalplanner.business.orders.entities.SchedulingState.Type;
import org.navalplanner.business.orders.entities.TaskSource.TaskSourceSynchronization;
import org.navalplanner.business.planner.entities.Task;
import org.navalplanner.business.planner.entities.TaskElement;
import org.navalplanner.business.requirements.entities.CriterionRequirement;
@ -71,8 +72,6 @@ public abstract class OrderElement extends BaseEntity {
private String code;
private Set<TaskElement> taskElements = new HashSet<TaskElement>();
private Set<CriterionRequirement> criterionRequirements = new HashSet<CriterionRequirement>();
protected OrderLineGroup parent;
@ -105,9 +104,6 @@ public abstract class OrderElement extends BaseEntity {
@Override
public void typeChanged(Type newType) {
schedulingStateType = newType;
if (newType == Type.SCHEDULING_POINT) {
taskSource = TaskSource.withHoursGroupOf(OrderElement.this);
}
}
});
return result;
@ -120,38 +116,119 @@ public abstract class OrderElement extends BaseEntity {
}
return result;
}
public List<TaskSourceSynchronization> calculateSynchronizationsNeeded() {
List<TaskSourceSynchronization> result = new ArrayList<TaskSourceSynchronization>();
if (isSchedulingPoint()) {
result.add(synchronizationForSchedulingPoint());
} else if (isSuperElementPartialOrCompletelyScheduled()) {
removeUnscheduled(result);
result.add(synchronizationForSuperelement());
} else if (schedulingState.isNoScheduled()) {
removeTaskSource(result);
}
return result;
}
private TaskSourceSynchronization synchronizationForSuperelement() {
List<TaskSourceSynchronization> childrenSynchronizations = childrenSynchronizations();
if (thereIsNoTaskSource()) {
taskSource = TaskSource.createForGroup(this);
return TaskSource
.mustAddGroup(taskSource,
childrenSynchronizations);
} else {
return taskSource.modifyGroup(childrenSynchronizations);
}
}
private List<TaskSourceSynchronization> childrenSynchronizations() {
List<TaskSourceSynchronization> childrenOfGroup = new ArrayList<TaskSourceSynchronization>();
for (OrderElement orderElement : getSomewhatScheduledOrderElements()) {
childrenOfGroup.addAll(orderElement
.calculateSynchronizationsNeeded());
}
return childrenOfGroup;
}
private void removeUnscheduled(List<TaskSourceSynchronization> result) {
for (OrderElement orderElement : getNoScheduledOrderElements()) {
orderElement.removeTaskSource(result);
}
}
private TaskSourceSynchronization synchronizationForSchedulingPoint() {
if (thereIsNoTaskSource()) {
taskSource = TaskSource.create(this, getHoursGroups());
return TaskSource.mustAdd(taskSource);
} else {
return taskSource.withCurrentHoursGroup(getHoursGroups());
}
}
private boolean thereIsNoTaskSource() {
return taskSource == null;
}
private List<OrderElement> getSomewhatScheduledOrderElements() {
List<OrderElement> result = new ArrayList<OrderElement>();
for (OrderElement orderElement : getChildren()) {
if (orderElement.getSchedulingStateType().isSomewhatScheduled()) {
result.add(orderElement);
}
}
return result;
}
private List<OrderElement> getNoScheduledOrderElements() {
List<OrderElement> result = new ArrayList<OrderElement>();
for (OrderElement orderElement : getChildren()) {
if (orderElement.getSchedulingState().isNoScheduled()) {
result.add(orderElement);
}
}
return result;
}
private void removeTaskSource(List<TaskSourceSynchronization> result) {
removeChildrenTaskSource(result);
if (taskSource != null) {
result.add(TaskSource.mustRemove(taskSource));
taskSource = null;
}
}
private void removeChildrenTaskSource(List<TaskSourceSynchronization> result) {
List<OrderElement> children = getChildren();
for (OrderElement each : children) {
each.removeTaskSource(result);
}
}
private boolean isSuperElementPartialOrCompletelyScheduled() {
return getSchedulingState().isSomewhatScheduled();
}
private boolean isSchedulingPoint() {
return getSchedulingState().getType() == Type.SCHEDULING_POINT;
}
public OrderLineGroup getParent() {
return parent;
}
public TaskElement getAssociatedTaskElement() {
if (taskSource == null) {
return null;
} else {
return taskSource.getTask();
}
}
protected void setParent(OrderLineGroup parent) {
this.parent = parent;
}
protected void hoursGroupAdded(HoursGroup hoursGroup) {
if (isSchedulingPoint()) {
taskSource.added(hoursGroup);
} else if (belongsToSchedulingPoint()) {
getParent().hoursGroupAdded(hoursGroup);
}
}
protected void hoursGroupDeleted(HoursGroup hoursGroup) {
if (isSchedulingPoint()) {
taskSource.removed(hoursGroup);
} else if (belongsToSchedulingPoint()) {
getParent().hoursGroupDeleted(hoursGroup);
}
}
private boolean isSchedulingPoint() {
return schedulingStateType == Type.SCHEDULING_POINT;
}
private boolean belongsToSchedulingPoint() {
return schedulingStateType.belongsToSchedulingPoint();
}
public abstract Integer getWorkHours();
public abstract List<HoursGroup> getHoursGroups();
@ -217,12 +294,8 @@ public abstract class OrderElement extends BaseEntity {
public abstract OrderLineGroup toContainer();
public Set<TaskElement> getTaskElements() {
return Collections.unmodifiableSet(taskElements);
}
public boolean isScheduled() {
return !taskElements.isEmpty();
return schedulingStateType.isSomewhatScheduled();
}
public boolean checkAtLeastOneHoursGroup() {
@ -537,4 +610,38 @@ public abstract class OrderElement extends BaseEntity {
}
return schedulingStateType;
}
public TaskSource getTaskSource() {
return taskSource;
}
public Set<TaskElement> getTaskElements() {
if (taskSource == null) {
return Collections.emptySet();
}
return Collections.singleton(taskSource.getTask());
}
public List<TaskSource> getTaskSourcesFromBottomToTop() {
List<TaskSource> result = new ArrayList<TaskSource>();
taskSourcesFromBottomToTop(result);
return result;
}
private void taskSourcesFromBottomToTop(List<TaskSource> result) {
if (isSchedulingPoint()) {
// checking taskSource is not null because the OrderElement might
// have not yet been saved, and the taskSources are created on save
if (taskSource != null) {
result.add(taskSource);
}
} else if (isSuperElementPartialOrCompletelyScheduled()) {
for (OrderElement each : getSomewhatScheduledOrderElements()) {
each.taskSourcesFromBottomToTop(result);
}
if (taskSource != null) {
result.add(taskSource);
}
}
}
}

View file

@ -24,7 +24,6 @@ import static org.navalplanner.business.i18n.I18nHelper._;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@ -122,13 +121,11 @@ public class OrderLine extends OrderElement {
hoursGroup.updateMyCriterionRequirements();
hoursGroups.add(hoursGroup);
recalculateHoursGroups();
hoursGroupAdded(hoursGroup);
}
public void deleteHoursGroup(HoursGroup hoursGroup) {
hoursGroups.remove(hoursGroup);
recalculateHoursGroups();
hoursGroupDeleted(hoursGroup);
}
/**
@ -156,7 +153,7 @@ public class OrderLine extends OrderElement {
hoursGroup.setWorkingHours(workHours);
hoursGroup.setPercentage((new BigDecimal(1).setScale(2)));
addHoursGroup(hoursGroup);
hoursGroups.add(hoursGroup);
} else {
if (!isTotalHoursValid(workHours)) {
@ -246,28 +243,12 @@ public class OrderLine extends OrderElement {
}
// Set the attribute with the new hours group calculated
deleteHoursGroups(hoursGroups);
addHoursGroups(newHoursGroups);
hoursGroups = newHoursGroups;
// Re-calculate percentages
recalculateHoursGroups();
}
private void addHoursGroups(Collection<? extends HoursGroup> newHoursGroups) {
hoursGroups.addAll(newHoursGroups);
for (HoursGroup each : newHoursGroups) {
hoursGroupAdded(each);
}
}
private void deleteHoursGroups(
Collection<? extends HoursGroup> oldHoursGroups) {
hoursGroups.removeAll(oldHoursGroups);
for (HoursGroup each : oldHoursGroups) {
hoursGroupDeleted(each);
}
}
/**
* Checks if the desired total number of hours is valid taking into account
* {@link HoursGroup} policy restrictions.

View file

@ -277,6 +277,10 @@ public class SchedulingState {
return type.isPartiallyScheduled();
}
public boolean isNoScheduled() {
return type == Type.NO_SCHEDULED;
}
public boolean isSomewhatScheduled() {
return type.isSomewhatScheduled();
}

View file

@ -19,25 +19,198 @@
*/
package org.navalplanner.business.orders.entities;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang.Validate;
import org.hibernate.validator.NotNull;
import org.navalplanner.business.common.BaseEntity;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.planner.daos.ITaskElementDAO;
import org.navalplanner.business.planner.daos.ITaskSourceDAO;
import org.navalplanner.business.planner.entities.Task;
import org.navalplanner.business.planner.entities.TaskElement;
import org.navalplanner.business.planner.entities.TaskGroup;
/**
* @author Óscar González Fernández <ogonzalez@igalia.com>
*/
public class TaskSource extends BaseEntity {
public static TaskSource create(OrderElement orderElement,
List<HoursGroup> hoursGroups) {
TaskSource result = create(new TaskSource(orderElement));
result.setHoursGroups(new HashSet<HoursGroup>(hoursGroups));
return result;
}
public static TaskSourceSynchronization mustAdd(
TaskSource taskSource) {
return new TaskSourceMustBeAdded(taskSource);
}
public static TaskSourceSynchronization mustAddGroup(TaskSource taskSource,
List<TaskSourceSynchronization> childrenOfGroup) {
return new TaskGroupMustBeAdded(taskSource, childrenOfGroup);
}
public static TaskSourceSynchronization mustRemove(TaskSource taskSource) {
return new TaskSourceMustBeRemoved(taskSource);
}
public static abstract class TaskSourceSynchronization {
public abstract TaskElement apply(ITaskSourceDAO taskSourceDAO);
protected void saveTaskSource(ITaskSourceDAO taskSourceDAO,
TaskSource taskSource) {
taskSourceDAO.save(taskSource);
}
}
static class TaskSourceMustBeAdded extends TaskSourceSynchronization {
private final TaskSource taskSource;
public TaskSourceMustBeAdded(TaskSource taskSource) {
this.taskSource = taskSource;
}
@Override
public TaskElement apply(ITaskSourceDAO taskSourceDAO) {
Task result = Task.createTask(taskSource);
taskSource.setTask(result);
taskSourceDAO.save(taskSource);
return result;
}
}
static class TaskSourceForTaskModified extends TaskSourceSynchronization {
private final TaskSource taskSource;
TaskSourceForTaskModified(TaskSource taskSource) {
this.taskSource = taskSource;
}
@Override
public TaskElement apply(ITaskSourceDAO taskSourceDAO) {
saveTaskSource(taskSourceDAO, taskSource);
return taskSource.getTask();
}
}
static abstract class TaskGroupSynchronization extends
TaskSourceSynchronization {
protected final TaskSource taskSource;
private final List<TaskSourceSynchronization> synchronizations;
TaskGroupSynchronization(TaskSource taskSource,
List<TaskSourceSynchronization> synchronizations) {
Validate.notNull(taskSource);
Validate.notNull(synchronizations);
this.taskSource = taskSource;
this.synchronizations = synchronizations;
}
@Override
public TaskElement apply(ITaskSourceDAO taskSourceDAO) {
List<TaskElement> children = getChildren(taskSourceDAO);
return apply(taskSourceDAO, children);
}
private List<TaskElement> getChildren(ITaskSourceDAO taskSourceDAO) {
List<TaskElement> result = new ArrayList<TaskElement>();
for (TaskSourceSynchronization each : synchronizations) {
TaskElement t = each.apply(taskSourceDAO);
if (t != null) {
// TaskSourceMustBeRemoved gives null
result.add(t);
}
}
return result;
}
protected abstract TaskElement apply(ITaskSourceDAO taskSourceDAO,
List<TaskElement> children);
}
static class TaskGroupMustBeAdded extends TaskGroupSynchronization {
private TaskGroupMustBeAdded(TaskSource taskSource,
List<TaskSourceSynchronization> synchronizations) {
super(taskSource, synchronizations);
}
@Override
protected TaskElement apply(ITaskSourceDAO taskSourceDAO,
List<TaskElement> children) {
TaskGroup result = TaskGroup.create(taskSource);
for (TaskElement taskElement : children) {
result.addTaskElement(taskElement);
}
taskSource.setTask(result);
saveTaskSource(taskSourceDAO, taskSource);
return result;
}
}
static class TaskSourceForTaskGroupModified extends
TaskGroupSynchronization {
TaskSourceForTaskGroupModified(TaskSource taskSource,
List<TaskSourceSynchronization> synchronizations) {
super(taskSource, synchronizations);
}
@Override
protected TaskElement apply(ITaskSourceDAO taskSourceDAO,
List<TaskElement> children) {
TaskGroup taskGroup = (TaskGroup) taskSource.getTask();
taskGroup.addChildren(children);
taskSourceDAO.save(taskSource);
return taskGroup;
}
}
static class TaskSourceMustBeRemoved extends TaskSourceSynchronization {
private final TaskSource taskSource;
public TaskSourceMustBeRemoved(TaskSource taskSource) {
this.taskSource = taskSource;
}
@Override
public TaskElement apply(ITaskSourceDAO taskSourceDAO) {
try {
taskSourceDAO.remove(taskSource.getId());
} catch (InstanceNotFoundException e) {
throw new RuntimeException(e);
}
return null;
}
}
public static TaskSource withHoursGroupOf(OrderElement orderElement) {
return create(new TaskSource(orderElement));
}
public static TaskSource createForGroup(OrderElement orderElement) {
return create(new TaskSource(orderElement));
}
@NotNull
private OrderElement orderElement;
@NotNull
private TaskElement task;
private Set<HoursGroup> hoursGroups = new HashSet<HoursGroup>();
public TaskSource() {
@ -45,17 +218,47 @@ public class TaskSource extends BaseEntity {
public TaskSource(OrderElement orderElement) {
Validate.notNull(orderElement);
this.setOrderElement(orderElement);
this.setHoursGroups(new HashSet<HoursGroup>(orderElement
.getHoursGroups()));
}
public TaskSourceSynchronization withCurrentHoursGroup(
List<HoursGroup> hoursGroups) {
setHoursGroups(new HashSet<HoursGroup>(hoursGroups));
return new TaskSourceForTaskModified(this);
}
public TaskSourceSynchronization modifyGroup(
List<TaskSourceSynchronization> childrenOfGroup) {
return new TaskSourceForTaskGroupModified(this, childrenOfGroup);
}
private void setTask(TaskElement task) {
this.task = task;
}
private void setOrderElement(OrderElement orderElement) {
this.orderElement = orderElement;
this.hoursGroups = new HashSet<HoursGroup>(orderElement
.getHoursGroups());
}
public void added(HoursGroup hoursGroup) {
hoursGroups.add(hoursGroup);
public TaskElement getTask() {
return task;
}
public void removed(HoursGroup hoursGroup) {
hoursGroups.remove(hoursGroup);
public OrderElement getOrderElement() {
return orderElement;
}
private void setHoursGroups(Set<HoursGroup> hoursGroups) {
this.hoursGroups = hoursGroups;
}
public Set<HoursGroup> getHoursGroups() {
return hoursGroups;
}
public void reloadTask(ITaskElementDAO taskElementDAO) {
taskElementDAO.save(task);
}
}

View file

@ -35,6 +35,8 @@ import org.joda.time.DateTime;
import org.joda.time.Days;
import org.joda.time.LocalDate;
import org.navalplanner.business.orders.entities.HoursGroup;
import org.navalplanner.business.orders.entities.OrderElement;
import org.navalplanner.business.orders.entities.TaskSource;
import org.navalplanner.business.planner.entities.allocationalgorithms.AllocationBeingModified;
import org.navalplanner.business.resources.entities.Criterion;
import org.navalplanner.business.resources.entities.Resource;
@ -45,10 +47,11 @@ import org.navalplanner.business.resources.entities.Worker;
*/
public class Task extends TaskElement {
public static Task createTask(HoursGroup hoursGroup) {
Task task = new Task(hoursGroup);
task.setNewObject(true);
return task;
public static Task createTask(TaskSource taskSource) {
Task task = new Task(taskSource.getHoursGroups().iterator().next());
OrderElement orderElement = taskSource.getOrderElement();
orderElement.applyStartConstraintIfNeededTo(task);
return create(task, taskSource);
}
@NotNull
@ -295,15 +298,13 @@ public class Task extends TaskElement {
List<ModifiedAllocation> copied = ModifiedAllocation
.copy(resourceAllocations);
List<AllocationBeingModified> allocations = AllocationBeingModified
.fromExistent(ModifiedAllocation
.modified(copied));
.fromExistent(ModifiedAllocation.modified(copied));
if (allocations.isEmpty()) {
return;
}
switch (calculatedValue) {
case NUMBER_OF_HOURS:
ResourceAllocation.allocating(allocations)
.withExistentResources()
ResourceAllocation.allocating(allocations).withExistentResources()
.allocateOnTaskLength();
break;
case END_DATE:
@ -326,4 +327,3 @@ public class Task extends TaskElement {
}
}

View file

@ -29,11 +29,11 @@ import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import org.apache.commons.lang.Validate;
import org.joda.time.LocalDate;
import org.navalplanner.business.calendars.entities.BaseCalendar;
import org.navalplanner.business.common.BaseEntity;
import org.navalplanner.business.orders.entities.OrderElement;
import org.navalplanner.business.orders.entities.TaskSource;
import org.navalplanner.business.planner.entities.Dependency.Type;
/**
@ -41,6 +41,19 @@ import org.navalplanner.business.planner.entities.Dependency.Type;
*/
public abstract class TaskElement extends BaseEntity {
protected static <T extends TaskElement> T create(T taskElement,
TaskSource taskSource) {
taskElement.taskSource = taskSource;
taskElement.setDeadline(new LocalDate(taskSource.getOrderElement()
.getDeadline()));
return create(taskElement);
}
protected static <T extends TaskElement> T createWithoutTaskSource(
T taskElement) {
return create(taskElement);
}
private Date startDate;
private Date endDate;
@ -55,14 +68,14 @@ public abstract class TaskElement extends BaseEntity {
protected Integer shareOfHours;
private OrderElement orderElement;
private Set<Dependency> dependenciesWithThisOrigin = new HashSet<Dependency>();
private Set<Dependency> dependenciesWithThisDestination = new HashSet<Dependency>();
private BaseCalendar calendar;
private TaskSource taskSource;
public Integer getWorkHours() {
if (shareOfHours != null) {
return shareOfHours;
@ -76,7 +89,12 @@ public abstract class TaskElement extends BaseEntity {
this.name = task.getName();
this.notes = task.getNotes();
this.startDate = task.getStartDate();
this.orderElement = task.getOrderElement();
this.taskSource = task.getTaskSource();
}
public TaskSource getTaskSource() {
return taskSource;
}
protected void copyDependenciesTo(TaskElement result) {
@ -116,18 +134,11 @@ public abstract class TaskElement extends BaseEntity {
this.notes = notes;
}
public void setOrderElement(OrderElement orderElement)
throws IllegalArgumentException, IllegalStateException {
Validate.notNull(orderElement, "orderElement must be not null");
if (this.orderElement != null) {
throw new IllegalStateException(
"once a orderElement is set, it cannot be changed");
}
this.orderElement = orderElement;
}
public OrderElement getOrderElement() {
return orderElement;
if (getTaskSource() == null) {
return null;
}
return getTaskSource().getOrderElement();
}
public Set<Dependency> getDependenciesWithThisOrigin() {

View file

@ -28,16 +28,16 @@ import java.util.Set;
import org.apache.commons.lang.Validate;
import org.hibernate.validator.AssertTrue;
import org.navalplanner.business.orders.entities.TaskSource;
/**
* @author Óscar González Fernández <ogonzalez@igalia.com>
*/
public class TaskGroup extends TaskElement {
public static TaskGroup create() {
public static TaskGroup create(TaskSource taskSource) {
TaskGroup taskGroup = new TaskGroup();
taskGroup.setNewObject(true);
return taskGroup;
return create(taskGroup, taskSource);
}
private List<TaskElement> taskElements = new ArrayList<TaskElement>();
@ -100,4 +100,21 @@ public class TaskGroup extends TaskElement {
protected void moveAllocations() {
// do nothing
}
public void addChildren(List<TaskElement> children) {
List<TaskElement> toRemove = new ArrayList<TaskElement>();
for (TaskElement each : taskElements) {
if (!children.contains(each)) {
toRemove.add(each);
}
}
taskElements.removeAll(toRemove);
for (TaskElement each : children) {
each.setParent(this);
if (!taskElements.contains(each)) {
taskElements.add(each);
}
}
}
}

View file

@ -29,7 +29,6 @@ import org.apache.commons.lang.Validate;
import org.hibernate.validator.AssertTrue;
import org.joda.time.DateTime;
import org.joda.time.Days;
import org.navalplanner.business.orders.entities.OrderElement;
/**
* @author Lorenzo Tilve Álvaro <ltilve@igalia.com>
@ -38,8 +37,7 @@ public class TaskMilestone extends TaskElement {
public static TaskMilestone create() {
TaskMilestone milestone = new TaskMilestone();
milestone.setNewObject(true);
return milestone;
return createWithoutTaskSource(milestone);
}
private CalculatedValue calculatedValue = CalculatedValue.END_DATE;
@ -98,14 +96,6 @@ public class TaskMilestone extends TaskElement {
return new DateTime(startDate.getTime());
}
@Override
public void setOrderElement(OrderElement orderElement)
throws IllegalStateException {
throw new IllegalStateException(
"milestones can't have orderElements associated");
}
@Override
public Integer defaultWorkHours() {
return Integer.valueOf(0);

View file

@ -21,10 +21,6 @@
<param name="enumClass">org.navalplanner.business.orders.entities.SchedulingState$Type</param>
</type>
</property>
<set name="taskElements" access="field" cascade="delete">
<key column="ORDER_ELEMENT_ID" />
<one-to-many class="org.navalplanner.business.planner.entities.TaskElement"></one-to-many>
</set>
<set name="directAdvanceAssignments" access="field" cascade="all,delete-orphan" inverse="true">
<key column="DIRECT_ORDER_ELEMENT_ID" />
<one-to-many class="org.navalplanner.business.advance.entities.DirectAdvanceAssignment" />
@ -43,7 +39,7 @@
<!-- Inverse navigation from OrderElement to OrderLineGroup -->
<many-to-one name="parent" access="field" cascade="all"/>
<one-to-one name="taskSource" class="TaskSource" access="field" cascade="all"/>
<one-to-one name="taskSource" class="TaskSource" access="field" property-ref="orderElement"/>
<joined-subclass name="OrderLineGroup">
<key column="ORDERELEMENTID"></key>
@ -104,15 +100,17 @@
<class name="TaskSource">
<id name="id" access="property" type="long">
<generator class="foreign">
<param name="property">orderElement</param>
<param name="property">task</param>
</generator>
</id>
<version name="version" access="property" type="long" />
<one-to-one name="orderElement"
<many-to-one name="orderElement"
class="OrderElement" cascade="none"
constrained="true" access="field"/>
unique="true" access="field"/>
<set name="hoursGroups" table="task_source_hours_groups" lazy="false" cascade="none" inverse="false" access="field">
<one-to-one name="task" class="org.navalplanner.business.planner.entities.TaskElement"
constrained="true" cascade="all" access="field" lazy="false"/>
<set name="hoursGroups" table="task_source_hours_groups" cascade="none" inverse="false" access="field">
<key column="TASK_SOURCE_ID"></key>
<many-to-many class="HoursGroup" column="HOURS_GROUP_ID"/>
</set>

View file

@ -16,10 +16,10 @@
<property name="endDate" type="timestamp" />
<property name="deadline" type="org.joda.time.contrib.hibernate.PersistentLocalDate" />
<many-to-one name="orderElement" cascade="none" column="ORDER_ELEMENT_ID" not-null="false" />
<many-to-one name="parent" class="TaskGroup" cascade="none" column="parent"/>
<one-to-one name="taskSource" cascade="none"/>
<set name="dependenciesWithThisOrigin" cascade="all">
<key column="ORIGIN"></key>
<one-to-many class="Dependency" />

View file

@ -27,6 +27,7 @@ import static org.junit.Assert.assertTrue;
import static org.navalplanner.business.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_FILE;
import static org.navalplanner.business.test.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_TEST_FILE;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
@ -37,8 +38,11 @@ import org.navalplanner.business.orders.daos.IHoursGroupDAO;
import org.navalplanner.business.orders.daos.IOrderElementDAO;
import org.navalplanner.business.orders.entities.HoursGroup;
import org.navalplanner.business.orders.entities.OrderLine;
import org.navalplanner.business.orders.entities.TaskSource;
import org.navalplanner.business.orders.entities.TaskSource.TaskSourceSynchronization;
import org.navalplanner.business.planner.daos.IResourceAllocationDAO;
import org.navalplanner.business.planner.daos.ITaskElementDAO;
import org.navalplanner.business.planner.daos.ITaskSourceDAO;
import org.navalplanner.business.planner.entities.GenericResourceAllocation;
import org.navalplanner.business.planner.entities.ResourceAllocation;
import org.navalplanner.business.planner.entities.ResourcesPerDay;
@ -77,6 +81,9 @@ public class ResourceAllocationDAOTest {
@Autowired
private IWorkerDAO workerDAO;
@Autowired
private ITaskSourceDAO taskSourceDAO;
@Autowired
IResourceDAO resourceDAO;
@ -104,18 +111,22 @@ public class ResourceAllocationDAOTest {
private ResourceAllocation<?> createValidResourceAllocation(
ResourceAllocationType type) {
OrderLine orderLine = createValidOrderLine();
orderLine.getSchedulingState().schedule();
orderElementDAO.save(orderLine);
HoursGroup hoursGroup = HoursGroup.create(orderLine);
hoursGroupDAO.save(hoursGroup);
Task task = Task.createTask(hoursGroup);
task.setOrderElement(orderLine);
taskElementDAO.save(task);
List<HoursGroup> hoursGroups = Arrays.asList(hoursGroup);
TaskSource taskSource = TaskSource.create(orderLine, hoursGroups);
TaskSourceSynchronization synchronization = TaskSource
.mustAdd(taskSource);
synchronization.apply(taskSourceDAO);
Task task = (Task) taskSource.getTask();
if (ResourceAllocationType.SPECIFIC_RESOURCE_ALLOCATION.equals(type)) {
SpecificResourceAllocation specificResourceAllocation = SpecificResourceAllocation
.createForTesting(ResourcesPerDay.amount(1), task);
.createForTesting(ResourcesPerDay.amount(1),
task);
Worker worker = (Worker) createValidWorker();
resourceDAO.save(worker);
specificResourceAllocation.setResource(worker);
@ -125,10 +136,8 @@ public class ResourceAllocationDAOTest {
if (ResourceAllocationType.GENERIC_RESOURCE_ALLOCATION.equals(type)) {
GenericResourceAllocation specificResourceAllocation = GenericResourceAllocation
.createForTesting(ResourcesPerDay.amount(1), task);
return specificResourceAllocation;
}
return null;
}

View file

@ -29,6 +29,8 @@ import static org.junit.Assert.assertTrue;
import static org.navalplanner.business.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_FILE;
import static org.navalplanner.business.test.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_TEST_FILE;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
@ -39,6 +41,8 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.navalplanner.business.IDataBootstrap;
import org.navalplanner.business.common.IAdHocTransactionService;
import org.navalplanner.business.common.IOnTransaction;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.navalplanner.business.orders.daos.IOrderDAO;
@ -46,7 +50,10 @@ import org.navalplanner.business.orders.entities.HoursGroup;
import org.navalplanner.business.orders.entities.Order;
import org.navalplanner.business.orders.entities.OrderElement;
import org.navalplanner.business.orders.entities.OrderLine;
import org.navalplanner.business.orders.entities.TaskSource;
import org.navalplanner.business.orders.entities.TaskSource.TaskSourceSynchronization;
import org.navalplanner.business.planner.daos.ITaskElementDAO;
import org.navalplanner.business.planner.daos.ITaskSourceDAO;
import org.navalplanner.business.planner.daos.TaskElementDAO;
import org.navalplanner.business.planner.entities.Dependency;
import org.navalplanner.business.planner.entities.Task;
@ -55,6 +62,7 @@ import org.navalplanner.business.planner.entities.TaskGroup;
import org.navalplanner.business.planner.entities.TaskMilestone;
import org.navalplanner.business.planner.entities.Dependency.Type;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.NotTransactional;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
@ -84,17 +92,27 @@ public class TaskElementDAOTest {
@Autowired
private IOrderDAO orderDAO;
@Autowired
private ITaskSourceDAO taskSourceDAO;
@Autowired
private SessionFactory sessionFactory;
@Autowired
private IAdHocTransactionService transactionService;
private HoursGroup associatedHoursGroup;
private Task createValidTask() {
associatedHoursGroup = new HoursGroup();
Task task = Task.createTask(associatedHoursGroup);
OrderLine orderLine = createOrderLine();
orderLine.addHoursGroup(associatedHoursGroup);
task.setOrderElement(orderLine);
TaskSource taskSource = TaskSource
.create(orderLine, Arrays
.asList(associatedHoursGroup));
TaskSourceSynchronization mustAdd = TaskSource.mustAdd(taskSource);
mustAdd.apply(taskSourceDAO);
Task task = (Task) taskSource.getTask();
return task;
}
@ -118,10 +136,13 @@ public class TaskElementDAOTest {
}
private TaskGroup createValidTaskGroup() {
TaskGroup result = TaskGroup.create();
OrderLine orderLine = createOrderLine();
result.setOrderElement(orderLine);
return result;
TaskSource taskSource = TaskSource.createForGroup(orderLine);
TaskSourceSynchronization synchronization = TaskSource
.mustAddGroup(taskSource, Collections
.<TaskSourceSynchronization> emptyList());
synchronization.apply(taskSourceDAO);
return (TaskGroup) taskSource.getTask();
}
private TaskMilestone createValidTaskMilestone() {
@ -236,56 +257,51 @@ public class TaskElementDAOTest {
}
@Test
public void savingTaskElementSavesAssociatedDependencies() {
Task child1 = createValidTask();
Task child2 = createValidTask();
taskElementDAO.save(child2);
Task oldChild2 = child2;
flushAndEvict(child2);
try {
child2 = (Task) taskElementDAO.find(child2.getId());
} catch (InstanceNotFoundException e) {
throw new RuntimeException(e);
}
Dependency.create(child1, oldChild2, Type.START_END);
taskElementDAO.save(child1);
oldChild2.dontPoseAsTransientObjectAnymore();
flushAndEvict(child1);
TaskElement child1Reloaded;
try {
child1Reloaded = (TaskElement) taskElementDAO.find(child1.getId());
} catch (InstanceNotFoundException e) {
throw new RuntimeException(e);
}
assertThat(child1Reloaded.getDependenciesWithThisOrigin().size(),
equalTo(1));
assertTrue(child1Reloaded.getDependenciesWithThisDestination()
.isEmpty());
@NotTransactional
public void savingTaskElementSavesAssociatedDependencies()
throws InstanceNotFoundException {
IOnTransaction<Task> createValidTask = new IOnTransaction<Task>() {
@Override
public Task execute() {
return createValidTask();
}
};
final Task child1 = transactionService
.runOnTransaction(createValidTask);
final Task child2 = transactionService
.runOnTransaction(createValidTask);
IOnTransaction<Void> createDependency = new IOnTransaction<Void>() {
@Override
public Void execute() {
child1.dontPoseAsTransientObjectAnymore();
child2.dontPoseAsTransientObjectAnymore();
Dependency.create(child1, child2, Type.START_END);
taskElementDAO.save(child1);
return null;
}
};
transactionService.runOnTransaction(createDependency);
assertThat(child2.getDependenciesWithThisDestination().size(),
equalTo(1));
assertTrue(child2.getDependenciesWithThisOrigin().isEmpty());
IOnTransaction<Void> checkDependencyWasSaved = new IOnTransaction<Void>() {
@Override
public Void execute() {
TaskElement fromDB = (TaskElement) taskElementDAO
.findExistingEntity(child1.getId());
assertThat(fromDB.getDependenciesWithThisOrigin()
.size(), equalTo(1));
assertTrue(fromDB.getDependenciesWithThisDestination()
.isEmpty());
return null;
}
};
transactionService.runOnTransaction(checkDependencyWasSaved);
}
@Test
public void testInverseManyToOneRelationshipInOrderElement() {
Task task = createValidTask();
taskElementDAO.save(task);
flushAndEvict(task);
sessionFactory.getCurrentSession().evict(task.getOrderElement());
TaskElement fromDB;
try {
fromDB = taskElementDAO.find(task.getId());
} catch (InstanceNotFoundException e) {
throw new RuntimeException(e);
}
OrderElement orderElement = fromDB.getOrderElement();
assertThat(orderElement.getTaskElements().size(), equalTo(1));
assertThat(orderElement.getTaskElements().iterator().next(),
equalTo(fromDB));
}
@Test
public void aTaskCanBeRemoved() {
Task task = createValidTask();
taskElementDAO.save(task);
@ -300,23 +316,93 @@ public class TaskElementDAOTest {
task.getId()));
}
@Test
public void aTaskGroupCanBeRemoved() {
TaskGroup taskGroup = createValidTaskGroup();
Task task = createValidTask();
taskGroup.addTaskElement(task);
taskElementDAO.save(taskGroup);
flushAndEvict(taskGroup);
try {
taskElementDAO.remove(taskGroup.getId());
} catch (InstanceNotFoundException e) {
throw new RuntimeException(e);
}
sessionFactory.getCurrentSession().flush();
assertNull(sessionFactory.getCurrentSession().get(TaskGroup.class,
taskGroup.getId()));
assertNull(sessionFactory.getCurrentSession().get(TaskElement.class,
task.getId()));
@NotTransactional
public void testInverseManyToOneRelationshipInOrderElementIsSavedCorrectly() {
final Task task = transactionService
.runOnTransaction(new IOnTransaction<Task>() {
@Override
public Task execute() {
return createValidTask();
}
});
transactionService.runOnReadOnlyTransaction(new IOnTransaction<Void>() {
@Override
public Void execute() {
TaskElement fromDB = taskElementDAO.findExistingEntity(task
.getId());
OrderElement orderElement = fromDB.getOrderElement();
assertThat(orderElement.getTaskElements().size(), equalTo(1));
assertThat(orderElement.getTaskElements().iterator().next(),
equalTo(fromDB));
return null;
}
});
}
@Test
@NotTransactional
public void aTaskCanBeRemovedFromItsTaskSource() {
final Task task = transactionService.runOnTransaction(new IOnTransaction<Task>(){
@Override
public Task execute() {
Task task = createValidTask();
taskElementDAO.save(task);
return task;
}});
transactionService.runOnTransaction(new IOnTransaction<Void>() {
@Override
public Void execute() {
try {
taskSourceDAO.remove(task.getTaskSource().getId());
} catch (InstanceNotFoundException e) {
throw new RuntimeException(e);
}
sessionFactory.getCurrentSession().flush();
assertNull(sessionFactory.getCurrentSession().get(TaskElement.class,
task.getId()));
return null;
}});
}
@Test
@NotTransactional
public void aTaskGroupCanBeRemovedFromItsTaskSourceIfBelowTasksSourcesAreRemovedFirst() {
final TaskGroup taskGroupWithOneChild = transactionService
.runOnTransaction(new IOnTransaction<TaskGroup>() {
@Override
public TaskGroup execute() {
TaskGroup taskGroup = createValidTaskGroup();
Task task = createValidTask();
taskGroup.addTaskElement(task);
return taskGroup;
}
});
transactionService.runOnTransaction(new IOnTransaction<Void>() {
@Override
public Void execute() {
try {
taskSourceDAO.remove(taskGroupWithOneChild.getChildren()
.get(0).getTaskSource().getId());
} catch (InstanceNotFoundException e) {
throw new RuntimeException(e);
}
try {
taskSourceDAO.remove(taskGroupWithOneChild.getTaskSource()
.getId());
} catch (InstanceNotFoundException e) {
throw new RuntimeException(e);
}
sessionFactory.getCurrentSession().flush();
assertNull(sessionFactory.getCurrentSession().get(
TaskElement.class, taskGroupWithOneChild.getId()));
return null;
}
});
}
}

View file

@ -20,28 +20,40 @@
package org.navalplanner.business.test.planner.entities;
import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertSame;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.navalplanner.business.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_FILE;
import static org.navalplanner.business.test.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_TEST_FILE;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import javax.annotation.Resource;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.joda.time.LocalDate;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.navalplanner.business.IDataBootstrap;
import org.navalplanner.business.orders.entities.HoursGroup;
import org.navalplanner.business.orders.entities.Order;
import org.navalplanner.business.orders.entities.OrderLine;
import org.navalplanner.business.orders.entities.OrderLineGroup;
import org.navalplanner.business.orders.entities.TaskSource;
import org.navalplanner.business.planner.entities.Dependency;
import org.navalplanner.business.planner.entities.StartConstraintType;
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;
import org.navalplanner.business.planner.entities.TaskStartConstraint;
import org.navalplanner.business.planner.entities.Dependency.Type;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@ -66,32 +78,11 @@ public class TaskElementTest {
private TaskElement task = new Task();
private TaskElement taskWithOrderLine;
private Dependency exampleDependency;
public TaskElementTest() {
this.taskWithOrderLine = new Task();
this.taskWithOrderLine.setOrderElement(OrderLine.create());
this.exampleDependency = Dependency.create(new Task(),
new Task(), Type.END_START);
}
@Test
public void taskElementHasAOneToOneRelationshipWithOrderElement() {
OrderLine order = OrderLine.create();
task.setOrderElement(order);
assertSame(order, task.getOrderElement());
}
@Test(expected = IllegalArgumentException.class)
public void orderElementCannotBeSetToNull() {
task.setOrderElement(null);
}
@Test(expected = IllegalStateException.class)
public void onceSetOrderElementCannotBeChanged() {
taskWithOrderLine.setOrderElement(OrderLine.create());
this.exampleDependency = Dependency.create(new Task(), new Task(),
Type.END_START);
}
@Test
@ -124,8 +115,7 @@ public class TaskElementTest {
Task origin = new Task();
Task destination = new Task();
Type type = Type.START_END;
Dependency.create(origin,
destination, type);
Dependency.create(origin, destination, type);
assertThat(origin.getDependenciesWithThisOrigin().size(), equalTo(1));
assertThat(destination.getDependenciesWithThisDestination().size(),
equalTo(1));
@ -135,50 +125,19 @@ public class TaskElementTest {
equalTo(0));
}
private void checkPopertiesAreKept(TaskElement original, TaskElement result) {
assertThat(result.getName(), equalTo(original.getName()));
assertThat(result.getNotes(), equalTo(original.getNotes()));
assertThat(result.getStartDate(), equalTo(original.getStartDate()));
assertThat(result.getOrderElement(),
equalTo(original.getOrderElement()));
}
private void checkDependenciesAreKept(
TaskElement taskResultOfTransformation, Task sourceDependencyTask,
Task destinationDependencyTask) {
assertThat(taskResultOfTransformation
.getDependenciesWithThisDestination().size(), equalTo(1));
Dependency withTaskResultOfSplitDestination = taskResultOfTransformation
.getDependenciesWithThisDestination().iterator().next();
assertThat(withTaskResultOfSplitDestination.getDestination(),
equalTo((TaskElement) taskResultOfTransformation));
assertThat(withTaskResultOfSplitDestination.getOrigin(),
equalTo((TaskElement) sourceDependencyTask));
assertThat(taskResultOfTransformation.getDependenciesWithThisOrigin()
.size(), equalTo(1));
Dependency withTaskResultOfSplitSource = taskResultOfTransformation
.getDependenciesWithThisOrigin().iterator().next();
assertThat(withTaskResultOfSplitSource.getDestination(),
equalTo((TaskElement) destinationDependencyTask));
assertThat(withTaskResultOfSplitSource.getOrigin(),
equalTo((TaskElement) taskResultOfTransformation));
}
private void addDependenciesForChecking(TaskElement taskBeingTransformed,
TaskElement sourceDependencyTask,
TaskElement destinationDependencyTask) {
Dependency.create(sourceDependencyTask, taskBeingTransformed,
Type.END_START);
Dependency.create(taskBeingTransformed,
destinationDependencyTask, Type.END_START);
Dependency.create(taskBeingTransformed, destinationDependencyTask,
Type.END_START);
}
public void detachRemovesDependenciesFromRelatedTasks() {
HoursGroup hoursGroup = new HoursGroup();
Task taskToDetach = Task.createTask(hoursGroup);
Task sourceDependencyTask = Task.createTask(new HoursGroup());
Task destinationDependencyTask = Task.createTask(new HoursGroup());
Task taskToDetach = (Task) TaskTest.createValidTask();
Task sourceDependencyTask = (Task) TaskTest.createValidTask();
Task destinationDependencyTask = (Task) TaskTest.createValidTask();
taskToDetach.setName("prueba");
taskToDetach.setNotes("blabla");
taskToDetach.setStartDate(new Date());
@ -193,10 +152,9 @@ public class TaskElementTest {
@Test
public void detachRemovesTaskFromParent() {
TaskGroup parent = TaskGroup.create();
HoursGroup hoursGroup = new HoursGroup();
Task child = Task.createTask(hoursGroup);
Task anotherChild = Task.createTask(hoursGroup);
TaskGroup parent = TaskGroupTest.createValidTaskGroup();
Task child = (Task) TaskTest.createValidTask();
Task anotherChild = (Task) TaskTest.createValidTask();
parent.addTaskElement(child);
parent.addTaskElement(anotherChild);
child.detach();
@ -205,14 +163,124 @@ public class TaskElementTest {
@Test
public void MilestoneOrderElementIsNull() {
TaskMilestone milestone = new TaskMilestone();
OrderLine orderLine = OrderLine.create();
try {
milestone.setOrderElement(orderLine);
} catch (IllegalStateException e) {
// Ok Exception expected
} finally {
assertTrue(milestone.getOrderElement() == null);
}
TaskMilestone milestone = TaskMilestone.create();
assertThat(milestone.getOrderElement(), nullValue());
}
@Test
public void theDeadlineOfTheOrderElementIsCopied() {
OrderLine orderLine = OrderLine.create();
LocalDate deadline = new LocalDate(2007, 4, 4);
orderLine.setDeadline(asDate(deadline));
TaskSource taskSource = asTaskSource(orderLine);
Task task = Task.createTask(taskSource);
assertThat(task.getDeadline(), equalTo(deadline));
}
private TaskSource asTaskSource(OrderLine orderLine) {
List<HoursGroup> hoursGroups = orderLine.getHoursGroups();
if (hoursGroups.isEmpty()) {
hoursGroups = Collections.singletonList(createHoursGroup(100));
}
return TaskSource.create(orderLine, hoursGroups);
}
private static Date asDate(LocalDate localDate) {
return localDate.toDateTimeAtStartOfDay().toDate();
}
private static HoursGroup createHoursGroup(int hours) {
HoursGroup result = new HoursGroup();
result.setWorkingHours(hours);
return result;
}
@Test
public void ifNoParentWithStartDateTheStartConstraintIsSoonAsPossible() {
OrderLine orderLine = OrderLine.create();
LocalDate deadline = new LocalDate(2007, 4, 4);
orderLine.setDeadline(asDate(deadline));
TaskSource taskSource = asTaskSource(orderLine);
Task task = Task.createTask(taskSource);
assertThat(task.getStartConstraint(),
isOfType(StartConstraintType.AS_SOON_AS_POSSIBLE));
}
@Test
@SuppressWarnings("unchecked")
public void ifSomeParentHasInitDateTheStartConstraintIsNotEarlierThan() {
Date initDate = asDate(new LocalDate(2005, 10, 5));
OrderLineGroup group = OrderLineGroup.create();
group.setInitDate(initDate);
OrderLine orderLine = OrderLine.create();
group.add(orderLine);
LocalDate deadline = new LocalDate(2007, 4, 4);
orderLine.setDeadline(asDate(deadline));
TaskSource taskSource = asTaskSource(orderLine);
Task task = Task.createTask(taskSource);
assertThat(task.getStartConstraint(), allOf(
isOfType(StartConstraintType.START_NOT_EARLIER_THAN),
hasValue(initDate)));
}
@Test
public void unlessTheOnlyParentWithInitDateNotNullIsTheOrder() {
Date initDate = asDate(new LocalDate(2005, 10, 5));
Order order = Order.create();
order.setInitDate(initDate);
OrderLine orderLine = OrderLine.create();
order.add(orderLine);
LocalDate deadline = new LocalDate(2007, 4, 4);
orderLine.setDeadline(asDate(deadline));
TaskSource taskSource = asTaskSource(orderLine);
Task task = Task.createTask(taskSource);
assertThat(task.getStartConstraint(),
isOfType(StartConstraintType.AS_SOON_AS_POSSIBLE));
}
private static Matcher<TaskStartConstraint> isOfType(
final StartConstraintType type) {
return new BaseMatcher<TaskStartConstraint>() {
@Override
public boolean matches(Object object) {
if (object instanceof TaskStartConstraint) {
TaskStartConstraint startConstraint = (TaskStartConstraint) object;
return startConstraint.getStartConstraintType() == type;
}
return false;
}
@Override
public void describeTo(Description description) {
description.appendText("the start constraint must be of type "
+ type);
}
};
}
private static Matcher<TaskStartConstraint> hasValue(final Date value) {
return new BaseMatcher<TaskStartConstraint>() {
@Override
public boolean matches(Object object) {
if (object instanceof TaskStartConstraint) {
TaskStartConstraint startConstraint = (TaskStartConstraint) object;
Date constraintDate = startConstraint.getConstraintDate();
boolean bothNotNull = value != null
&& constraintDate != null;
return value == constraintDate || bothNotNull
&& constraintDate.equals(value);
}
return false;
}
@Override
public void describeTo(Description description) {
description.appendText("the start constraint must have date "
+ value);
}
};
}
}

View file

@ -29,6 +29,8 @@ import java.util.List;
import org.junit.Test;
import org.navalplanner.business.orders.entities.HoursGroup;
import org.navalplanner.business.orders.entities.OrderLine;
import org.navalplanner.business.orders.entities.TaskSource;
import org.navalplanner.business.planner.entities.Task;
import org.navalplanner.business.planner.entities.TaskElement;
import org.navalplanner.business.planner.entities.TaskGroup;
@ -37,7 +39,7 @@ import org.navalplanner.business.planner.entities.TaskGroup;
* @author Óscar González Fernández <ogonzalez@igalia.com>
*/
public class TaskGroupTest {
private TaskGroup taskGroup = TaskGroup.create();
private TaskGroup taskGroup = createValidTaskGroup();
@Test
public void taskGroupIsAnInstanceOfTaskElement() {
@ -51,7 +53,7 @@ public class TaskGroupTest {
.isEmpty());
TaskElement child1 = new Task();
taskGroup.addTaskElement(child1);
TaskGroup child2 = TaskGroup.create();
TaskGroup child2 = createValidTaskGroup();
taskGroup.addTaskElement(child2);
List<TaskElement> taskElements = taskGroup.getChildren();
assertThat(taskElements.size(), equalTo(2));
@ -61,7 +63,7 @@ public class TaskGroupTest {
@Test
public void addingTaskElementToTaskGroupSetsTheParentProperty() {
Task child = Task.createTask(new HoursGroup());
Task child = TaskTest.createValidTask();
taskGroup.addTaskElement(child);
assertThat(child.getParent(), equalTo(taskGroup));
}
@ -75,4 +77,13 @@ public class TaskGroupTest {
public void taskElementsCollectionCannotBeModified() {
taskGroup.getChildren().set(0, null);
}
public static TaskGroup createValidTaskGroup() {
HoursGroup hoursGroup = new HoursGroup();
hoursGroup.setWorkingHours(3);
TaskSource taskSource = TaskSource.create(OrderLine.create(), Arrays
.asList(hoursGroup));
return TaskGroup.create(taskSource);
}
}

View file

@ -28,8 +28,12 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import org.junit.Test;
import org.navalplanner.business.orders.entities.HoursGroup;
import org.navalplanner.business.orders.entities.OrderLine;
import org.navalplanner.business.orders.entities.TaskSource;
import org.navalplanner.business.planner.entities.ResourceAllocation;
import org.navalplanner.business.planner.entities.SpecificResourceAllocation;
import org.navalplanner.business.planner.entities.Task;
@ -46,7 +50,9 @@ public class TaskTest {
public TaskTest() {
hoursGroup = new HoursGroup();
hoursGroup.setWorkingHours(3);
task = Task.createTask(hoursGroup);
TaskSource taskSource = TaskSource.create(OrderLine.create(), Arrays
.asList(hoursGroup));
task = Task.createTask(taskSource);
}
@Test
@ -65,10 +71,12 @@ public class TaskTest {
assertNotNull(hoursGroup);
}
public static TaskElement createValidTask() {
HoursGroup hours = new HoursGroup();
hours.setWorkingHours(20);
return Task.createTask(hours);
public static Task createValidTask() {
HoursGroup hoursGroup = new HoursGroup();
hoursGroup.setWorkingHours(3);
TaskSource taskSource = TaskSource.create(OrderLine.create(), Arrays
.asList(hoursGroup));
return Task.createTask(taskSource);
}
@Test

View file

@ -46,6 +46,10 @@ import org.navalplanner.business.orders.entities.IOrderLineGroup;
import org.navalplanner.business.orders.entities.Order;
import org.navalplanner.business.orders.entities.OrderElement;
import org.navalplanner.business.orders.entities.OrderLineGroup;
import org.navalplanner.business.orders.entities.TaskSource;
import org.navalplanner.business.orders.entities.TaskSource.TaskSourceSynchronization;
import org.navalplanner.business.planner.daos.ITaskElementDAO;
import org.navalplanner.business.planner.daos.ITaskSourceDAO;
import org.navalplanner.business.requirements.entities.DirectCriterionRequirement;
import org.navalplanner.business.resources.daos.ICriterionDAO;
import org.navalplanner.business.resources.daos.ICriterionTypeDAO;
@ -91,8 +95,14 @@ public class OrderModel implements IOrderModel {
@Autowired
private IOrderElementDAO orderElementDAO;
@Autowired
private ITaskSourceDAO taskSourceDAO;
private Set<Label> cacheLabels = new HashSet<Label>();
@Autowired
private ITaskElementDAO taskElementDAO;
@Override
public List<Label> getLabels() {
final List<Label> result = new ArrayList<Label>();
@ -231,10 +241,25 @@ public class OrderModel implements IOrderModel {
@Transactional
public void save() throws ValidationException {
reattachCriterions();
reattachTasksForTasksSources();
this.orderDAO.save(order);
synchronizeWithSchedule(order);
deleteOrderElementWithoutParent();
}
private void reattachTasksForTasksSources() {
for (TaskSource each : order.getTaskSourcesFromBottomToTop()) {
each.reloadTask(taskElementDAO);
}
}
private void synchronizeWithSchedule(OrderElement orderElement) {
for (TaskSourceSynchronization each : order
.calculateSynchronizationsNeeded()) {
each.apply(taskSourceDAO);
}
}
private void deleteOrderElementWithoutParent() throws ValidationException {
List<OrderElement> listToBeRemoved = orderElementDAO
.findWithoutParent();

View file

@ -413,10 +413,4 @@ public class OrderModelTest {
orderModel.save();
}
private HoursGroup createHoursGroup(int hours) {
HoursGroup result = new HoursGroup();
result.setWorkingHours(hours);
return result;
}
}