source: trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/Task.java @ 2126

Last change on this file since 2126 was 2126, checked in by pharms, 8 years ago
  • implemented some performance improvements
  • Property svn:executable set to *
File size: 10.9 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 final Collection<ITaskInstance> instances = new HashSet<ITaskInstance>();
84   
85    /**
86     * <p>
87     * the unmodifiable view on the instances of this task
88     * </p>
89     */
90    private final Collection<ITaskInstance> unmodifiableInstances;
91   
92    /**
93     * <p>
94     * the execution variants of this task
95     * </p>
96     */
97    private Collection<Collection<ITaskInstance>> executionVariants;
98
99    /**
100     * <p>
101     * constructs a new task with a new id. The id is generated using the {@link #getNewId()}
102     * method
103     * </p>
104     *
105     * @param type the human readable type of the task
106     *
107     * @throws IllegalArgumentException in the case the provided type is null
108     */
109    Task(String type) {
110        this.id = getNewId();
111        this.type = type;
112       
113        if (type == null) {
114            throw new IllegalArgumentException("type must not be null");
115        }
116       
117        unmodifiableInstances = Collections.unmodifiableCollection(instances);
118    }
119
120    /**
121     * <p>
122     * creates a new id for a task using {@link #temporalId} by incrementing it an returning its
123     * current value. Resets the counter if {@link Integer.MAX_VALUE} is reached.
124     * </p>
125     *
126     * @return a new unique id for a task as long as {@link #temporalId} does not overflow
127     */
128    private static synchronized int getNewId() {
129        if (temporalId == Integer.MAX_VALUE) {
130            temporalId = 0;
131        }
132
133        return temporalId++;
134    }
135
136    /* (non-Javadoc)
137     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#geId()
138     */
139    @Override
140    public int getId() {
141        return id;
142    }
143
144    /* (non-Javadoc)
145     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#getType()
146     */
147    @Override
148    public String getType() {
149        return type;
150    }
151
152    /* (non-Javadoc)
153     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#getDescription()
154     */
155    @Override
156    public String getDescription() {
157        return description;
158    }
159
160    /* (non-Javadoc)
161     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#getInstances()
162     */
163    @Override
164    public Collection<ITaskInstance> getInstances() {
165        return unmodifiableInstances;
166    }
167
168    /* (non-Javadoc)
169     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#getExecutionVariants()
170     */
171    @Override
172    public synchronized Collection<Collection<ITaskInstance>> getExecutionVariants() {
173        if (executionVariants == null) {
174            executionVariants = new LinkedList<Collection<ITaskInstance>>();
175            determineExecutionVariants(executionVariants);
176        }
177       
178        return executionVariants;
179    }
180
181    /* (non-Javadoc)
182     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#equals(ITask)
183     */
184    @Override
185    public final boolean equals(ITask task) {
186        // tasks are only equal if they are identical or if they have the same id
187        // (may happen, if they are cloned)
188        return (this == task) || (this.hashCode() == task.hashCode());
189    }
190
191    /* (non-Javadoc)
192     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#hashCode()
193     */
194    @Override
195    public synchronized int hashCode() {
196        return id;
197    }
198
199    /* (non-Javadoc)
200     * @see java.lang.Object#toString()
201     */
202    @Override
203    public synchronized String toString() {
204        StringBuffer result = new StringBuffer();
205        result.append(type);
206        result.append(" #");
207        result.append(id);
208       
209        if (description != null) {
210            result.append(" (");
211            result.append(description);
212            result.append(')');
213        }
214       
215        return result.toString();
216    }
217
218    /* (non-Javadoc)
219     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#clone()
220     */
221    @Override
222    public synchronized ITask clone() {
223        Task clone = null;
224        try {
225            clone = (Task) super.clone();
226        }
227        catch (CloneNotSupportedException e) {
228            // this should never happen. Therefore simply dump the exception
229            e.printStackTrace();
230        }
231
232        return clone;
233    }
234
235    /**
236     * <p>
237     * internally used to set the human readable description of the task
238     * </p>
239     *
240     * @param description the new human readable description of the task
241     */
242    void setDescription(String description) {
243        this.description = description;
244    }
245
246    /**
247     * <p>
248     * internally used to remove an instance from this task
249     * </p>
250     *
251     * @param instance the instance to be removed from this task
252     */
253    synchronized void removeInstance(ITaskInstance instance) {
254        this.instances.remove(instance);
255        this.executionVariants = null;
256    }
257
258    /**
259     * <p>
260     * internally used to add an instance to this task
261     * </p>
262     *
263     * @param instance the instance belonging to this task
264     */
265    synchronized void addInstance(ITaskInstance instance) {
266        this.instances.add(instance);
267        this.executionVariants = null;
268    }
269   
270    /* (non-Javadoc)
271     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#accept(ITaskVisitor)
272     */
273    @Override
274    public void accept(ITaskVisitor visitor) {
275        visitor.visit(this);
276    }
277
278    /**
279     *
280     */
281    private void determineExecutionVariants(Collection<Collection<ITaskInstance>> executionVariants)
282    {
283        for (ITaskInstance instance : instances) {
284            boolean added = false;
285            for (Collection<ITaskInstance> variant : executionVariants) {
286                if (!variant.isEmpty() && (isSameExecution(variant.iterator().next(), instance))) {
287                    variant.add(instance);
288                    added = true;
289                }
290            }
291           
292            if (!added) {
293                Collection<ITaskInstance> variant = new HashSet<ITaskInstance>();
294                variant.add(instance);
295                executionVariants.add(variant);
296            }
297        }
298    }
299
300    /**
301     *
302     */
303    private boolean isSameExecution(ITaskInstance instance1, ITaskInstance instance2) {
304        if (instance1 instanceof IIterationInstance) {
305            if (!(instance2 instanceof IIterationInstance)) {
306                return false;
307            }
308           
309            ITaskInstanceList iteration1 = (ITaskInstanceList) instance1;
310            ITaskInstanceList iteration2 = (ITaskInstanceList) instance2;
311           
312            return isSameExecutionList(iteration1, iteration2);
313        }
314        else if (instance1 instanceof ISequenceInstance) {
315            if (!(instance2 instanceof ISequenceInstance)) {
316                return false;
317            }
318           
319            ITaskInstanceList selection1 = (ITaskInstanceList) instance1;
320            ITaskInstanceList selection2 = (ITaskInstanceList) instance2;
321           
322            return isSameExecutionList(selection1, selection2);
323        }
324        else if (instance1 instanceof ISelectionInstance) {
325            if (!(instance2 instanceof ISelectionInstance)) {
326                return false;
327            }
328            else {
329                return isSameExecution(((ISelectionInstance) instance1).getChild(),
330                                       ((ISelectionInstance) instance2).getChild());
331            }
332        }
333        else if (instance1 instanceof IOptionalInstance) {
334            if (!(instance2 instanceof IOptionalInstance)) {
335                return false;
336            }
337            else {
338                return isSameExecution(((IOptionalInstance) instance1).getChild(),
339                                       ((IOptionalInstance) instance2).getChild());
340            }
341        }
342        else if (instance1 instanceof IEventTaskInstance) {
343            if (!(instance2 instanceof IEventTaskInstance)) {
344                return false;
345            }
346            else {
347                return ((IEventTaskInstance) instance1).getTask().equals
348                    (((IEventTaskInstance) instance2).getTask());
349            }
350        }
351        else if (instance1 == null) {
352            return instance2 == null;
353        }
354        else {
355            throw new IllegalArgumentException("unknown type of task instance: " + instance1);
356        }
357    }
358
359    /**
360     *
361     */
362    private boolean isSameExecutionList(ITaskInstanceList list1, ITaskInstanceList list2) {
363        if (list1.size() == list2.size()) {
364            for (int i = 0; i < list1.size(); i++) {
365                if (!isSameExecution(list1.get(i), list2.get(i))) {
366                    return false;
367                }
368            }
369           
370            return true;
371        }
372        else {
373            return false;
374        }
375    }
376}
Note: See TracBrowser for help on using the repository browser.