Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 200235
Collapse All | Expand All

(-)src/org/eclipse/mylyn/tasks/core/AbstractTaskContainer.java (-5 / +10 lines)
Lines 13-19 Link Here
13
import java.util.concurrent.CopyOnWriteArraySet;
13
import java.util.concurrent.CopyOnWriteArraySet;
14
14
15
import org.eclipse.core.runtime.PlatformObject;
15
import org.eclipse.core.runtime.PlatformObject;
16
import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants;
17
import org.eclipse.mylyn.tasks.core.AbstractTask.PriorityLevel;
16
import org.eclipse.mylyn.tasks.core.AbstractTask.PriorityLevel;
18
17
19
/**
18
/**
Lines 97-112 Link Here
97
	 * TODO: review policy
96
	 * TODO: review policy
98
	 */
97
	 */
99
	public boolean contains(String handle) {
98
	public boolean contains(String handle) {
100
		return containsHelper(getChildrenInternal(), handle, 0);
99
		return containsHelper(getChildrenInternal(), handle, new HashSet<AbstractTaskContainer>());
101
	}
100
	}
102
101
103
	private boolean containsHelper(Set<AbstractTask> children, String handle, int depth) {
102
	private boolean containsHelper(Set<AbstractTask> children, String handle,
104
		if (depth < ITasksCoreConstants.MAX_SUBTASK_DEPTH && children != null && !children.isEmpty()) {
103
			Set<AbstractTaskContainer> visitedContainers) {
104
		if (children != null && !children.isEmpty()) {
105
			for (AbstractTask child : children) {
105
			for (AbstractTask child : children) {
106
				if (visitedContainers.contains(child)) {
107
					continue;
108
				}
109
				visitedContainers.add(child);
110
106
				if (child != null
111
				if (child != null
107
						&& handle != null
112
						&& handle != null
108
						&& (handle.equals(child.getHandleIdentifier()) || containsHelper(child.getChildrenInternal(),
113
						&& (handle.equals(child.getHandleIdentifier()) || containsHelper(child.getChildrenInternal(),
109
								handle, depth + 1))) {
114
								handle, visitedContainers))) {
110
					return true;
115
					return true;
111
				}
116
				}
112
			}
117
			}
(-)src/org/eclipse/mylyn/tasks/core/TaskList.java (-8 / +17 lines)
Lines 65-77 Link Here
65
	 * @since 2.2
65
	 * @since 2.2
66
	 */
66
	 */
67
	private void addOrphan(AbstractTask task, Set<TaskContainerDelta> delta) {
67
	private void addOrphan(AbstractTask task, Set<TaskContainerDelta> delta) {
68
		addOrphan(task, delta, 0);
68
		addOrphan(task, delta, new HashSet<AbstractTaskContainer>());
69
	}
69
	}
70
70
71
	/**
71
	/**
72
	 * @since 2.2
72
	 * @since 2.2
73
	 */
73
	 */
74
	private void addOrphan(AbstractTask task, Set<TaskContainerDelta> delta, int depth) {
74
	private void addOrphan(AbstractTask task, Set<TaskContainerDelta> delta,
75
			Set<AbstractTaskContainer> visitedContainers) {
75
		if (!task.getParentContainers().isEmpty()) {
76
		if (!task.getParentContainers().isEmpty()) {
76
			// Current policy is not to archive/orphan if the task exists in some other container
77
			// Current policy is not to archive/orphan if the task exists in some other container
77
			return;
78
			return;
Lines 101-109 Link Here
101
			//StatusHandler.log("Orphan container not found for: " + task.getRepositoryUrl(), this);
102
			//StatusHandler.log("Orphan container not found for: " + task.getRepositoryUrl(), this);
102
		}
103
		}
103
104
104
		if (depth < ITasksCoreConstants.MAX_SUBTASK_DEPTH && !task.isEmpty()) {
105
		if (!task.isEmpty()) {
105
			for (AbstractTask child : task.getChildren()) {
106
			for (AbstractTask child : task.getChildren()) {
106
				addOrphan(child, delta, depth + 1);
107
				if (visitedContainers.contains(child)) {
108
					continue;
109
				}
110
				visitedContainers.add(child);
111
				addOrphan(child, delta, visitedContainers);
107
			}
112
			}
108
		}
113
		}
109
114
Lines 113-125 Link Here
113
	 * @since 2.2
118
	 * @since 2.2
114
	 */
119
	 */
115
	private void removeOrphan(AbstractTask task, Set<TaskContainerDelta> delta) {
120
	private void removeOrphan(AbstractTask task, Set<TaskContainerDelta> delta) {
116
		removeOrphan(task, delta, 0);
121
		removeOrphan(task, delta, new HashSet<AbstractTaskContainer>());
117
	}
122
	}
118
123
119
	/**
124
	/**
120
	 * @since 2.2
125
	 * @since 2.2
121
	 */
126
	 */
122
	private void removeOrphan(AbstractTask task, Set<TaskContainerDelta> delta, int depth) {
127
	private void removeOrphan(AbstractTask task, Set<TaskContainerDelta> delta, Set<AbstractTaskContainer> visitedTasks) {
123
		UnmatchedTaskContainer orphans = repositoryOrphansMap.get(task.getRepositoryUrl());
128
		UnmatchedTaskContainer orphans = repositoryOrphansMap.get(task.getRepositoryUrl());
124
		if (orphans != null) {
129
		if (orphans != null) {
125
			if (orphans.contains(task.getHandleIdentifier())) {
130
			if (orphans.contains(task.getHandleIdentifier())) {
Lines 128-136 Link Here
128
					delta.add(new TaskContainerDelta(orphans, TaskContainerDelta.Kind.CHANGED));
133
					delta.add(new TaskContainerDelta(orphans, TaskContainerDelta.Kind.CHANGED));
129
				}
134
				}
130
135
131
				if (depth < ITasksCoreConstants.MAX_SUBTASK_DEPTH && !task.isEmpty()) {
136
				if (!task.isEmpty()) {
132
					for (AbstractTask child : task.getChildren()) {
137
					for (AbstractTask child : task.getChildren()) {
133
						removeOrphan(child, delta, depth + 1);
138
						if (visitedTasks.contains(child)) {
139
							continue;
140
						}
141
						visitedTasks.add(child);
142
						removeOrphan(child, delta, visitedTasks);
134
					}
143
					}
135
				}
144
				}
136
145
(-)src/org/eclipse/mylyn/internal/tasks/core/ITasksCoreConstants.java (-2 lines)
Lines 13-20 Link Here
13
 */
13
 */
14
public interface ITasksCoreConstants {
14
public interface ITasksCoreConstants {
15
15
16
	public static final int MAX_SUBTASK_DEPTH = 10;
17
18
	public static final String ID_PLUGIN = "org.eclipse.mylyn.tasks.core";
16
	public static final String ID_PLUGIN = "org.eclipse.mylyn.tasks.core";
19
17
20
}
18
}
(-)src/org/eclipse/mylyn/tasks/tests/AbstractTaskContainerTest.java (-1 / +5 lines)
Lines 18-29 Link Here
18
		MockTask task1 = new MockTask("1");
18
		MockTask task1 = new MockTask("1");
19
		MockTask task2 = new MockTask("2");
19
		MockTask task2 = new MockTask("2");
20
		MockTask task3 = new MockTask("3");
20
		MockTask task3 = new MockTask("3");
21
		MockTask task4 = new MockTask("4");
21
22
22
		task1.internalAddChild(task2);
23
		task1.internalAddChild(task2);
23
		task2.internalAddChild(task3);
24
		task2.internalAddChild(task3);
24
		task3.internalAddChild(task1);
25
		task3.internalAddChild(task1);
26
		task3.internalAddChild(task4);
25
27
26
		assertFalse(task1.contains("abc"));
28
		assertTrue(task1.contains(task4.getHandleIdentifier()));
29
		assertTrue(task3.contains(task4.getHandleIdentifier()));
30
		assertFalse(task3.contains("abc"));
27
	}
31
	}
28
32
29
}
33
}
(-)src/org/eclipse/mylyn/internal/context/ui/TaskListInterestFilter.java (-18 / +22 lines)
Lines 9-20 Link Here
9
package org.eclipse.mylyn.internal.context.ui;
9
package org.eclipse.mylyn.internal.context.ui;
10
10
11
import java.util.Calendar;
11
import java.util.Calendar;
12
import java.util.HashSet;
12
import java.util.Set;
13
import java.util.Set;
13
14
14
import org.eclipse.core.runtime.IStatus;
15
import org.eclipse.core.runtime.IStatus;
15
import org.eclipse.core.runtime.Status;
16
import org.eclipse.core.runtime.Status;
16
import org.eclipse.mylyn.context.ui.ContextUiPlugin;
17
import org.eclipse.mylyn.context.ui.ContextUiPlugin;
17
import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants;
18
import org.eclipse.mylyn.internal.tasks.core.LocalRepositoryConnector;
18
import org.eclipse.mylyn.internal.tasks.core.LocalRepositoryConnector;
19
import org.eclipse.mylyn.internal.tasks.core.ScheduledTaskContainer;
19
import org.eclipse.mylyn.internal.tasks.core.ScheduledTaskContainer;
20
import org.eclipse.mylyn.internal.tasks.ui.AbstractTaskListFilter;
20
import org.eclipse.mylyn.internal.tasks.ui.AbstractTaskListFilter;
Lines 59-65 Link Here
59
				}
59
				}
60
60
61
				for (AbstractTask task : children) {
61
				for (AbstractTask task : children) {
62
					if (shouldAlwaysShow(child, task, ITasksCoreConstants.MAX_SUBTASK_DEPTH)) {
62
					if (shouldAlwaysShow(child, task, new HashSet<AbstractTaskContainer>())) {
63
						return true;
63
						return true;
64
					}
64
					}
65
				}
65
				}
Lines 85-94 Link Here
85
85
86
	// TODO: make meta-context more explicit
86
	// TODO: make meta-context more explicit
87
	protected boolean isInteresting(Object parent, AbstractTask task) {
87
	protected boolean isInteresting(Object parent, AbstractTask task) {
88
		return shouldAlwaysShow(parent, task, ITasksCoreConstants.MAX_SUBTASK_DEPTH);
88
		return shouldAlwaysShow(parent, task, new HashSet<AbstractTaskContainer>());
89
	}
89
	}
90
90
91
	public boolean shouldAlwaysShow(Object parent, AbstractTask task, int depth) {
91
	public boolean shouldAlwaysShow(Object parent, AbstractTask task, Set<AbstractTaskContainer> visitedContainers) {
92
92
93
		return task.isActive()
93
		return task.isActive()
94
				|| TasksUiPlugin.getTaskActivityManager().isCompletedToday(task)
94
				|| TasksUiPlugin.getTaskActivityManager().isCompletedToday(task)
Lines 96-115 Link Here
96
				|| !task.isCompleted()
96
				|| !task.isCompleted()
97
				&& (LocalRepositoryConnector.DEFAULT_SUMMARY.equals(task.getSummary())
97
				&& (LocalRepositoryConnector.DEFAULT_SUMMARY.equals(task.getSummary())
98
						|| shouldShowInFocusedWorkweekDateContainer(parent, task)
98
						|| shouldShowInFocusedWorkweekDateContainer(parent, task)
99
						|| TasksUiPlugin.getTaskActivityManager().isOverdue(task) || isInterestingForThisWeek(parent, task) || hasInterestingSubTasks(
99
						|| TasksUiPlugin.getTaskActivityManager().isOverdue(task)
100
						parent, task, depth));
100
						|| isInterestingForThisWeek(parent, task) || hasInterestingSubTasks(parent, task,
101
	}
101
						visitedContainers));
102
102
	}
103
	private boolean hasInterestingSubTasks(Object parent, AbstractTask task, int depth) {
103
104
		if (depth > 0) {
104
	private boolean hasInterestingSubTasks(Object parent, AbstractTask task,
105
			if (!TasksUiPlugin.getDefault().groupSubtasks(task)) {
105
			Set<AbstractTaskContainer> visitedContainers) {
106
				return false;
106
		if (!TasksUiPlugin.getDefault().groupSubtasks(task)) {
107
			}
107
			return false;
108
			if (task.getChildren() != null && task.getChildren().size() > 0) {
108
		}
109
				for (AbstractTask subTask : task.getChildren()) {
109
		if (task.getChildren() != null && task.getChildren().size() > 0) {
110
					if (shouldAlwaysShow(parent, subTask, depth - 1)) {
110
			for (AbstractTask subTask : task.getChildren()) {
111
						return true;
111
				if (visitedContainers.contains(subTask)) {
112
					}
112
					continue;
113
				}
114
				visitedContainers.add(subTask);
115
				if (shouldAlwaysShow(parent, subTask, visitedContainers)) {
116
					return true;
113
				}
117
				}
114
			}
118
			}
115
		}
119
		}
(-)src/org/eclipse/mylyn/internal/tasks/ui/AbstractTaskListFilter.java (-9 / +20 lines)
Lines 7-15 Link Here
7
 *******************************************************************************/
7
 *******************************************************************************/
8
package org.eclipse.mylyn.internal.tasks.ui;
8
package org.eclipse.mylyn.internal.tasks.ui;
9
9
10
import java.util.HashSet;
10
import java.util.Set;
11
import java.util.Set;
11
12
12
import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants;
13
import org.eclipse.mylyn.tasks.core.AbstractTask;
13
import org.eclipse.mylyn.tasks.core.AbstractTask;
14
import org.eclipse.mylyn.tasks.core.AbstractTaskContainer;
14
import org.eclipse.mylyn.tasks.core.AbstractTaskContainer;
15
import org.eclipse.mylyn.tasks.core.AbstractTask.RepositoryTaskSyncState;
15
import org.eclipse.mylyn.tasks.core.AbstractTask.RepositoryTaskSyncState;
Lines 30-55 Link Here
30
	 * TODO: Move to an internal utility class
30
	 * TODO: Move to an internal utility class
31
	 */
31
	 */
32
	public static boolean hasDescendantIncoming(AbstractTaskContainer container) {
32
	public static boolean hasDescendantIncoming(AbstractTaskContainer container) {
33
		return hasDescendantIncoming(container, ITasksCoreConstants.MAX_SUBTASK_DEPTH);
33
		return hasDescendantIncoming(container, new HashSet<AbstractTaskContainer>());
34
	}
34
	}
35
35
36
	public static boolean hasIncompleteDescendant(AbstractTaskContainer container) {
36
	public static boolean hasIncompleteDescendant(AbstractTaskContainer container) {
37
		return hasIncompleteDescendant(container, ITasksCoreConstants.MAX_SUBTASK_DEPTH);
37
		return hasIncompleteDescendant(container, new HashSet<AbstractTaskContainer>());
38
	}
38
	}
39
39
40
	private static boolean hasDescendantIncoming(AbstractTaskContainer container, int depth) {
40
	private static boolean hasDescendantIncoming(AbstractTaskContainer container,
41
			Set<AbstractTaskContainer> visitedContainers) {
41
		Set<AbstractTask> children = container.getChildren();
42
		Set<AbstractTask> children = container.getChildren();
42
		if (children == null || depth <= 0) {
43
		if (children == null) {
43
			return false;
44
			return false;
44
		}
45
		}
45
46
46
		for (AbstractTask task : children) {
47
		for (AbstractTask task : children) {
48
			if (visitedContainers.contains(task)) {
49
				continue;
50
			}
51
			visitedContainers.add(task);
52
47
			if (task != null) {
53
			if (task != null) {
48
				AbstractTask containedRepositoryTask = task;
54
				AbstractTask containedRepositoryTask = task;
49
				if (containedRepositoryTask.getSynchronizationState() == RepositoryTaskSyncState.INCOMING) {
55
				if (containedRepositoryTask.getSynchronizationState() == RepositoryTaskSyncState.INCOMING) {
50
					return true;
56
					return true;
51
				} else if (TasksUiPlugin.getDefault().groupSubtasks(container)
57
				} else if (TasksUiPlugin.getDefault().groupSubtasks(container)
52
						&& hasDescendantIncoming(task, depth - 1)) {
58
						&& hasDescendantIncoming(task, visitedContainers)) {
53
					return true;
59
					return true;
54
				}
60
				}
55
			}
61
			}
Lines 57-74 Link Here
57
		return false;
63
		return false;
58
	}
64
	}
59
65
60
	private static boolean hasIncompleteDescendant(AbstractTaskContainer container, int depth) {
66
	private static boolean hasIncompleteDescendant(AbstractTaskContainer container,
67
			Set<AbstractTaskContainer> visitedContainers) {
61
		Set<AbstractTask> children = container.getChildren();
68
		Set<AbstractTask> children = container.getChildren();
62
		if (children == null || depth <= 0) {
69
		if (children == null) {
63
			return false;
70
			return false;
64
		}
71
		}
65
72
66
		for (AbstractTask task : children) {
73
		for (AbstractTask task : children) {
74
			if (visitedContainers.contains(task)) {
75
				continue;
76
			}
77
			visitedContainers.add(task);
67
			if (task != null) {
78
			if (task != null) {
68
				AbstractTask containedRepositoryTask = task;
79
				AbstractTask containedRepositoryTask = task;
69
				if (!containedRepositoryTask.isCompleted()) {
80
				if (!containedRepositoryTask.isCompleted()) {
70
					return true;
81
					return true;
71
				} else if (hasIncompleteDescendant(task, depth - 1)) {
82
				} else if (hasIncompleteDescendant(task, visitedContainers)) {
72
					return true;
83
					return true;
73
				}
84
				}
74
			}
85
			}

Return to bug 200235