diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/FunctionalityExposedForExtensions.java b/ganttzk/src/main/java/org/zkoss/ganttz/FunctionalityExposedForExtensions.java index 8738c29ac..8f78f770b 100644 --- a/ganttzk/src/main/java/org/zkoss/ganttz/FunctionalityExposedForExtensions.java +++ b/ganttzk/src/main/java/org/zkoss/ganttz/FunctionalityExposedForExtensions.java @@ -45,6 +45,7 @@ import org.zkoss.ganttz.data.Position; import org.zkoss.ganttz.data.Task; import org.zkoss.ganttz.data.TaskContainer; import org.zkoss.ganttz.data.TaskLeaf; +import org.zkoss.ganttz.data.GanttDiagramGraph.GanttZKDiagramGraph; import org.zkoss.ganttz.data.criticalpath.CriticalPathCalculator; import org.zkoss.ganttz.extensions.IContext; import org.zkoss.ganttz.timetracker.TimeTracker; @@ -166,13 +167,13 @@ public class FunctionalityExposedForExtensions implements IContext { private final IAdapterToTaskFundamentalProperties adapter; private final IStructureNavigator navigator; private final OneToOneMapper mapper = new OneToOneMapper(); - private final GanttDiagramGraph diagramGraph; + private final GanttZKDiagramGraph diagramGraph; private TimeTracker timeTracker; private final PlannerConfiguration configuration; public FunctionalityExposedForExtensions(Planner planner, PlannerConfiguration configuration, - GanttDiagramGraph diagramGraph) { + GanttZKDiagramGraph diagramGraph) { this.planner = planner; this.configuration = configuration; this.adapter = configuration.getAdapter(); @@ -313,7 +314,7 @@ public class FunctionalityExposedForExtensions implements IContext { add(position, newDomainObject); } - public GanttDiagramGraph getDiagramGraph() { + public GanttZKDiagramGraph getDiagramGraph() { return diagramGraph; } @@ -351,7 +352,7 @@ public class FunctionalityExposedForExtensions implements IContext { public void removeDependency(Dependency dependency) { adapter.removeDependency(toDomainDependency(dependency)); - diagramGraph.remove(dependency); + diagramGraph.removeDependency(dependency); getDependencyList().remove(dependency); } diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/Planner.java b/ganttzk/src/main/java/org/zkoss/ganttz/Planner.java index 62dfd2a13..cfcc09f70 100644 --- a/ganttzk/src/main/java/org/zkoss/ganttz/Planner.java +++ b/ganttzk/src/main/java/org/zkoss/ganttz/Planner.java @@ -38,6 +38,7 @@ import org.zkoss.ganttz.data.Dependency; import org.zkoss.ganttz.data.GanttDiagramGraph; import org.zkoss.ganttz.data.Position; import org.zkoss.ganttz.data.Task; +import org.zkoss.ganttz.data.GanttDiagramGraph.GanttZKDiagramGraph; import org.zkoss.ganttz.data.GanttDiagramGraph.IGraphChangeListener; import org.zkoss.ganttz.extensions.ICommand; import org.zkoss.ganttz.extensions.ICommandOnTask; @@ -111,7 +112,7 @@ public class Planner extends HtmlMacroComponent { return result; } - private GanttDiagramGraph diagramGraph; + private GanttZKDiagramGraph diagramGraph; private LeftPane leftPane; diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/data/Dependency.java b/ganttzk/src/main/java/org/zkoss/ganttz/data/Dependency.java index fa7f2f506..f6d297a80 100644 --- a/ganttzk/src/main/java/org/zkoss/ganttz/data/Dependency.java +++ b/ganttzk/src/main/java/org/zkoss/ganttz/data/Dependency.java @@ -27,6 +27,7 @@ import java.util.List; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; +import org.zkoss.ganttz.data.GanttDiagramGraph.GanttZKAdapter; import org.zkoss.ganttz.data.GanttDiagramGraph.TaskPoint; import org.zkoss.ganttz.data.constraint.Constraint; import org.zkoss.ganttz.data.constraint.Constraint.IConstraintViolationListener; @@ -167,8 +168,9 @@ public class Dependency implements IDependency { return new Dependency(source, destination, type, visible); } - public TaskPoint getDestinationPoint() { - return new TaskPoint(destination, type.getPointModified()); + public TaskPoint getDestinationPoint() { + return new TaskPoint(new GanttZKAdapter(), + destination, type.getPointModified()); } } \ No newline at end of file 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 551fba589..64e987634 100644 --- a/ganttzk/src/main/java/org/zkoss/ganttz/data/GanttDiagramGraph.java +++ b/ganttzk/src/main/java/org/zkoss/ganttz/data/GanttDiagramGraph.java @@ -53,28 +53,198 @@ import org.zkoss.ganttz.util.PreAndPostNotReentrantActionsWrapper; * dependencies and in the duration of the tasks using listeners.
* @author Óscar González Fernández */ -public class GanttDiagramGraph implements ICriticalPathCalculable { +public class GanttDiagramGraph { private static final Log LOG = LogFactory.getLog(GanttDiagramGraph.class); + public interface IAdapter { + List getChildren(V task); + + boolean isContainer(V task); + + void registerDependenciesEnforcerHookOn(V task, + IDependenciesEnforcerHookFactory hookFactory); + + Date getStartDate(V task); + + void setStartDateFor(V task, Date newStart); + + Date getEndDateFor(V task); + + void setEndDateFor(V task, Date newEnd); + + Date getSmallestBeginDateFromChildrenFor(V container); + + Constraint getCurrentLenghtConstraintFor(V task); + + Constraint getEndDateBiggerThanStartDateConstraintFor(V task); + + List> getConstraintsGivenIncoming(Set incoming); + + List> getStartCosntraintsGiven(Set withDependencies); + + List> getStartConstraintsFor(V task); + + V getSource(D dependency); + + V getDestination(D dependency); + + Class getDependencyType(); + + D createInvisibleDependency(V origin, V destination, DependencyType type); + + DependencyType getType(D dependency); + + TaskPoint getDestinationPoint(D dependency); + + boolean isVisible(D dependency); + + } + + static class GanttZKAdapter implements IAdapter { + + @Override + public List getChildren(Task task) { + return task.getTasks(); + } + + @Override + public Task getDestination(Dependency dependency) { + return dependency.getDestination(); + } + + @Override + public Task getSource(Dependency dependency) { + return dependency.getSource(); + } + + @Override + public boolean isContainer(Task task) { + return task.isContainer(); + } + + @Override + public void registerDependenciesEnforcerHookOn(Task task, + IDependenciesEnforcerHookFactory hookFactory) { + task.registerDependenciesEnforcerHook(hookFactory); + } + + @Override + public Dependency createInvisibleDependency(Task origin, + Task destination, DependencyType type) { + return new Dependency(origin, destination, type, false); + } + + @Override + public Class getDependencyType() { + return Dependency.class; + } + + @Override + public DependencyType getType(Dependency dependency) { + return dependency.getType(); + } + + @Override + public TaskPoint getDestinationPoint( + Dependency dependency) { + return dependency.getDestinationPoint(); + } + + @Override + public boolean isVisible(Dependency dependency) { + return dependency.isVisible(); + } + + @Override + public Date getEndDateFor(Task task) { + return task.getEndDate(); + } + + @Override + public Constraint getCurrentLenghtConstraintFor(Task task) { + return task.getCurrentLengthConstraint(); + } + + @Override + public Constraint getEndDateBiggerThanStartDateConstraintFor( + Task task) { + return task.getEndDateBiggerThanStartDate(); + } + + @Override + public List> getConstraintsGivenIncoming( + Set incoming) { + return Dependency.getEndConstraints(incoming); + } + + @Override + public void setEndDateFor(Task task, Date newEnd) { + task.setEndDate(newEnd); + } + + @Override + public Date getStartDate(Task task) { + return task.getBeginDate(); + } + + @Override + public void setStartDateFor(Task task, Date newStart) { + task.setBeginDate(newStart); + } + + @Override + public List> getStartCosntraintsGiven( + Set withDependencies) { + return Dependency.getStartConstraints(withDependencies); + } + + @Override + public List> getStartConstraintsFor(Task task) { + return task.getStartConstraints(); + } + + @Override + public Date getSmallestBeginDateFromChildrenFor(Task container) { + return ((TaskContainer) container).getSmallestBeginDateFromChildren(); + } + + } + + public static class GanttZKDiagramGraph extends + GanttDiagramGraph implements + ICriticalPathCalculable { + + private GanttZKDiagramGraph( + List> globalStartConstraints, + List> globalEndConstraints, + boolean dependenciesConstraintsHavePriority) { + super(new GanttZKAdapter(), globalStartConstraints, + globalEndConstraints, + dependenciesConstraintsHavePriority); + } + + } + public interface IGraphChangeListener { public void execute(); } - public static GanttDiagramGraph create( + public static GanttZKDiagramGraph create( List> globalStartConstraints, List> globalEndConstraints, boolean dependenciesConstraintsHavePriority) { - return new GanttDiagramGraph(globalStartConstraints, + return new GanttZKDiagramGraph(globalStartConstraints, globalEndConstraints, dependenciesConstraintsHavePriority); } - private final DirectedGraph graph = new SimpleDirectedGraph( - Dependency.class); + private final IAdapter adapter; - private List topLevelTasks = new ArrayList(); + private final DirectedGraph graph; - private Map fromChildToParent = new HashMap(); + private List topLevelTasks = new ArrayList(); + + private Map fromChildToParent = new HashMap(); private final List> globalStartConstraints; @@ -145,50 +315,52 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { } } - private GanttDiagramGraph(List> globalStartConstraints, + protected GanttDiagramGraph(IAdapter adapter, + List> globalStartConstraints, List> globalEndConstraints, boolean dependenciesConstraintsHavePriority) { + this.adapter = adapter; this.globalStartConstraints = globalStartConstraints; this.globalEndConstraints = globalEndConstraints; this.dependenciesConstraintsHavePriority = dependenciesConstraintsHavePriority; + this.graph = new SimpleDirectedGraph(adapter.getDependencyType()); } public void enforceAllRestrictions() { enforcer.enforceRestrictionsOn(getTopLevelTasks()); } - public void addTopLevel(Task task) { + public void addTopLevel(V task) { topLevelTasks.add(task); addTask(task); } - public void addTopLevel(Collection tasks) { - for (Task task : tasks) { + public void addTopLevel(Collection tasks) { + for (V task : tasks) { addTopLevel(task); } } - public void addTasks(Collection tasks) { - for (Task t : tasks) { + public void addTasks(Collection tasks) { + for (V t : tasks) { addTask(t); } } - public void addTask(Task task) { + public void addTask(V task) { graph.addVertex(task); - task.registerDependenciesEnforcerHook(enforcer); - if (task.isContainer()) { - List dependenciesToAdd = new ArrayList(); - for (Task child : task.getTasks()) { - fromChildToParent.put(child, (TaskContainer) task); + adapter.registerDependenciesEnforcerHookOn(task, enforcer); + if (adapter.isContainer(task)) { + List dependenciesToAdd = new ArrayList(); + for (V child : adapter.getChildren(task)) { + fromChildToParent.put(child, task); addTask(child); - dependenciesToAdd.add(new Dependency(child, task, - DependencyType.END_END, false)); - dependenciesToAdd.add(new Dependency(task, child, - DependencyType.START_START, - false)); + dependenciesToAdd.add(adapter.createInvisibleDependency(child, task, + DependencyType.END_END)); + dependenciesToAdd.add(adapter.createInvisibleDependency(task, + child, DependencyType.START_START)); } - for (Dependency each : dependenciesToAdd) { + for (D each : dependenciesToAdd) { add(each); } } @@ -202,8 +374,8 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { long newLengthMilliseconds); } - public interface IDependenciesEnforcerHookFactory { - public IDependenciesEnforcerHook create(Task task, + public interface IDependenciesEnforcerHookFactory { + public IDependenciesEnforcerHook create(T task, INotificationAfterDependenciesEnforcement notification); } @@ -216,13 +388,13 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { public class DeferedNotifier { - private Map notificationsPending = new LinkedHashMap(); + private Map notificationsPending = new LinkedHashMap(); - public void add(Task task, StartDateNofitication notification) { + public void add(V task, StartDateNofitication notification) { retrieveOrCreateFor(task).setStartDateNofitication(notification); } - private NotificationPendingForTask retrieveOrCreateFor(Task task) { + private NotificationPendingForTask retrieveOrCreateFor(V task) { NotificationPendingForTask result = notificationsPending.get(task); if (result == null) { result = new NotificationPendingForTask(); @@ -231,7 +403,7 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { return result; } - void add(Task task, LengthNotification notification) { + void add(V task, LengthNotification notification) { retrieveOrCreateFor(task).setLengthNofitication(notification); } @@ -245,7 +417,7 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { } - private static class NotificationPendingForTask { + private class NotificationPendingForTask { private StartDateNofitication startDateNofitication; private LengthNotification lengthNofitication; @@ -328,18 +500,18 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { } private class DependenciesEnforcer implements - IDependenciesEnforcerHookFactory { + IDependenciesEnforcerHookFactory { private ThreadLocal deferedNotifier = new ThreadLocal(); @Override - public IDependenciesEnforcerHook create(Task task, + public IDependenciesEnforcerHook create(V task, INotificationAfterDependenciesEnforcement notificator) { return onlyEnforceDependenciesOnEntrance(onEntrance(task), onNotification(task, notificator)); } - private IDependenciesEnforcerHook onEntrance(final Task task) { + private IDependenciesEnforcerHook onEntrance(final V task) { return new IDependenciesEnforcerHook() { @Override @@ -356,7 +528,7 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { }; } - private IDependenciesEnforcerHook onNotification(final Task task, + private IDependenciesEnforcerHook onNotification(final V task, final INotificationAfterDependenciesEnforcement notification) { return new IDependenciesEnforcerHook() { @@ -454,15 +626,15 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { } - void enforceRestrictionsOn(Collection tasks) { + void enforceRestrictionsOn(Collection tasks) { List allRecalculations = new ArrayList(); - for (Task each : tasks) { + for (V each : tasks) { allRecalculations.addAll(getRecalculationsNeededFrom(each)); } enforceRestrictionsOn(allRecalculations); } - void enforceRestrictionsOn(Task task) { + void enforceRestrictionsOn(V task) { enforceRestrictionsOn(getRecalculationsNeededFrom(task)); } @@ -540,7 +712,7 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { return result; } - private void taskPositionModified(final Task task) { + private void taskPositionModified(final V task) { executeWithPreAndPostActionsOnlyIfNewEntrance(new IAction() { @Override public void doAction() { @@ -551,7 +723,7 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { } private void doRecalculations(List recalculationsNeeded) { - Set allModified = new HashSet(); + Set allModified = new HashSet(); List calculated = new ArrayList(); for (Recalculation each : recalculationsNeeded) { if (each.haveToDoCalculation()) { @@ -562,36 +734,35 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { allModified.add(each.taskPoint.task); } } - List shrunkContainers = shrunkContainersOfModified(allModified); - for (Task each : getTaskAffectedByShrinking(shrunkContainers)) { + List shrunkContainers = shrunkContainersOfModified(allModified); + for (V each : getTaskAffectedByShrinking(shrunkContainers)) { doRecalculations(getRecalculationsNeededFrom(each)); } } - private List getTaskAffectedByShrinking( - List shrunkContainers) { - List tasksAffectedByShrinking = new ArrayList(); - for (TaskContainer each : shrunkContainers) { - for (Dependency eachDependency : graph.outgoingEdgesOf(each)) { - if (eachDependency.getType() == DependencyType.START_START - && eachDependency.isVisible()) { - tasksAffectedByShrinking.add(eachDependency - .getDestination()); + private List getTaskAffectedByShrinking(List shrunkContainers) { + List tasksAffectedByShrinking = new ArrayList(); + for (V each : shrunkContainers) { + for (D eachDependency : graph.outgoingEdgesOf(each)) { + if (adapter.getType(eachDependency) == DependencyType.START_START + && adapter.isVisible(eachDependency)) { + tasksAffectedByShrinking.add(adapter + .getDestination(eachDependency)); } } } return tasksAffectedByShrinking; } - private List shrunkContainersOfModified( - Set allModified) { - Set topmostToShrink = getTopMostThatCouldPotentiallyNeedShrinking(allModified); - List allToShrink = new ArrayList(); - for (TaskContainer each : topmostToShrink) { + private List shrunkContainersOfModified( + Set allModified) { + Set topmostToShrink = getTopMostThatCouldPotentiallyNeedShrinking(allModified); + List allToShrink = new ArrayList(); + for (V each : topmostToShrink) { allToShrink.addAll(getContainersBottomUp(each)); } - List result = new ArrayList(); - for (TaskContainer each : allToShrink) { + List result = new ArrayList(); + for (V each : allToShrink) { boolean modified = enforceParentShrinkage(each); if (modified) { result.add(each); @@ -600,60 +771,50 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { return result; } - private Set getTopMostThatCouldPotentiallyNeedShrinking( - Collection modified) { - Set result = new HashSet(); - for (Task each : modified) { - Task t = getTopmostFor(each); - if (t.isContainer()) { - result.add((TaskContainer) t); + private Set getTopMostThatCouldPotentiallyNeedShrinking( + Collection modified) { + Set result = new HashSet(); + for (V each : modified) { + V t = getTopmostFor(each); + if (adapter.isContainer(t)) { + result.add(t); } } return result; } - private Collection getContainersBottomUp( - TaskContainer container) { - List result = new ArrayList(); - List tasks = container.getTasks(); - for (Task each : tasks) { - if (each.isContainer()) { - TaskContainer childContainer = (TaskContainer) each; - result.addAll(getContainersBottomUp(childContainer)); - result.add(childContainer); + private Collection getContainersBottomUp( + V container) { + List result = new ArrayList(); + List tasks = adapter.getChildren(container); + for (V each : tasks) { + if (adapter.isContainer(each)) { + result.addAll(getContainersBottomUp(each)); + result.add(each); } } result.add(container); return result; } - - - boolean enforceParentShrinkage(TaskContainer container) { - Date oldBeginDate = container.getBeginDate(); - Date firstStart = container.getSmallestBeginDateFromChildren(); - Date previousEnd = container.getEndDate(); + boolean enforceParentShrinkage(V container) { + Date oldBeginDate = adapter.getStartDate(container); + Date firstStart = adapter + .getSmallestBeginDateFromChildrenFor(container); + Date previousEnd = adapter.getEndDateFor(container); if (firstStart.after(oldBeginDate)) { - container.setBeginDate(firstStart); - container.setEndDate(previousEnd); + adapter.setStartDateFor(container, firstStart); + adapter.setEndDateFor(container, previousEnd); return true; } return false; } - - - - - - - - } - List getRecalculationsNeededFrom(Task task) { + List getRecalculationsNeededFrom(V task) { List result = new LinkedList(); Set parentRecalculationsAlreadyDone = new HashSet(); - Recalculation first = recalculationFor(TaskPoint.both(task)); + Recalculation first = recalculationFor(TaskPoint.both(adapter, task)); first.couldHaveBeenModifiedBeforehand(); Queue pendingOfNavigate = new LinkedList(); result.addAll(getParentsRecalculations(parentRecalculationsAlreadyDone, @@ -662,7 +823,7 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { pendingOfNavigate.offer(first); while (!pendingOfNavigate.isEmpty()) { Recalculation current = pendingOfNavigate.poll(); - for (TaskPoint each : getImmendiateReachableFrom(current.taskPoint)) { + for (TaskPoint each : getImmendiateReachableFrom(current.taskPoint)) { Recalculation recalculationToAdd = recalculationFor(each); ListIterator listIterator = result .listIterator(); @@ -686,9 +847,9 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { private List getParentsRecalculations( Set parentRecalculationsAlreadyDone, - TaskPoint taskPoint) { + TaskPoint taskPoint) { List result = new ArrayList(); - for (TaskPoint eachParent : parentsRecalculationsNeededFor(taskPoint)) { + for (TaskPoint eachParent : parentsRecalculationsNeededFor(taskPoint)) { Recalculation parentRecalculation = parentRecalculation(eachParent.task); if (!parentRecalculationsAlreadyDone .contains(parentRecalculation)) { @@ -699,10 +860,11 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { return result; } - private Set parentsRecalculationsNeededFor(TaskPoint current) { - Set result = new LinkedHashSet(); + private Set> parentsRecalculationsNeededFor( + TaskPoint current) { + Set> result = new LinkedHashSet>(); if (current.pointType == PointType.BOTH) { - List path = fromTaskToTop(current.task); + List path = fromTaskToTop(current.task); if (path.size() > 1) { path = path.subList(1, path.size()); Collections.reverse(path); @@ -712,17 +874,17 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { return result; } - private Collection asBothPoints(List parents) { - List result = new ArrayList(); - for (Task each : parents) { - result.add(TaskPoint.both(each)); + private Collection> asBothPoints(List parents) { + List> result = new ArrayList>(); + for (V each : parents) { + result.add(TaskPoint.both(adapter, each)); } return result; } - private List fromTaskToTop(Task task) { - List result = new ArrayList(); - Task current = task; + private List fromTaskToTop(V task) { + List result = new ArrayList(); + V current = task; while (current != null) { result.add(current); current = fromChildToParent.get(current); @@ -730,11 +892,11 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { return result; } - private Recalculation parentRecalculation(Task task) { - return new Recalculation(TaskPoint.both(task), true); + private Recalculation parentRecalculation(V task) { + return new Recalculation(TaskPoint.both(adapter, task), true); } - private Recalculation recalculationFor(TaskPoint taskPoint) { + private Recalculation recalculationFor(TaskPoint taskPoint) { return new Recalculation(taskPoint, false); } @@ -742,7 +904,7 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { private final boolean parentRecalculation; - private final TaskPoint taskPoint; + private final TaskPoint taskPoint; private Set parents = new HashSet(); @@ -752,7 +914,7 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { private boolean couldHaveBeenModifiedBeforehand = false; - Recalculation(TaskPoint taskPoint, boolean isParentRecalculation) { + Recalculation(TaskPoint taskPoint, boolean isParentRecalculation) { Validate.notNull(taskPoint); this.taskPoint = taskPoint; this.parentRecalculation = isParentRecalculation; @@ -779,7 +941,7 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { private boolean taskChangesPosition() { PointType pointType = taskPoint.pointType; - Task task = taskPoint.task; + V task = taskPoint.task; switch (pointType) { case BOTH: return enforceStartAndEnd(task); @@ -804,61 +966,62 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { return false; } - private boolean enforceStartAndEnd(Task task) { - Set incoming = graph.incomingEdgesOf(task); - Date previousEndDate = task.getEndDate(); + private boolean enforceStartAndEnd(V task) { + Set incoming = graph.incomingEdgesOf(task); + Date previousEndDate = adapter.getEndDateFor(task); boolean startDateChanged = enforceStartDate(task, incoming); boolean endDateChanged = enforceEndDate(task, previousEndDate, incoming); return startDateChanged || endDateChanged; } - private boolean enforceEnd(Task task) { - Set incoming = graph.incomingEdgesOf(task); - Date previousEndDate = task.getEndDate(); + private boolean enforceEnd(V task) { + Set incoming = graph.incomingEdgesOf(task); + Date previousEndDate = adapter.getEndDateFor(task); return enforceEndDate(task, previousEndDate, incoming); } @SuppressWarnings("unchecked") - private boolean enforceEndDate(Task task, Date previousEndDate, - Set incoming) { - Constraint currentLength = task.getCurrentLengthConstraint(); - Constraint respectStartDate = task - .getEndDateBiggerThanStartDate(); - Date newEnd = Constraint. initialValue(null).withConstraints( - currentLength).withConstraints( - Dependency.getEndConstraints(incoming)).withConstraints( - respectStartDate).apply(); - if (!task.getEndDate().equals(newEnd)) { - task.setEndDate(newEnd); + private boolean enforceEndDate(V task, Date previousEndDate, + Set incoming) { + Constraint currentLength = adapter + .getCurrentLenghtConstraintFor(task); + Constraint respectStartDate = adapter + .getEndDateBiggerThanStartDateConstraintFor(task); + Date newEnd = Constraint. initialValue(null) + .withConstraints(currentLength) + .withConstraints(adapter.getConstraintsGivenIncoming(incoming)) + .withConstraints(respectStartDate) + .apply(); + if (!adapter.getEndDateFor(task).equals(newEnd)) { + adapter.setEndDateFor(task, newEnd); } return !previousEndDate.equals(newEnd); } - private boolean enforceStartDate(Task task, Set incoming) { + private boolean enforceStartDate(V task, Set incoming) { Date newStart = calculateStartDateFor(task, incoming); - if (!task.getBeginDate().equals(newStart)) { - task.setBeginDate(newStart); + if (!adapter.getStartDate(task).equals(newStart)) { + adapter.setStartDateFor(task, newStart); return true; } return false; } - private Date calculateStartDateFor(Task task, - Set withDependencies) { - List> dependencyConstraints = Dependency - .getStartConstraints(withDependencies); + private Date calculateStartDateFor(V task, Set withDependencies) { + List> dependencyConstraints = adapter + .getStartCosntraintsGiven(withDependencies); Date newStart; if (dependenciesConstraintsHavePriority) { newStart = Constraint. initialValue(null) - .withConstraints(task.getStartConstraints()) + .withConstraints(adapter.getStartConstraintsFor(task)) .withConstraints(dependencyConstraints) .withConstraints(globalStartConstraints).apply(); } else { newStart = Constraint. initialValue(null) .withConstraints(dependencyConstraints) - .withConstraints(task.getStartConstraints()) + .withConstraints(adapter.getStartConstraintsFor(task)) .withConstraints(globalStartConstraints).apply(); } return newStart; @@ -891,7 +1054,7 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { @Override public boolean equals(Object obj) { - if (obj instanceof Recalculation) { + if (Recalculation.class.isInstance(obj)) { Recalculation other = (Recalculation) obj; return new EqualsBuilder().append(parentRecalculation, other.parentRecalculation) .append(taskPoint, other.taskPoint) @@ -901,33 +1064,33 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { } } - public void remove(final Task task) { - Set needingEnforcing = getOutgoingTasksFor(task); + public void remove(final V task) { + Set needingEnforcing = getOutgoingTasksFor(task); graph.removeVertex(task); topLevelTasks.remove(task); fromChildToParent.remove(task); - if (task.isContainer()) { - for (Task t : task.getTasks()) { + if (adapter.isContainer(task)) { + for (V t : adapter.getChildren(task)) { remove(t); } } enforcer.enforceRestrictionsOn(needingEnforcing); } - public void remove(Dependency dependency) { + public void removeDependency(D dependency) { graph.removeEdge(dependency); - Task destination = dependency.getDestination(); + V destination = adapter.getDestination(dependency); enforcer.enforceRestrictionsOn(destination); } - public void add(Dependency dependency) { - Task source = dependency.getSource(); - Task destination = dependency.getDestination(); + public void add(D dependency) { + V source = adapter.getSource(dependency); + V destination = adapter.getDestination(dependency); graph.addEdge(source, destination, dependency); enforceRestrictions(destination); } - public void enforceRestrictions(final Task task) { + public void enforceRestrictions(final V task) { enforcer.taskPositionModified(task); } @@ -935,82 +1098,69 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { return enforcer.manualNotification(action); } - public boolean contains(Dependency dependency) { + public boolean contains(D dependency) { return graph.containsEdge(dependency); } - @Override - public List getTasks() { - return new ArrayList(graph.vertexSet()); + public List getTasks() { + return new ArrayList(graph.vertexSet()); } - public List getVisibleDependencies() { - Set edgeSet = graph.edgeSet(); - ArrayList result = new ArrayList(); - for (Dependency dependency : edgeSet) { - if (dependency.isVisible()) { + public List getVisibleDependencies() { + ArrayList result = new ArrayList(); + for (D dependency : graph.edgeSet()) { + if (adapter.isVisible(dependency)) { result.add(dependency); } } return result; } - public List getTopLevelTasks() { + public List getTopLevelTasks() { return Collections.unmodifiableList(topLevelTasks); } - public void childrenAddedTo(TaskContainer task) { + public void childrenAddedTo(V task) { enforcer.enforceRestrictionsOn(task); } - @Override - public List getInitialTasks() { - List tasks = new ArrayList(); - - for (Task task : graph.vertexSet()) { + public List getInitialTasks() { + List result = new ArrayList(); + for (V task : graph.vertexSet()) { int dependencies = graph.inDegreeOf(task); if ((dependencies == 0) || (dependencies == getNumberOfIncomingDependenciesByType( task, DependencyType.END_END))) { - tasks.add(task); + result.add(task); } } - - return tasks; + return result; } - @Override - public Dependency getDependencyFrom(Task from, Task to) { + public D getDependencyFrom(V from, V to) { return graph.getEdge(from, to); } - @Override - public Set getOutgoingTasksFor(Task task) { - Set tasks = new HashSet(); - - for (Dependency dependency : graph.outgoingEdgesOf(task)) { - tasks.add(dependency.getDestination()); + public Set getOutgoingTasksFor(V task) { + Set result = new HashSet(); + for (D dependency : graph.outgoingEdgesOf(task)) { + result.add(adapter.getDestination(dependency)); } - - return tasks; + return result; } - @Override - public Set getIncomingTasksFor(Task task) { - Set tasks = new HashSet(); - - for (Dependency dependency : graph.incomingEdgesOf(task)) { - tasks.add(dependency.getSource()); + public Set getIncomingTasksFor(V task) { + Set result = new HashSet(); + for (D dependency : graph.incomingEdgesOf(task)) { + result.add(adapter.getSource(dependency)); } - - return tasks; + return result; } - @Override - public List getLatestTasks() { - List tasks = new ArrayList(); + public List getLatestTasks() { + List tasks = new ArrayList(); - for (Task task : graph.vertexSet()) { + for (V task : graph.vertexSet()) { int dependencies = graph.outDegreeOf(task); if ((dependencies == 0) || (dependencies == getNumberOfOutgoingDependenciesByType( @@ -1022,51 +1172,49 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { return tasks; } - private int getNumberOfIncomingDependenciesByType(Task task, + private int getNumberOfIncomingDependenciesByType(V task, DependencyType dependencyType) { int count = 0; - for (Dependency dependency : graph.incomingEdgesOf(task)) { - if (dependency.getType().equals(dependencyType)) { + for (D dependency : graph.incomingEdgesOf(task)) { + if (adapter.getType(dependency).equals(dependencyType)) { count++; } } return count; } - private int getNumberOfOutgoingDependenciesByType(Task task, + private int getNumberOfOutgoingDependenciesByType(V task, DependencyType dependencyType) { int count = 0; - for (Dependency dependency : graph.outgoingEdgesOf(task)) { - if (dependency.getType().equals(dependencyType)) { + for (D dependency : graph.outgoingEdgesOf(task)) { + if (adapter.getType(dependency).equals(dependencyType)) { count++; } } return count; } - @Override - public boolean isContainer(Task task) { + public boolean isContainer(V task) { if (task == null) { return false; } - return task.isContainer(); + return adapter.isContainer(task); } - @Override - public boolean contains(Task container, Task task) { + public boolean contains(V container, V task) { if ((container == null) || (task == null)) { return false; } - if (container.isContainer()) { - return container.getTasks().contains(task); + if (adapter.isContainer(container)) { + return adapter.getChildren(container).contains(task); } return false; } - public boolean doesNotProvokeLoop(Dependency dependency) { - Set reachableFromDestination = getReachableFrom(dependency - .getDestinationPoint()); - for (TaskPoint each : reachableFromDestination) { + public boolean doesNotProvokeLoop(D dependency) { + Set> reachableFromDestination = getReachableFrom(adapter + .getDestinationPoint(dependency)); + for (TaskPoint each : reachableFromDestination) { if (each.sendsModificationsThrough(dependency)) { return false; } @@ -1096,21 +1244,25 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { } } - static class TaskPoint { + static class TaskPoint { - public static TaskPoint both(Task task){ - return new TaskPoint(task, PointType.BOTH); + public static TaskPoint both(IAdapter adapter, T task) { + return new TaskPoint(adapter, task, PointType.BOTH); } - public static TaskPoint endOf(Task task) { - return new TaskPoint(task, PointType.END); + public static TaskPoint endOf(IAdapter adapter, + T task) { + return new TaskPoint(adapter, task, PointType.END); } - final Task task; + final T task; final PointType pointType; - TaskPoint(Task task, PointType pointType) { + private final IAdapter adapter; + + TaskPoint(IAdapter adapter, T task, PointType pointType) { + this.adapter = adapter; this.task = task; this.pointType = pointType; } @@ -1122,8 +1274,8 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { @Override public boolean equals(Object obj) { - if (obj instanceof TaskPoint) { - TaskPoint other = (TaskPoint) obj; + if (obj instanceof TaskPoint) { + TaskPoint other = (TaskPoint) obj; return new EqualsBuilder().append(task, other.task).append( pointType, other.pointType).isEquals(); } @@ -1135,22 +1287,22 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { return new HashCodeBuilder().append(task).append(pointType).toHashCode(); } - public boolean sendsModificationsThrough(Dependency dependency) { - DependencyType type = dependency.getType(); - return dependency.getSource().equals(task) + public boolean sendsModificationsThrough(D dependency) { + DependencyType type = adapter.getType(dependency); + return adapter.getSource(dependency).equals(task) && pointType.sendsModificationsThrough(type); } } - private Set getReachableFrom(TaskPoint task) { - Set result = new HashSet(); - Queue pending = new LinkedList(); + private Set> getReachableFrom(TaskPoint task) { + Set> result = new HashSet>(); + Queue> pending = new LinkedList>(); result.add(task); pending.offer(task); while (!pending.isEmpty()) { - TaskPoint current = pending.poll(); - Set immendiate = getImmendiateReachableFrom(current); - for (TaskPoint each : immendiate) { + TaskPoint current = pending.poll(); + Set> immendiate = getImmendiateReachableFrom(current); + for (TaskPoint each : immendiate) { if (!result.contains(each)) { result.add(each); pending.offer(each); @@ -1162,20 +1314,21 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { - private Task getTopmostFor(Task task) { - Task result = task; + private V getTopmostFor(V task) { + V result = task; while (fromChildToParent.containsKey(result)) { result = fromChildToParent.get(result); } return result; } - private Set getImmendiateReachableFrom(TaskPoint current) { - Set result = new HashSet(); - Set outgoingEdgesOf = graph.outgoingEdgesOf(current.task); - for (Dependency each : outgoingEdgesOf) { + private Set> getImmendiateReachableFrom( + TaskPoint current) { + Set> result = new HashSet>(); + Set outgoingEdgesOf = graph.outgoingEdgesOf(current.task); + for (D each : outgoingEdgesOf) { if (current.sendsModificationsThrough(each)) { - result.add(each.getDestinationPoint()); + result.add(adapter.getDestinationPoint(each)); } } return result;