diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/LeftTasksTreeRow.java b/ganttzk/src/main/java/org/zkoss/ganttz/LeftTasksTreeRow.java index b4d5ad708..aafe0c38d 100644 --- a/ganttzk/src/main/java/org/zkoss/ganttz/LeftTasksTreeRow.java +++ b/ganttzk/src/main/java/org/zkoss/ganttz/LeftTasksTreeRow.java @@ -25,7 +25,6 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.text.DateFormat; import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; import java.util.List; @@ -36,6 +35,8 @@ import org.apache.commons.logging.LogFactory; import org.joda.time.LocalDate; import org.zkoss.ganttz.adapters.IDisabilityConfiguration; import org.zkoss.ganttz.data.GanttDate; +import org.zkoss.ganttz.data.ITaskFundamentalProperties.IModifications; +import org.zkoss.ganttz.data.ITaskFundamentalProperties.IUpdatablePosition; import org.zkoss.ganttz.data.Task; import org.zkoss.ganttz.util.ComponentsFinder; import org.zkoss.util.Locales; @@ -377,8 +378,15 @@ public class LeftTasksTreeRow extends GenericForwardComposer { } } else if (updatedComponent == getStartDateTextBox()) { try { - Date begin = dateFormat.parse(getStartDateTextBox().getValue()); - task.moveTo(GanttDate.createFrom(begin)); + final Date begin = dateFormat.parse(getStartDateTextBox() + .getValue()); + task.doPositionModifications(new IModifications() { + + @Override + public void doIt(IUpdatablePosition position) { + position.moveTo(GanttDate.createFrom(begin)); + } + }); } catch (ParseException e) { getStartDateTextBox().setValue( dateFormat.format(task.getBeginDate() diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/TaskComponent.java b/ganttzk/src/main/java/org/zkoss/ganttz/TaskComponent.java index 1ea4dcdef..9770a3935 100644 --- a/ganttzk/src/main/java/org/zkoss/ganttz/TaskComponent.java +++ b/ganttzk/src/main/java/org/zkoss/ganttz/TaskComponent.java @@ -34,6 +34,8 @@ import org.joda.time.DateTime; import org.joda.time.LocalDate; import org.zkoss.ganttz.adapters.IDisabilityConfiguration; import org.zkoss.ganttz.data.GanttDate; +import org.zkoss.ganttz.data.ITaskFundamentalProperties.IModifications; +import org.zkoss.ganttz.data.ITaskFundamentalProperties.IUpdatablePosition; import org.zkoss.ganttz.data.Milestone; import org.zkoss.ganttz.data.Task; import org.zkoss.ganttz.data.Task.IReloadResourcesTextRequested; @@ -343,8 +345,14 @@ public class TaskComponent extends Div implements AfterCompose { void doUpdatePosition(int leftX, int topY) { GanttDate startBeforeMoving = this.task.getBeginDate(); - LocalDate newPosition = getMapper().toDate(leftX); - this.task.moveTo(GanttDate.createFrom(newPosition)); + final LocalDate newPosition = getMapper().toDate(leftX); + this.task.doPositionModifications(new IModifications() { + + @Override + public void doIt(IUpdatablePosition position) { + position.moveTo(GanttDate.createFrom(newPosition)); + } + }); boolean remainsInOriginalPosition = this.task.getBeginDate().equals( startBeforeMoving); if (remainsInOriginalPosition) { diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/TaskEditFormComposer.java b/ganttzk/src/main/java/org/zkoss/ganttz/TaskEditFormComposer.java index 7209db8dd..85679aee6 100644 --- a/ganttzk/src/main/java/org/zkoss/ganttz/TaskEditFormComposer.java +++ b/ganttzk/src/main/java/org/zkoss/ganttz/TaskEditFormComposer.java @@ -25,6 +25,8 @@ import java.util.Date; import org.joda.time.LocalDate; import org.zkoss.ganttz.data.GanttDate; +import org.zkoss.ganttz.data.ITaskFundamentalProperties.IModifications; +import org.zkoss.ganttz.data.ITaskFundamentalProperties.IUpdatablePosition; import org.zkoss.ganttz.data.Task; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.util.GenericForwardComposer; @@ -120,12 +122,19 @@ public class TaskEditFormComposer extends GenericForwardComposer { return localDate.toDateTimeAtStartOfDay().toDate(); } - private void copyFromDTO(TaskDTO taskDTO, Task currentTask, + private void copyFromDTO(final TaskDTO taskDTO, Task currentTask, boolean copyDates) { currentTask.setName(taskDTO.name); if (copyDates) { - currentTask.setBeginDate(GanttDate.createFrom(taskDTO.beginDate)); - currentTask.resizeTo(GanttDate.createFrom(taskDTO.endDate)); + currentTask.doPositionModifications(new IModifications() { + + @Override + public void doIt(IUpdatablePosition position) { + position.setBeginDate(GanttDate + .createFrom(taskDTO.beginDate)); + position.resizeTo(GanttDate.createFrom(taskDTO.endDate)); + } + }); } currentTask.setNotes(taskDTO.notes); currentTask.setDeadline(taskDTO.deadlineDate); diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/data/DefaultFundamentalProperties.java b/ganttzk/src/main/java/org/zkoss/ganttz/data/DefaultFundamentalProperties.java index b55ed9ec8..75a6949c1 100644 --- a/ganttzk/src/main/java/org/zkoss/ganttz/data/DefaultFundamentalProperties.java +++ b/ganttzk/src/main/java/org/zkoss/ganttz/data/DefaultFundamentalProperties.java @@ -59,6 +59,33 @@ public class DefaultFundamentalProperties implements ITaskFundamentalProperties private String resourcesText; + private IUpdatablePosition position = new IUpdatablePosition() { + + private final DefaultFundamentalProperties parent = DefaultFundamentalProperties.this; + + @Override + public void setBeginDate(GanttDate beginDate) { + parent.beginDate = toMilliseconds(beginDate); + } + + @Override + public void setEndDate(GanttDate endDate) { + parent.beginDate = toMilliseconds(endDate) + - parent.lengthMilliseconds; + } + + @Override + public void resizeTo(GanttDate endDate) { + parent.lengthMilliseconds = toMilliseconds(endDate) - beginDate; + } + + @Override + public void moveTo(GanttDate date) { + setBeginDate(date); + } + + }; + public DefaultFundamentalProperties() { } @@ -80,6 +107,11 @@ public class DefaultFundamentalProperties implements ITaskFundamentalProperties this.resourcesText = ""; } + @Override + public void doPositionModifications(IModifications modifications) { + modifications.doIt(position); + } + public String getName() { return name; } @@ -115,11 +147,6 @@ public class DefaultFundamentalProperties implements ITaskFundamentalProperties return toGanttDate(beginDate); } - @Override - public void setBeginDate(GanttDate beginDate) { - this.beginDate = toMilliseconds(beginDate); - } - public long getLengthMilliseconds() { return lengthMilliseconds; } @@ -129,16 +156,6 @@ public class DefaultFundamentalProperties implements ITaskFundamentalProperties return toGanttDate(beginDate + getLengthMilliseconds()); } - @Override - public void setEndDate(GanttDate endDate) { - this.beginDate = toMilliseconds(endDate) - this.lengthMilliseconds; - } - - @Override - public void resizeTo(GanttDate endDate) { - this.lengthMilliseconds = toMilliseconds(endDate) - beginDate; - } - public String getNotes() { return notes; } @@ -193,11 +210,6 @@ public class DefaultFundamentalProperties implements ITaskFundamentalProperties return Collections.emptyList(); } - @Override - public void moveTo(GanttDate date) { - setBeginDate(date); - } - @Override public Date getDeadline() { return null; diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/data/GanttDiagramGraph.java b/ganttzk/src/main/java/org/zkoss/ganttz/data/GanttDiagramGraph.java index 4a0b3255f..7c8322897 100644 --- a/ganttzk/src/main/java/org/zkoss/ganttz/data/GanttDiagramGraph.java +++ b/ganttzk/src/main/java/org/zkoss/ganttz/data/GanttDiagramGraph.java @@ -46,12 +46,16 @@ import org.apache.commons.logging.LogFactory; import org.jgrapht.DirectedGraph; import org.jgrapht.graph.SimpleDirectedGraph; import org.zkoss.ganttz.data.DependencyType.Point; +import org.zkoss.ganttz.data.ITaskFundamentalProperties.IModifications; +import org.zkoss.ganttz.data.ITaskFundamentalProperties.IUpdatablePosition; import org.zkoss.ganttz.data.constraint.Constraint; import org.zkoss.ganttz.data.constraint.ConstraintOnComparableValues; import org.zkoss.ganttz.data.constraint.ConstraintOnComparableValues.ComparisonType; import org.zkoss.ganttz.data.criticalpath.ICriticalPathCalculable; import org.zkoss.ganttz.util.IAction; import org.zkoss.ganttz.util.PreAndPostNotReentrantActionsWrapper; +import org.zkoss.ganttz.util.ReentranceGuard; +import org.zkoss.ganttz.util.ReentranceGuard.IReentranceCases; /** * This class contains a graph with the {@link Task tasks} as vertexes and the @@ -180,8 +184,14 @@ public class GanttDiagramGraph> implements @Override - public void setEndDateFor(Task task, GanttDate newEnd) { - task.setEndDate(newEnd); + public void setEndDateFor(Task task, final GanttDate newEnd) { + task.doPositionModifications(new IModifications() { + + @Override + public void doIt(IUpdatablePosition position) { + position.setEndDate(newEnd); + } + }); } @Override @@ -190,8 +200,14 @@ public class GanttDiagramGraph> implements } @Override - public void setStartDateFor(Task task, GanttDate newStart) { - task.setBeginDate(newStart); + public void setStartDateFor(Task task, final GanttDate newStart) { + task.doPositionModifications(new IModifications() { + + @Override + public void doIt(IUpdatablePosition position) { + position.setBeginDate(newStart); + } + }); } @Override @@ -2284,31 +2300,4 @@ public class GanttDiagramGraph> implements return adapter.getChildren(task); } -} - -interface IReentranceCases { - public void ifNewEntrance(); - - public void ifAlreadyInside(); -} - -class ReentranceGuard { - private final ThreadLocal inside = new ThreadLocal() { - protected Boolean initialValue() { - return false; - }; - }; - - public void entranceRequested(IReentranceCases reentranceCases) { - if (inside.get()) { - reentranceCases.ifAlreadyInside(); - return; - } - inside.set(true); - try { - reentranceCases.ifNewEntrance(); - } finally { - inside.set(false); - } - } } \ No newline at end of file diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/data/ITaskFundamentalProperties.java b/ganttzk/src/main/java/org/zkoss/ganttz/data/ITaskFundamentalProperties.java index a2e8fae6e..1c35b2de9 100644 --- a/ganttzk/src/main/java/org/zkoss/ganttz/data/ITaskFundamentalProperties.java +++ b/ganttzk/src/main/java/org/zkoss/ganttz/data/ITaskFundamentalProperties.java @@ -32,15 +32,30 @@ import org.zkoss.ganttz.data.constraint.Constraint; */ public interface ITaskFundamentalProperties { + public interface IUpdatablePosition { + + public void setBeginDate(GanttDate beginDate); + + public void setEndDate(GanttDate endDate); + + public void resizeTo(GanttDate endDate); + + public void moveTo(GanttDate newStart); + } + + /** + * The position modifications must be wrapped inside this + */ + public interface IModifications { + public void doIt(IUpdatablePosition position); + } + + public void doPositionModifications(IModifications modifications); + public String getName(); public void setName(String name); - /** - * Sets the beginDate. - */ - public void setBeginDate(GanttDate beginDate); - public GanttDate getBeginDate(); /** @@ -55,10 +70,6 @@ public interface ITaskFundamentalProperties { public GanttDate getEndDate(); - public void setEndDate(GanttDate endDate); - - public void resizeTo(GanttDate endDate); - public String getNotes(); public void setNotes(String notes); @@ -81,8 +92,6 @@ public interface ITaskFundamentalProperties { public List> getEndConstraints(); - public void moveTo(GanttDate newStart); - public boolean isSubcontracted(); public boolean isLimiting(); diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/data/Task.java b/ganttzk/src/main/java/org/zkoss/ganttz/data/Task.java index 6d8e60ac2..0ee220112 100644 --- a/ganttzk/src/main/java/org/zkoss/ganttz/data/Task.java +++ b/ganttzk/src/main/java/org/zkoss/ganttz/data/Task.java @@ -32,7 +32,6 @@ import java.util.Collections; import java.util.Date; import java.util.List; -import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.Validate; import org.joda.time.Duration; import org.joda.time.LocalDate; @@ -124,6 +123,70 @@ public abstract class Task implements ITaskFundamentalProperties { .getEndConstraints()); } + @Override + public void doPositionModifications(final IModifications modifications) { + fundamentalProperties.doPositionModifications(new IModifications() { + + @Override + public void doIt(IUpdatablePosition p) { + modifications.doIt(position); + + } + }); + } + + private final IUpdatablePosition position = new IUpdatablePosition() { + + @Override + public void setEndDate(GanttDate value) { + if (value == null) { + return; + } + GanttDate previousEnd = fundamentalProperties.getEndDate(); + getFundamentalPropertiesPosition().setEndDate(value); + dependenciesEnforcerHook.setNewEnd(previousEnd, + fundamentalProperties.getEndDate()); + } + + @Override + public void setBeginDate(GanttDate newStart) { + GanttDate previousValue = fundamentalProperties.getBeginDate(); + GanttDate previousEnd = fundamentalProperties.getEndDate(); + getFundamentalPropertiesPosition().setBeginDate(newStart); + dependenciesEnforcerHook.setStartDate(previousValue, previousEnd, + newStart); + } + + @Override + public void resizeTo(GanttDate newEnd) { + GanttDate previousEnd = getEndDate(); + getFundamentalPropertiesPosition().resizeTo(newEnd); + dependenciesEnforcerHook.setNewEnd(previousEnd, newEnd); + } + + @Override + public void moveTo(GanttDate date) { + GanttDate previousStart = getBeginDate(); + GanttDate previousEnd = getEndDate(); + getFundamentalPropertiesPosition().moveTo(date); + dependenciesEnforcerHook.setStartDate(previousStart, previousEnd, + date); + } + + private IUpdatablePosition getFundamentalPropertiesPosition() { + final IUpdatablePosition[] result = new IUpdatablePosition[1]; + fundamentalProperties.doPositionModifications(new IModifications() { + + @Override + public void doIt(IUpdatablePosition position) { + result[0] = position; + } + }); + assert result[0] != null; + return result[0]; + } + }; + public abstract boolean isLeaf(); public abstract boolean isContainer(); @@ -195,14 +258,6 @@ public abstract class Task implements ITaskFundamentalProperties { Validate.notNull(dependenciesEnforcerHook); } - public void setBeginDate(GanttDate newStart) { - GanttDate previousValue = fundamentalProperties.getBeginDate(); - GanttDate previousEnd = fundamentalProperties.getEndDate(); - fundamentalProperties.setBeginDate(newStart); - dependenciesEnforcerHook.setStartDate(previousValue, previousEnd, - newStart); - } - public void fireChangesForPreviousValues(GanttDate previousStart, GanttDate previousEnd) { dependenciesEnforcerHook.setStartDate(previousStart, previousStart, @@ -284,28 +339,17 @@ public abstract class Task implements ITaskFundamentalProperties { previousValue, this.fundamentalProperties.getNotes()); } - @Override - public void setEndDate(GanttDate value) { - if (value == null) { - return; - } - GanttDate previousEnd = fundamentalProperties.getEndDate(); - fundamentalProperties.setEndDate(value); - dependenciesEnforcerHook.setNewEnd(previousEnd, - fundamentalProperties.getEndDate()); - } - - public void resizeTo(LocalDate date) { + public void resizeTo(final LocalDate date) { if (date.compareTo(getBeginDateAsLocalDate()) < 0) { return; } - resizeTo(GanttDate.createFrom(date)); - } + doPositionModifications(new IModifications() { - public void resizeTo(GanttDate newEnd) { - GanttDate previousEnd = getEndDate(); - fundamentalProperties.resizeTo(newEnd); - dependenciesEnforcerHook.setNewEnd(previousEnd, newEnd); + @Override + public void doIt(IUpdatablePosition position) { + position.resizeTo(GanttDate.createFrom(date)); + } + }); } public void removed() { @@ -356,13 +400,6 @@ public abstract class Task implements ITaskFundamentalProperties { return fundamentalProperties.getResourcesText(); } - public void moveTo(GanttDate date) { - GanttDate previousStart = getBeginDate(); - GanttDate previousEnd = getEndDate(); - fundamentalProperties.moveTo(date); - dependenciesEnforcerHook.setStartDate(previousStart, previousEnd, date); - } - @Override public Date getDeadline() { return fundamentalProperties.getDeadline(); diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/util/ReentranceGuard.java b/ganttzk/src/main/java/org/zkoss/ganttz/util/ReentranceGuard.java new file mode 100644 index 000000000..dff3ba324 --- /dev/null +++ b/ganttzk/src/main/java/org/zkoss/ganttz/util/ReentranceGuard.java @@ -0,0 +1,50 @@ +/* + * This file is part of LibrePlan + * + * 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 . + */ +package org.zkoss.ganttz.util; + +/** + * @author Óscar González Fernández + */ +public class ReentranceGuard { + + public interface IReentranceCases { + public void ifNewEntrance(); + + public void ifAlreadyInside(); + } + + private final ThreadLocal inside = new ThreadLocal() { + protected Boolean initialValue() { + return false; + }; + }; + + public void entranceRequested(IReentranceCases reentranceCases) { + if (inside.get()) { + reentranceCases.ifAlreadyInside(); + return; + } + inside.set(true); + try { + reentranceCases.ifNewEntrance(); + } finally { + inside.set(false); + } + } +} \ No newline at end of file diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/planner/TaskElementAdapter.java b/libreplan-webapp/src/main/java/org/libreplan/web/planner/TaskElementAdapter.java index 383c9ef24..20d8880f9 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/web/planner/TaskElementAdapter.java +++ b/libreplan-webapp/src/main/java/org/libreplan/web/planner/TaskElementAdapter.java @@ -100,6 +100,8 @@ import org.zkoss.ganttz.data.GanttDate.CustomDate; import org.zkoss.ganttz.data.GanttDate.LocalDateBased; import org.zkoss.ganttz.data.ITaskFundamentalProperties; import org.zkoss.ganttz.data.constraint.Constraint; +import org.zkoss.ganttz.util.ReentranceGuard; +import org.zkoss.ganttz.util.ReentranceGuard.IReentranceCases; /** * @author Óscar González Fernández @@ -224,6 +226,8 @@ public class TaskElementAdapter { @Autowired private IAdHocTransactionService transactionService; + private final ReentranceGuard reentranceGuard = new ReentranceGuard(); + @Autowired private IOrderElementDAO orderElementDAO; @@ -396,6 +400,48 @@ public class TaskElementAdapter { this.taskElement = taskElement; } + private final IUpdatablePosition position = new IUpdatablePosition() { + + @Override + public void setEndDate(GanttDate endDate) { + stepsBeforePossibleReallocation(); + getDatesHandler(taskElement).moveEndTo(toIntraDay(endDate)); + } + + @Override + public void setBeginDate(final GanttDate beginDate) { + stepsBeforePossibleReallocation(); + getDatesHandler(taskElement).moveTo(toIntraDay(beginDate)); + } + + @Override + public void resizeTo(final GanttDate endDate) { + stepsBeforePossibleReallocation(); + updateTaskPositionConstraint(endDate); + getDatesHandler(taskElement).resizeTo(toIntraDay(endDate)); + } + + private void stepsBeforePossibleReallocation() { + taskDAO.reattach(taskElement); + } + + @Override + public void moveTo(GanttDate newStart) { + if (taskElement instanceof ITaskPositionConstrained) { + ITaskPositionConstrained task = (ITaskPositionConstrained) taskElement; + if (task.getPositionConstraint() + .isConstraintAppliedToStart()) { + setBeginDate(newStart); + task.explicityMoved(toIntraDay(newStart)); + } else { + GanttDate newEnd = inferEndFrom(newStart); + setEndDate(newEnd); + task.explicityMoved(toIntraDay(newEnd)); + } + } + } + }; + @Override public void setName(String name) { taskElement.setName(name); @@ -432,17 +478,32 @@ public class TaskElementAdapter { } @Override - public void setBeginDate(final GanttDate beginDate) { - transactionService - .runOnReadOnlyTransaction(new IOnTransaction() { + public void doPositionModifications( + final IModifications modifications) { + reentranceGuard.entranceRequested(new IReentranceCases() { + + @Override + public void ifNewEntrance() { + transactionService.runOnReadOnlyTransaction(asTransaction(modifications)); + } + + IOnTransaction asTransaction( + final IModifications modifications) { + return new IOnTransaction() { + @Override public Void execute() { - stepsBeforePossibleReallocation(); - getDatesHandler(taskElement).moveTo( - toIntraDay(beginDate)); + modifications.doIt(position); return null; } - }); + }; + } + + @Override + public void ifAlreadyInside() { + modifications.doIt(position); + } + }); } @Override @@ -450,35 +511,6 @@ public class TaskElementAdapter { return toGantt(taskElement.getIntraDayEndDate()); } - @Override - public void setEndDate(final GanttDate endDate) { - transactionService - .runOnReadOnlyTransaction(new IOnTransaction() { - @Override - public Void execute() { - stepsBeforePossibleReallocation(); - getDatesHandler(taskElement).moveEndTo( - toIntraDay(endDate)); - return null; - } - }); - } - - @Override - public void resizeTo(final GanttDate endDate) { - transactionService - .runOnReadOnlyTransaction(new IOnTransaction() { - @Override - public Void execute() { - stepsBeforePossibleReallocation(); - updateTaskPositionConstraint(endDate); - getDatesHandler(taskElement).resizeTo( - toIntraDay(endDate)); - return null; - } - }); - } - IDatesHandler getDatesHandler(TaskElement taskElement) { return taskElement.getDatesHandler(currentScenario, searcher); } @@ -965,22 +997,6 @@ public class TaskElementAdapter { return Collections.emptyList(); } - @Override - public void moveTo(GanttDate newStart) { - if (taskElement instanceof ITaskPositionConstrained) { - ITaskPositionConstrained task = (ITaskPositionConstrained) taskElement; - if (task.getPositionConstraint() - .isConstraintAppliedToStart()) { - setBeginDate(newStart); - task.explicityMoved(toIntraDay(newStart)); - } else { - GanttDate newEnd = inferEndFrom(newStart); - setEndDate(newEnd); - task.explicityMoved(toIntraDay(newEnd)); - } - } - } - private GanttDate inferEndFrom(GanttDate newStart) { if (taskElement instanceof Task) { Task task = (Task) taskElement; @@ -1037,10 +1053,6 @@ public class TaskElementAdapter { return taskElement.hasConsolidations(); } - private void stepsBeforePossibleReallocation() { - taskDAO.reattach(taskElement); - } - @Override public boolean canBeExplicitlyResized() { return taskElement.canBeExplicitlyResized();