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

Last change on this file since 2136 was 2136, checked in by pharms, 7 years ago
  • Property svn:executable set to *
File size: 11.2 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        // the feature of an unmodifiable collection was added later. To ensure backward
166        // compatibility with stored data, check if the object exists, if not return the instances.
167        if (unmodifiableInstances == null) {
168            return instances;
169        }
170       
171        return unmodifiableInstances;
172    }
173
174    /* (non-Javadoc)
175     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#getExecutionVariants()
176     */
177    @Override
178    public synchronized Collection<Collection<ITaskInstance>> getExecutionVariants() {
179        if (executionVariants == null) {
180            executionVariants = new LinkedList<Collection<ITaskInstance>>();
181            determineExecutionVariants(executionVariants);
182        }
183       
184        return executionVariants;
185    }
186
187    /* (non-Javadoc)
188     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#equals(ITask)
189     */
190    @Override
191    public final boolean equals(ITask task) {
192        // tasks are only equal if they are identical or if they have the same id
193        // (may happen, if they are cloned)
194        return (this == task) || (this.hashCode() == task.hashCode());
195    }
196
197    /* (non-Javadoc)
198     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#hashCode()
199     */
200    @Override
201    public synchronized int hashCode() {
202        return id;
203    }
204
205    /* (non-Javadoc)
206     * @see java.lang.Object#toString()
207     */
208    @Override
209    public synchronized String toString() {
210        StringBuffer result = new StringBuffer();
211        result.append(type);
212        result.append(" #");
213        result.append(id);
214       
215        if (description != null) {
216            result.append(" (");
217            result.append(description);
218            result.append(')');
219        }
220       
221        return result.toString();
222    }
223
224    /* (non-Javadoc)
225     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#clone()
226     */
227    @Override
228    public synchronized ITask clone() {
229        Task clone = null;
230        try {
231            clone = (Task) super.clone();
232        }
233        catch (CloneNotSupportedException e) {
234            // this should never happen. Therefore simply dump the exception
235            e.printStackTrace();
236        }
237
238        return clone;
239    }
240
241    /**
242     * <p>
243     * internally used to set the human readable description of the task
244     * </p>
245     *
246     * @param description the new human readable description of the task
247     */
248    void setDescription(String description) {
249        this.description = description;
250    }
251
252    /**
253     * <p>
254     * internally used to remove an instance from this task
255     * </p>
256     *
257     * @param instance the instance to be removed from this task
258     */
259    synchronized void removeInstance(ITaskInstance instance) {
260        this.instances.remove(instance);
261        this.executionVariants = null;
262    }
263
264    /**
265     * <p>
266     * internally used to add an instance to this task
267     * </p>
268     *
269     * @param instance the instance belonging to this task
270     */
271    synchronized void addInstance(ITaskInstance instance) {
272        this.instances.add(instance);
273        this.executionVariants = null;
274    }
275   
276    /* (non-Javadoc)
277     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#accept(ITaskVisitor)
278     */
279    @Override
280    public void accept(ITaskVisitor visitor) {
281        visitor.visit(this);
282    }
283
284    /**
285     *
286     */
287    private void determineExecutionVariants(Collection<Collection<ITaskInstance>> executionVariants)
288    {
289        for (ITaskInstance instance : instances) {
290            boolean added = false;
291            for (Collection<ITaskInstance> variant : executionVariants) {
292                if (!variant.isEmpty() && (isSameExecution(variant.iterator().next(), instance))) {
293                    variant.add(instance);
294                    added = true;
295                }
296            }
297           
298            if (!added) {
299                Collection<ITaskInstance> variant = new HashSet<ITaskInstance>();
300                variant.add(instance);
301                executionVariants.add(variant);
302            }
303        }
304    }
305
306    /**
307     *
308     */
309    private boolean isSameExecution(ITaskInstance instance1, ITaskInstance instance2) {
310        if (instance1 instanceof IIterationInstance) {
311            if (!(instance2 instanceof IIterationInstance)) {
312                return false;
313            }
314           
315            ITaskInstanceList iteration1 = (ITaskInstanceList) instance1;
316            ITaskInstanceList iteration2 = (ITaskInstanceList) instance2;
317           
318            return isSameExecutionList(iteration1, iteration2);
319        }
320        else if (instance1 instanceof ISequenceInstance) {
321            if (!(instance2 instanceof ISequenceInstance)) {
322                return false;
323            }
324           
325            ITaskInstanceList selection1 = (ITaskInstanceList) instance1;
326            ITaskInstanceList selection2 = (ITaskInstanceList) instance2;
327           
328            return isSameExecutionList(selection1, selection2);
329        }
330        else if (instance1 instanceof ISelectionInstance) {
331            if (!(instance2 instanceof ISelectionInstance)) {
332                return false;
333            }
334            else {
335                return isSameExecution(((ISelectionInstance) instance1).getChild(),
336                                       ((ISelectionInstance) instance2).getChild());
337            }
338        }
339        else if (instance1 instanceof IOptionalInstance) {
340            if (!(instance2 instanceof IOptionalInstance)) {
341                return false;
342            }
343            else {
344                return isSameExecution(((IOptionalInstance) instance1).getChild(),
345                                       ((IOptionalInstance) instance2).getChild());
346            }
347        }
348        else if (instance1 instanceof IEventTaskInstance) {
349            if (!(instance2 instanceof IEventTaskInstance)) {
350                return false;
351            }
352            else {
353                return ((IEventTaskInstance) instance1).getTask().equals
354                    (((IEventTaskInstance) instance2).getTask());
355            }
356        }
357        else if (instance1 == null) {
358            return instance2 == null;
359        }
360        else {
361            throw new IllegalArgumentException("unknown type of task instance: " + instance1);
362        }
363    }
364
365    /**
366     *
367     */
368    private boolean isSameExecutionList(ITaskInstanceList list1, ITaskInstanceList list2) {
369        if (list1.size() == list2.size()) {
370            for (int i = 0; i < list1.size(); i++) {
371                if (!isSameExecution(list1.get(i), list2.get(i))) {
372                    return false;
373                }
374            }
375           
376            return true;
377        }
378        else {
379            return false;
380        }
381    }
382}
Note: See TracBrowser for help on using the repository browser.