source: branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/Task.java @ 1587

Last change on this file since 1587 was 1400, checked in by pharms, 10 years ago
  • added possibility to determine execution variants of a task
  • Property svn:executable set to *
File size: 10.7 KB
Line 
1//   Copyright 2012 Georg-August-Universität Göttingen, Germany
2//
3//   Licensed under the Apache License, Version 2.0 (the "License");
4//   you may not use this file except in compliance with the License.
5//   You may obtain a copy of the License at
6//
7//       http://www.apache.org/licenses/LICENSE-2.0
8//
9//   Unless required by applicable law or agreed to in writing, software
10//   distributed under the License is distributed on an "AS IS" BASIS,
11//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//   See the License for the specific language governing permissions and
13//   limitations under the License.
14
15package de.ugoe.cs.autoquest.tasktrees.treeimpl;
16
17import java.util.Collection;
18import java.util.Collections;
19import java.util.HashSet;
20import java.util.LinkedList;
21
22import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance;
23import de.ugoe.cs.autoquest.tasktrees.treeifc.IIterationInstance;
24import de.ugoe.cs.autoquest.tasktrees.treeifc.IOptionalInstance;
25import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelectionInstance;
26import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequenceInstance;
27import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
28import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
29import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList;
30import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskVisitor;
31
32/**
33 * <p>
34 * this is the default implementation of the interface {@link ITask}. It
35 * does not do anything fancy except implementing the interface.
36 * </p>
37 *
38 * @author Patrick Harms
39 */
40abstract class Task implements ITask {
41
42    /**
43     * <p>
44     * default serial version UID
45     * </p>
46     */
47    private static final long serialVersionUID = 1L;
48
49    /**
50     * <p>
51     * used as a counter to generate new ids for each newly created task. May overflow.
52     * </p>
53     */
54    private static int temporalId = 0;
55
56    /**
57     * <p>
58     * the id of the task (unique throughout the system as long as {@link #temporalId} does not
59     * overflow.
60     * </p>
61     */
62    private int id;
63   
64    /**
65     * <p>
66     * a human readable type of the task (used for visualization purposes)
67     * </p>
68     */
69    private String type;
70
71    /**
72     * <p>
73     * a human readable description of the task
74     * </p>
75     */
76    private String description;
77   
78    /**
79     * <p>
80     * the instances of this task
81     * </p>
82     */
83    private Collection<ITaskInstance> instances = new HashSet<ITaskInstance>();
84   
85    /**
86     * <p>
87     * the execution variants of this task
88     * </p>
89     */
90    private Collection<Collection<ITaskInstance>> executionVariants;
91
92    /**
93     * <p>
94     * constructs a new task with a new id. The id is generated using the {@link #getNewId()}
95     * method
96     * </p>
97     *
98     * @param type the human readable type of the task
99     *
100     * @throws IllegalArgumentException in the case the provided type is null
101     */
102    Task(String type) {
103        this.id = getNewId();
104        this.type = type;
105       
106        if (type == null) {
107            throw new IllegalArgumentException("type must not be null");
108        }
109    }
110
111    /**
112     * <p>
113     * creates a new id for a task using {@link #temporalId} by incrementing it an returning its
114     * current value. Resets the counter if {@link Integer.MAX_VALUE} is reached.
115     * </p>
116     *
117     * @return a new unique id for a task as long as {@link #temporalId} does not overflow
118     */
119    private static synchronized int getNewId() {
120        if (temporalId == Integer.MAX_VALUE) {
121            temporalId = 0;
122        }
123
124        return temporalId++;
125    }
126
127    /* (non-Javadoc)
128     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#geId()
129     */
130    @Override
131    public int getId() {
132        return id;
133    }
134
135    /* (non-Javadoc)
136     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#getType()
137     */
138    @Override
139    public String getType() {
140        return type;
141    }
142
143    /* (non-Javadoc)
144     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#getDescription()
145     */
146    @Override
147    public String getDescription() {
148        return description;
149    }
150
151    /* (non-Javadoc)
152     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#getInstances()
153     */
154    @Override
155    public Collection<ITaskInstance> getInstances() {
156        return Collections.unmodifiableCollection(instances);
157    }
158
159    /* (non-Javadoc)
160     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#getExecutionVariants()
161     */
162    @Override
163    public synchronized Collection<Collection<ITaskInstance>> getExecutionVariants() {
164        if (executionVariants == null) {
165            executionVariants = new LinkedList<Collection<ITaskInstance>>();
166            determineExecutionVariants(executionVariants);
167        }
168       
169        return executionVariants;
170    }
171
172    /* (non-Javadoc)
173     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#equals(ITask)
174     */
175    @Override
176    public final boolean equals(ITask task) {
177        // tasks are only equal if they are identical or if they have the same id
178        // (may happen, if they are cloned)
179        return (this == task) || (this.hashCode() == task.hashCode());
180    }
181
182    /* (non-Javadoc)
183     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#hashCode()
184     */
185    @Override
186    public synchronized int hashCode() {
187        return id;
188    }
189
190    /* (non-Javadoc)
191     * @see java.lang.Object#toString()
192     */
193    @Override
194    public synchronized String toString() {
195        StringBuffer result = new StringBuffer();
196        result.append(type);
197        result.append(" #");
198        result.append(id);
199       
200        if (description != null) {
201            result.append(" (");
202            result.append(description);
203            result.append(')');
204        }
205       
206        return result.toString();
207    }
208
209    /* (non-Javadoc)
210     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#clone()
211     */
212    @Override
213    public synchronized ITask clone() {
214        Task clone = null;
215        try {
216            clone = (Task) super.clone();
217        }
218        catch (CloneNotSupportedException e) {
219            // this should never happen. Therefore simply dump the exception
220            e.printStackTrace();
221        }
222
223        return clone;
224    }
225
226    /**
227     * <p>
228     * internally used to set the human readable description of the task
229     * </p>
230     *
231     * @param description the new human readable description of the task
232     */
233    void setDescription(String description) {
234        this.description = description;
235    }
236
237    /**
238     * <p>
239     * internally used to remove an instance from this task
240     * </p>
241     *
242     * @param instance the instance to be removed from this task
243     */
244    synchronized void removeInstance(ITaskInstance instance) {
245        this.instances.remove(instance);
246        this.executionVariants = null;
247    }
248
249    /**
250     * <p>
251     * internally used to add an instance to this task
252     * </p>
253     *
254     * @param instance the instance belonging to this task
255     */
256    synchronized void addInstance(ITaskInstance instance) {
257        this.instances.add(instance);
258        this.executionVariants = null;
259    }
260   
261    /* (non-Javadoc)
262     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#accept(ITaskVisitor)
263     */
264    @Override
265    public void accept(ITaskVisitor visitor) {
266        visitor.visit(this);
267    }
268
269    /**
270     *
271     */
272    private void determineExecutionVariants(Collection<Collection<ITaskInstance>> executionVariants)
273    {
274        for (ITaskInstance instance : instances) {
275            boolean added = false;
276            for (Collection<ITaskInstance> variant : executionVariants) {
277                if (!variant.isEmpty() && (isSameExecution(variant.iterator().next(), instance))) {
278                    variant.add(instance);
279                    added = true;
280                }
281            }
282           
283            if (!added) {
284                Collection<ITaskInstance> variant = new HashSet<ITaskInstance>();
285                variant.add(instance);
286                executionVariants.add(variant);
287            }
288        }
289    }
290
291    /**
292     *
293     */
294    private boolean isSameExecution(ITaskInstance instance1, ITaskInstance instance2) {
295        if (instance1 instanceof IIterationInstance) {
296            if (!(instance2 instanceof IIterationInstance)) {
297                return false;
298            }
299           
300            ITaskInstanceList iteration1 = (ITaskInstanceList) instance1;
301            ITaskInstanceList iteration2 = (ITaskInstanceList) instance2;
302           
303            return isSameExecutionList(iteration1, iteration2);
304        }
305        else if (instance1 instanceof ISequenceInstance) {
306            if (!(instance2 instanceof ISequenceInstance)) {
307                return false;
308            }
309           
310            ITaskInstanceList selection1 = (ITaskInstanceList) instance1;
311            ITaskInstanceList selection2 = (ITaskInstanceList) instance2;
312           
313            return isSameExecutionList(selection1, selection2);
314        }
315        else if (instance1 instanceof ISelectionInstance) {
316            if (!(instance2 instanceof ISelectionInstance)) {
317                return false;
318            }
319            else {
320                return isSameExecution(((ISelectionInstance) instance1).getChild(),
321                                       ((ISelectionInstance) instance2).getChild());
322            }
323        }
324        else if (instance1 instanceof IOptionalInstance) {
325            if (!(instance2 instanceof IOptionalInstance)) {
326                return false;
327            }
328            else {
329                return isSameExecution(((IOptionalInstance) instance1).getChild(),
330                                       ((IOptionalInstance) instance2).getChild());
331            }
332        }
333        else if (instance1 instanceof IEventTaskInstance) {
334            if (!(instance2 instanceof IEventTaskInstance)) {
335                return false;
336            }
337            else {
338                return ((IEventTaskInstance) instance1).getTask().equals
339                    (((IEventTaskInstance) instance2).getTask());
340            }
341        }
342        else if (instance1 == null) {
343            return instance2 == null;
344        }
345        else {
346            throw new IllegalArgumentException("unknown type of task instance: " + instance1);
347        }
348    }
349
350    /**
351     *
352     */
353    private boolean isSameExecutionList(ITaskInstanceList list1, ITaskInstanceList list2) {
354        if (list1.size() == list2.size()) {
355            for (int i = 0; i < list1.size(); i++) {
356                if (!isSameExecution(list1.get(i), list2.get(i))) {
357                    return false;
358                }
359            }
360           
361            return true;
362        }
363        else {
364            return false;
365        }
366    }
367}
Note: See TracBrowser for help on using the repository browser.