Skip to content

Method: toString()

1: package de.fhdw.wtf.common.task;
2:
3: import java.util.ArrayList;
4: import java.util.Collection;
5: import java.util.Iterator;
6: import java.util.concurrent.Callable;
7:
8: import de.fhdw.wtf.common.exception.walker.CyclicDependencyException;
9: import de.fhdw.wtf.common.exception.walker.DependencyException;
10: import de.fhdw.wtf.common.task.result.ExceptionalTaskResult;
11: import de.fhdw.wtf.common.task.result.OKTaskResult;
12: import de.fhdw.wtf.common.task.result.TaskResult;
13: import de.fhdw.wtf.common.task.result.visitor.TaskResultVisitor;
14:
15: /**
16: * A dependency task is a piece of work that may have dependencies on other tasks completion and on which other tasks
17: * may depend on.
18: *
19: * On successful completion this task checks possible starts of tasks depending on it and submit it.
20: *
21: */
22: public abstract class DependencyTask implements Task, Callable<TaskResult> {
23:         
24:         /**
25:          * Tasks that depend on the successful execution of this task.
26:          */
27:         private final DependencyList dependencies;
28:         
29:         /**
30:          * All dependency-tasks must have exited successfully, before this task may start its work.
31:          */
32:         private final Collection<DependencyTask> observers;
33:         
34:         /**
35:          * Instance of the task executor managing the delayed start of a task, depending on defined thread resources.
36:          */
37:         private final TaskExecutor taskmanager;
38:         
39:         /**
40:          * Constructor. This constructor introduces the new task directly to the task executor!
41:          *
42:          * @see TaskExecutor#introduce(DependencyTask)
43:          *
44:          * @param taskmanager
45:          * task executor, that organizes concurrent execution of tasks
46:          */
47:         public DependencyTask(final TaskExecutor taskmanager) {
48:                 this.dependencies = DependencyList.create(this);
49:                 this.observers = new ArrayList<>();
50:                 this.taskmanager = taskmanager;
51:                 taskmanager.introduce(this);
52:         }
53:         
54:         @Override
55:         public String toString() {
56:                 return this.getClass().getSimpleName();
57:         }
58:         
59:         @Override
60:         public final void start() {
61:                 System.out.println("[submitted] " + this);
62:                 this.taskmanager.submit(this);
63:         }
64:         
65:         /**
66:          * Adds a new task as dependency for the current task.
67:          *
68:          * @param a
69:          * must have completed successfully before this task starts its work
70:          * @throws CyclicDependencyException
71:          * when cyclic dependencies are added
72:          */
73:         public void addDependency(final DependencyTask a) throws CyclicDependencyException {
74:                 
75:                 if (this.contains(a)) {
76:                         throw CyclicDependencyException.create(a.toString());
77:                 } else {
78:                         this.getDependencies().addDependency(a);
79:                         a.register(this);
80:                 }
81:                 
82:         }
83:         
84:         /**
85:          * Adds a new observer on the successful execution of this task.
86:          *
87:          * @param a
88:          * wants to be notified
89:          */
90:         private void register(final DependencyTask a) {
91:                 this.observers.add(a);
92:         }
93:         
94:         /**
95:          * This operation must be called by its owning task, when it has successfully ended its work.
96:          */
97:         synchronized void notifyObservers() {
98:                 final Iterator<DependencyTask> i = this.observers.iterator();
99:                 while (i.hasNext()) {
100:                         final DependencyTask current = i.next();
101:                         current.updateFinished(this);
102:                 }
103:         }
104:         
105:         /**
106:          * Updates the list of dependencies because of <code>task</code> exited successful. It is no longer a dependency to
107:          * be fulfilled.
108:          *
109:          * @param task
110:          * successful executed task
111:          */
112:         private synchronized void updateFinished(final DependencyTask task) {
113:                 final boolean removed = this.getDependencies().remove(task);
114:                 if (!removed) {
115:                         throw new DependencyException(this.toString() + ": Task <" + task.toString()
116:                                         + "> is not registered as dependency or already removed!!");
117:                 }
118:                 if (this.getDependencies().isEmpty()) {
119:                         this.start();
120:                 }
121:         }
122:         
123:         /**
124:          * This tests whether the given task is a part of this task.
125:          *
126:          * @param a
127:          * task to be compared with this task
128:          * @return true, if a is a part of this task
129:          */
130:         public boolean contains(final DependencyTask a) {
131:                 return this.equals(a) || this.containsTransitive(a);
132:         }
133:         
134:         /**
135:          * This tests whether the given task is a transitive part of this task.
136:          *
137:          * @param a
138:          * task to be compared with this task
139:          * @return true, if a is a transitive part of this task
140:          */
141:         public abstract boolean containsTransitive(DependencyTask a);
142:         
143:         @Override
144:         public final TaskResult call() {
145:                 System.out.println("[started] " + this);
146:                 final TaskResult result = this.doWork();
147:                 System.out.println("[ended] " + this);
148:                 result.accept(new TaskResultVisitor() {
149:                         @Override
150:                         public void handleOkTaskResult(final OKTaskResult okTaskResult) {
151:                                 DependencyTask.this.notifyObservers();
152:                         }
153:                         
154:                         @Override
155:                         public void handleExceptionalTaskResult(final ExceptionalTaskResult exceptionalTaskResult) {
156:                                 // Nothing
157:                         }
158:                 });
159:                 
160:                 return result;
161:         }
162:         
163:         /**
164:          * The tasks processes its work and produces a result in the end.
165:          *
166:          * @return result of this task
167:          */
168:         public abstract TaskResult doWork();
169:         
170:         /**
171:          * Gets a list of dependencies - tasks that are required to be run before this task starts its work.
172:          *
173:          * @return list of dependencies
174:          */
175:         protected DependencyList getDependencies() {
176:                 return this.dependencies;
177:         }
178: }