RecalculateTaskScheduleAlgorithm.java
| Index Score | ||
|---|---|---|
![]() |
![]() |
net.sourceforge.ganttproject.task.algorithm |
![]() |
![]() |
GanttProject |
View: Reasons, Metrics, Source Code
These are the metrics that contribute to the Enerjy Score for this file, ranked by impact. So the metrics listed at the top influence the score to a greater extent that the metrics listed at the bottom.
package net.sourceforge.ganttproject.task.algorithm;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import net.sourceforge.ganttproject.GanttCalendar;
import net.sourceforge.ganttproject.task.Task;
import net.sourceforge.ganttproject.task.TaskContainmentHierarchyFacade;
import net.sourceforge.ganttproject.task.TaskLength;
import net.sourceforge.ganttproject.task.TaskMutator;
import net.sourceforge.ganttproject.task.dependency.TaskDependency;
import net.sourceforge.ganttproject.task.dependency.TaskDependencyConstraint;
import net.sourceforge.ganttproject.task.dependency.TaskDependencyException;
/**
* Created by IntelliJ IDEA. User: bard
*/
public abstract class RecalculateTaskScheduleAlgorithm extends AlgorithmBase {
private Set myMarkedTasks = new HashSet();
private SortedMap myDistance2dependencyList = new TreeMap();
private Set<Task> myModifiedTasks = new HashSet<Task>();
private final AdjustTaskBoundsAlgorithm myAdjuster;
private int myEntranceCounter;
private boolean isRunning;
public RecalculateTaskScheduleAlgorithm(AdjustTaskBoundsAlgorithm adjuster) {
myAdjuster = adjuster;
}
public void run(Task changedTask) throws TaskDependencyException {
if (!isEnabled()) {
return;
}
isRunning = true;
myEntranceCounter++;
myMarkedTasks.clear();
buildDistanceGraph(changedTask);
fulfilDependencies();
myDistance2dependencyList.clear();
myModifiedTasks.add(changedTask);
myAdjuster.run((Task[]) myModifiedTasks.toArray(new Task[0]));
myDistance2dependencyList.clear();
myModifiedTasks.clear();
myEntranceCounter--;
isRunning = false;
}
public void run(Set taskSet) throws TaskDependencyException {
if (!isEnabled()) {
return;
}
isRunning = true;
myEntranceCounter++;
myMarkedTasks.clear();
for (Iterator tasks = taskSet.iterator(); tasks.hasNext();) {
Task nextTask = (Task) tasks.next();
buildDistanceGraph(nextTask);
fulfilDependencies();
myDistance2dependencyList.clear();
myModifiedTasks.add(nextTask);
}
myAdjuster.run((Task[]) myModifiedTasks.toArray(new Task[0]));
myDistance2dependencyList.clear();
myModifiedTasks.clear();
myEntranceCounter--;
isRunning = false;
}
public void run() throws TaskDependencyException {
if (!isEnabled()) {
return;
}
isRunning = true;
TaskContainmentHierarchyFacade facade = createContainmentFacade();
Set independentTasks = new HashSet();
traverse(facade, facade.getRootTask(), independentTasks);
for (Iterator it = independentTasks.iterator(); it.hasNext();) {
Task next = (Task) it.next();
buildDistanceGraph(next);
}
fulfilDependencies();
isRunning = false;
}
public boolean isRunning() {
return isRunning;
}
private void traverse(TaskContainmentHierarchyFacade facade, Task root,
Set independentTasks) {
TaskDependency[] asDependant = root.getDependenciesAsDependant()
.toArray();
if (asDependant.length == 0) {
independentTasks.add(root);
}
Task[] nestedTasks = facade.getNestedTasks(root);
for (int i = 0; i < nestedTasks.length; i++) {
traverse(facade, nestedTasks[i], independentTasks);
}
}
private void fulfilDependencies() throws TaskDependencyException {
// System.err.println("[RecalculateTaskSchedule]
// >>>fulfilDependencies()");
for (Iterator distances = myDistance2dependencyList.entrySet()
.iterator(); distances.hasNext();) {
Map.Entry nextEntry = (Map.Entry) distances.next();
List nextDependenciesList = (List) nextEntry.getValue();
for (int i = 0; i < nextDependenciesList.size(); i++) {
TaskDependency nextDependency = (TaskDependency) nextDependenciesList
.get(i);
TaskDependencyConstraint nextConstraint = nextDependency
.getConstraint();
TaskDependencyConstraint.Collision collision = nextConstraint
.getCollision();
if (collision.isActive()) {
fulfilConstraints(nextDependency);
nextDependency.getDependant().applyThirdDateConstraint();
}
}
}
// System.err.println("[RecalculateTaskSchedule]
// <<<fulfilDependencies()");
}
private void fulfilConstraints(TaskDependency dependency)
throws TaskDependencyException {
Task dependant = dependency.getDependant();
TaskDependency[] depsAsDependant = dependant
.getDependenciesAsDependant().toArray();
if (depsAsDependant.length > 0) {
ArrayList startLaterVariations = new ArrayList();
ArrayList startEarlierVariations = new ArrayList();
ArrayList noVariations = new ArrayList();
//
for (int i = 0; i < depsAsDependant.length; i++) {
TaskDependency next = depsAsDependant[i];
TaskDependencyConstraint.Collision nextCollision = next
.getConstraint().getCollision();
GanttCalendar acceptableStart = nextCollision
.getAcceptableStart();
switch (nextCollision.getVariation()) {
case TaskDependencyConstraint.Collision.START_EARLIER_VARIATION: {
startEarlierVariations.add(acceptableStart);
break;
}
case TaskDependencyConstraint.Collision.START_LATER_VARIATION: {
startLaterVariations.add(acceptableStart);
break;
}
case TaskDependencyConstraint.Collision.NO_VARIATION: {
noVariations.add(acceptableStart);
break;
}
}
}
if (noVariations.size() > 1) {
throw new TaskDependencyException(
"Failed to fulfill constraints of task="
+ dependant
+ ". There are "
+ noVariations.size()
+ " constraints which don't allow for task start variation");
}
//
Collections.sort(startEarlierVariations);
Collections.sort(startLaterVariations);
//
GanttCalendar solution;
GanttCalendar earliestStart = (GanttCalendar) (startEarlierVariations
.size() == 0 ? null : startEarlierVariations.get(0));
GanttCalendar latestStart = (GanttCalendar) (startLaterVariations
.size() >= 0 ? startLaterVariations
.get(startLaterVariations.size() - 1) : null);
if (earliestStart == null && latestStart == null) {
solution = dependant.getStart();
} else {
if (earliestStart == null && latestStart != null) {
earliestStart = latestStart;
} else if (earliestStart != null && latestStart == null) {
latestStart = earliestStart;
}
if (earliestStart.compareTo(latestStart) < 0) {
throw new TaskDependencyException(
"Failed to fulfill constraints of task="
+ dependant);
}
}
if (noVariations.size() > 0) {
GanttCalendar notVariableStart = (GanttCalendar) noVariations
.get(0);
if (notVariableStart.compareTo(earliestStart) < 0
|| notVariableStart.compareTo(latestStart) > 0) {
throw new TaskDependencyException(
"Failed to fulfill constraints of task="
+ dependant);
}
solution = notVariableStart;
} else {
solution = latestStart;
}
//
modifyTaskStart(dependant, solution);
}
}
private void modifyTaskStart(Task task, GanttCalendar newStart) {
TaskMutator mutator = task.createMutator();
mutator.createFixedDurationTimeInterval().setStartDate(newStart.getTime());
mutator.commit();
myModifiedTasks.add(task);
}
private void modifyTaskEnd(Task task, GanttCalendar taskEnd) {
task.setEnd(taskEnd);
myModifiedTasks.add(task);
}
private void buildDistanceGraph(Task changedTask) {
TaskDependency[] depsAsDependee = changedTask
.getDependenciesAsDependee().toArray();
buildDistanceGraph(depsAsDependee, 1);
}
private void buildDistanceGraph(TaskDependency[] deps, int distance) {
if (deps.length == 0) {
return;
}
Integer key = new Integer(distance);
List depsList = (List) myDistance2dependencyList.get(key);
if (depsList == null) {
depsList = new ArrayList();
myDistance2dependencyList.put(key, depsList);
}
depsList.addAll(Arrays.asList(deps));
for (int i = 0; i < deps.length; i++) {
Task dependant = deps[i].getDependant();
TaskDependency[] nextStepDeps = dependant
.getDependenciesAsDependee().toArray();
buildDistanceGraph(nextStepDeps, ++distance);
}
}
/*
* private void forwardScheduling(Task changedTask,
* TaskContainmentHierarchyFacade containmentFacade) { //new
* Exception().printStackTrace(); //System.out.println("forword scheduling:
* "+count++); //for Debug CL /////////////////////////////////
* //setAllDependencies(); ////Code should be deleted after the depend has
* been replaced by successors //////////////////////////////// ArrayList
* taskNodes = null;//getAllTasks(); for (int i = 0; i < taskNodes.size();
* i++) { DefaultMutableTreeNode node = (DefaultMutableTreeNode)
* taskNodes.get(i); if (node.getChildCount() == 0) { //it is not a mother
* task GanttTask task = (GanttTask) node.getUserObject(); if
* (!task.isChecked()) { findEarliestStart(task); } } } //Treat the mother
* task. (the children have been scheduled.) //start date of mother task
* should be the earliest start date of its children //finish date of mother
* task is the last finish date of its children for (int i = 0; i <
* taskNodes.size(); i++) { DefaultMutableTreeNode node =
* (DefaultMutableTreeNode) taskNodes.get(i); if (node.getChildCount() != 0) {
* //it is a mother task if (node.isRoot()) { continue; } Task task = (Task)
* node.getUserObject(); GanttCalendar earliestStartDate = new
* GanttCalendar(2949, 10, 1); GanttCalendar earliestFinishDate = new
* GanttCalendar(1049, 10, 1); //find the earliest date of children's start
* dates //find the last finish date of children's finish dates Enumeration
* childNodes = node.children(); while (childNodes.hasMoreElements()) { Task
* childTask = (Task) ((DefaultMutableTreeNode) childNodes.nextElement()).
* getUserObject(); if (earliestStartDate.compareTo(childTask.getStart()) >
* 0) { earliestStartDate = childTask.getStart().Clone(); } if
* (earliestFinishDate.compareTo(childTask.getEnd()) < 0) {
* earliestFinishDate = childTask.getEnd().Clone(); } }
* task.setStart(earliestStartDate); task.setEnd(earliestFinishDate); } } }
* //static int countFindEarliestStart=0;//for Debug CL private void
* findEarliestStart(Task task) { //System.out.println("I m in
* findEarliestStart for "+countFindEarliestStart++);//for Debug CL
* GanttCalendar earliestStart = new GanttCalendar(1099, 10, 1); //set the
* earliest start date to be some date impossible. at least where I don't
* care:) if (!isMarked(task)) { TaskDependency[] asDependant =
* task.getDependenciesAsDependant().toArray(); //for the task without
* predecessor, the start date is the earliest start date if
* (asDependant.length==0) { markTask(task); return; } //If there are
* predecessors, the earliest date should be depended //on the relationship
* type and start or end date of each predecessor. for (int i = 0; i <
* asDependant.length; i++) { Task predecessorTask =
* asDependant[i].getDependee(); int relationshipType =
* ((GanttTaskRelationship) predecessors.get(i)).getRelationshipType(); if
* (relationshipType == GanttTaskRelationship.FS) {
* //////////////////////////////////// //FS realtionship: the earliest
* start date should be the //latest earliest finish date of all the
* predecessors //////////////////////////////////// if
* (!predecessorTask.isChecked()) { //If ther predecessor has not been
* checked, check it here. It is a recursive algorithm
* findEarliestStart(predecessorTask); } if (predecessorTask.isChecked()) {
* //if checked, the start and end date are valid GanttCalendar temp =
* predecessorTask.getEnd().Clone(); //temp.add(1); //should be one day
* behind the predecessor finish date. if (temp.compareTo(earliestStart) >
* 0) { //if the current earliest start is earlier than the end date of one
* of its prodecessor, it set equal to the end date of this predecessor
* earliestStart = temp; } } } else if (relationshipType ==
* GanttTaskRelationship.FF) { //////////////////////////////////// //FF
* realtionship: As soon as the predecessor task finishes, //the successor
* task can finish //////////////////////////////////// if
* (!predecessorTask.isChecked()) { findEarliestStart(predecessorTask);
* //check the predecessor } if (predecessorTask.isChecked()) {
* GanttCalendar temp = predecessorTask.getEnd().Clone(); GanttCalendar
* earliestFinish = earliestStart; earliestFinish.add(task.getLength()); if
* (earliestFinish.compareTo(temp) < 0) { //if the earliest finish is
* earlier than the end date of its predecessor, it set equal to the end
* date of predecessor earliestFinish = temp.Clone(); earliestStart =
* earliestFinish.Clone(); earliestStart.add(-task.getLength()); } else {
* //do nothing, if it is behind end date of predecessor } } } else if
* (relationshipType == GanttTaskRelationship.SF) {
* //////////////////////////////////// //SF realtionship: As soon as the
* predecessor task starts, //the successor task can finish.
* //////////////////////////////////// if (!predecessorTask.isChecked()) {
* findEarliestStart(predecessorTask); //if the predecessor has not been
* checked, check it here. it is a recursive algorithm } if
* (predecessorTask.isChecked()) { GanttCalendar temp =
* predecessorTask.getStart().Clone(); GanttCalendar earliestFinish =
* earliestStart; earliestFinish.add(task.getLength()); if
* (earliestFinish.compareTo(temp) < 0) { //if the earliest finish of the
* task is earlier than the start date of one of its predecessors, it set
* equal to the start date of the predecessor earliestFinish = temp.Clone();
* earliestStart = earliestFinish.Clone();
* earliestStart.add(-task.getLength()); } else { //already satisfied the SF
* relationship, do nothing } } } else if (relationshipType ==
* GanttTaskRelationship.SS) { //////////////////////////////////// //SS
* realtionship: As soon as the predecessor task starts, //the successor
* task can start. //////////////////////////////////// if
* (!predecessorTask.isChecked()) { findEarliestStart(predecessorTask); //if
* the predecessor has not been checked, check it here. it is a recursive
* algorithm } if (predecessorTask.isChecked()) { GanttCalendar temp =
* predecessorTask.getStart().Clone(); if (earliestStart.compareTo(temp) <
* 0) { // if the start date of the task is earlier than the start date of
* its predecessor, it set equal to the start date of predecessor
* earliestStart = temp.Clone(); } else { //already satisfied the SS
* relationship, do nothing. } } } } if
* (earliestStart.compareTo(task.getStart()) < 0) { //if the actual start is
* behind earliest start, don't need to do anything } else {
* task.setStart(earliestStart); GanttCalendar temp = earliestStart.Clone();
* temp.add(task.getLength()); task.setEnd(temp); } task.setChecked(true); }
* return; }
*/
private void markTask(Task task) {
myMarkedTasks.add(task);
}
private boolean isMarked(Task task) {
return myMarkedTasks.contains(task);
}
protected abstract TaskContainmentHierarchyFacade createContainmentFacade();
}
The table below shows all metrics for RecalculateTaskScheduleAlgorithm.java.




