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

Last change on this file since 1891 was 1891, checked in by pharms, 9 years ago
  • remove support for tasks contexts in value measurements
  • Property svn:executable set to *
File size: 14.0 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.Arrays;
18import java.util.Collection;
19import java.util.Collections;
20import java.util.HashMap;
21import java.util.List;
22import java.util.Map;
23
24import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask;
25import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance;
26import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration;
27import de.ugoe.cs.autoquest.tasktrees.treeifc.IIterationInstance;
28import de.ugoe.cs.autoquest.tasktrees.treeifc.IMarkingTemporalRelationship;
29import de.ugoe.cs.autoquest.tasktrees.treeifc.IOptional;
30import de.ugoe.cs.autoquest.tasktrees.treeifc.IOptionalInstance;
31import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelection;
32import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelectionInstance;
33import de.ugoe.cs.autoquest.tasktrees.treeifc.IStructuringTemporalRelationship;
34import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
35import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
36import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList;
37import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel;
38import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo;
39import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession;
40import de.ugoe.cs.autoquest.tasktrees.treeifc.TaskMetric;
41
42/**
43 * <p>
44 * this is the default implementation of the interface {@link ITaskModel}. It
45 * does not do anything fancy except implementing the interface. It also calculates on
46 * initialisations the measures for diverse metrics of the task belonging to the model
47 * </p>
48 *
49 * @author Patrick Harms
50 */
51class TaskModel implements ITaskModel {
52   
53    /**
54     * <p>
55     * default serial version UID
56     * </p>
57     */
58    private static final long serialVersionUID = 1L;
59   
60    /**
61     * <p>
62     * all metrics calculated by this type of task model
63     * </p>
64     */
65    private static final TaskMetric[] taskMetrics = new TaskMetric[]
66        { TaskMetric.COUNT,
67          TaskMetric.DEPTH,
68          TaskMetric.EVENT_COVERAGE,
69          TaskMetric.EVENT_COVERAGE_RATIO,
70          TaskMetric.EVENT_COVERAGE_QUANTILE };
71
72    /**
73     * <p>
74     * the user sessions belonging to the model
75     * </p>
76     */
77    private List<IUserSession> userSessions;
78
79    /**
80     * <p>
81     * index for effectively accessing the model and calculating statistics about it
82     * </p>
83     */
84    private transient TaskModelIndex index = null;
85   
86    /**
87     * <p>
88     * initializes the task model with the user sessions out of which the tasks are extracted
89     * </p>
90     *
91     * @param userSessions as described
92     */
93    TaskModel(List<IUserSession> userSessions) {
94        if ((userSessions == null) || (userSessions.size() == 0)) {
95            throw new IllegalArgumentException("user sessions must not be null");
96        }
97       
98        this.userSessions = userSessions;
99    }
100
101   
102    /* (non-Javadoc)
103     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel#getUserSessions()
104     */
105    @Override
106    public List<IUserSession> getUserSessions() {
107        ensureInitialized();
108        return Collections.unmodifiableList(userSessions);
109    }
110
111
112    /* (non-Javadoc)
113     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel#getTasks()
114     */
115    @Override
116    public Collection<ITask> getTasks() {
117        ensureInitialized();
118        return Collections.unmodifiableCollection(index.taskMap.keySet());
119    }
120
121
122    /* (non-Javadoc)
123     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel#getTaskInfo(ITask)
124     */
125    @Override
126    public ITaskInfo getTaskInfo(ITask task) {
127        ensureInitialized();
128        return index.taskMap.get(task);
129    }
130
131    /* (non-Javadoc)
132     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel#getAllMetrics()
133     */
134    @Override
135    public TaskMetric[] getAllMetrics() {
136        return taskMetrics;
137    }
138
139
140    /* (non-Javadoc)
141     * @see java.lang.Object#clone()
142     */
143    @Override
144    public TaskModel clone() {
145        return new TaskModel(userSessions);
146    }
147
148    /* (non-Javadoc)
149     * @see java.lang.Object#toString()
150     */
151    @Override
152    public String toString() {
153        return "Task Model (" + userSessions.size() + " sessions, " + index.taskMap.size() +
154            " tasks, hash " + System.identityHashCode(this) + ")";
155    }
156
157    /**
158     * <p>
159     * internal convenience method that initializes the internal index and calculates all measures
160     * for metrics available for the tasks
161     * </p>
162     */
163    private synchronized void ensureInitialized() {
164        if (index == null) {
165            index = new TaskModelIndex();
166           
167            for (IUserSession session : this.userSessions) {
168                for (ITaskInstance taskInstance : session) {
169                    index.handleTaskInstance(taskInstance);
170                }
171            }
172           
173            // count all events covered
174            int allEventsCovered = 0;
175            Collection<ITask> tasks = getTasks();
176            for (ITask task : tasks) {
177                if (task instanceof IEventTask) {
178                    allEventsCovered += task.getInstances().size();
179                }
180            }
181           
182            int[] eventCoverageRatios = new int[tasks.size()];
183            int i = 0;
184
185            // add some further measures
186            for (ITask task : tasks) {
187                TaskInfo info = index.taskMap.get(task);
188                info.addMeasure(TaskMetric.EVENT_COVERAGE_RATIO);
189               
190                int coveredEvents = info.getMeasureValue(TaskMetric.EVENT_COVERAGE);
191                int coverageRatio = 0;
192               
193                if (allEventsCovered > 0) {
194                    coverageRatio = (coveredEvents * 1000) / allEventsCovered;
195                }
196               
197                eventCoverageRatios[i++] = coverageRatio;
198                info.setCount(TaskMetric.EVENT_COVERAGE_RATIO, coverageRatio);
199            }
200           
201            Arrays.sort(eventCoverageRatios);
202           
203            // add some further measures
204            for (ITask task : tasks) {
205                TaskInfo info = index.taskMap.get(task);
206                info.addMeasure(TaskMetric.EVENT_COVERAGE_QUANTILE);
207                int quantile = Arrays.binarySearch
208                    (eventCoverageRatios, info.getMeasureValue(TaskMetric.EVENT_COVERAGE_RATIO));
209               
210                quantile = 1000 * quantile / eventCoverageRatios.length;
211               
212                info.setCount(TaskMetric.EVENT_COVERAGE_QUANTILE, quantile);
213            }
214           
215            //index.dumpToCSV(System.out);
216            /*try {
217                OutputStream stream = new FileOutputStream(new File("tasks.csv"));
218                index.dumpToCSV(new PrintStream(stream));
219                stream.close();
220            }
221            catch (FileNotFoundException e) {
222                e.printStackTrace();
223            }*/
224        }
225       
226    }
227
228    /**
229     * <p>
230     * the index of task infos used internally. The index is created once and while that filled
231     * with task infos for each observed task containing all measures for metrics belonging
232     * to the tasks.
233     * </p>
234     *
235     * @author Patrick Harms
236     */
237    private static class TaskModelIndex {
238
239        /**
240         * <p>
241         * the tasks contained in the user session belonging to the model as well as statistical
242         * infos about them
243         * </p>
244         */
245        private Map<ITask, TaskInfo> taskMap = new HashMap<ITask, TaskInfo>();
246
247        /**
248         * <p>
249         * called on initialization to fill the index with infos about the given task instance
250         * as well as to calculate the appropriate metrics
251         * </p>
252         */
253        private int[] handleTaskInstance(ITaskInstance taskInstance) {
254            int eventTaskInstancesCovered = 0;
255            int depth = 0;
256           
257            if (taskInstance instanceof ITaskInstanceList) {
258                for (ITaskInstance child : (ITaskInstanceList) taskInstance) {
259                    int[] measures = handleTaskInstance(child);
260                    eventTaskInstancesCovered += measures[0];
261                    depth = Math.max(depth, measures[1]);
262                }
263               
264                if ((((ITaskInstanceList) taskInstance).size() == 0) &&
265                    (taskInstance instanceof IIterationInstance))
266                {
267                    // ensure also empty task infos for unselected variants
268                    ensureTaskInfo(((IIteration) taskInstance.getTask()).getMarkedTask());
269                }
270            }
271            else if (taskInstance instanceof ISelectionInstance) {
272                ITaskInstance child = ((ISelectionInstance) taskInstance).getChild();
273                int[] measures = handleTaskInstance(child);
274                eventTaskInstancesCovered += measures[0];
275                depth = Math.max(depth, measures[1]);
276               
277                // ensure also empty task infos for unselected variants
278                for (ITask otherChildTask : ((ISelection) taskInstance.getTask()).getChildren()) {
279                    ensureTaskInfo(otherChildTask);
280                }
281            }
282            else if (taskInstance instanceof IOptionalInstance) {
283                ITaskInstance child = ((IOptionalInstance) taskInstance).getChild();
284                if (child != null) {
285                    int[] measures = handleTaskInstance(child);
286                    eventTaskInstancesCovered += measures[0];
287                    depth = Math.max(depth, measures[1]);
288                }
289                else {
290                    // ensure also empty task infos for unselected variants
291                    ensureTaskInfo(((IOptional) taskInstance.getTask()).getMarkedTask());
292                }
293            }
294            else if (taskInstance instanceof IEventTaskInstance) {
295                eventTaskInstancesCovered = 1;
296            }
297           
298            depth++;
299           
300            ensureTaskInfo(taskInstance.getTask(), eventTaskInstancesCovered, depth);
301           
302            return new int[] { eventTaskInstancesCovered, depth };
303        }
304       
305        /**
306         * <p>
307         * internal convenience method to build the task model during initialization
308         * </p>
309         */
310        private void ensureTaskInfo(ITask task) {
311            ensureTaskInfo(task, 0, 0);
312           
313            if (task instanceof IStructuringTemporalRelationship) {
314                for (ITask child : ((IStructuringTemporalRelationship) task).getChildren()) {
315                    ensureTaskInfo(child);
316                }
317            }
318            else if (task instanceof IMarkingTemporalRelationship) {
319                ensureTaskInfo(((IMarkingTemporalRelationship) task).getMarkedTask());
320            }
321       
322        }
323       
324        /**
325         * <p>
326         * internal convenience method to build the task model during initialization. Adds a new
327         * task info object to the map for the provided task and fills it with measures. If there
328         * are already some task infos for the task, the contained measures are updated according
329         * to the parameters.
330         * </p>
331         */
332        private void ensureTaskInfo(ITask task,
333                                    int   eventTaskInstancesCovered,
334                                    int   depth)
335        {
336            TaskInfo taskInfo = taskMap.get(task);
337
338            if (taskInfo == null) {
339                taskInfo = new TaskInfo(task);
340                taskInfo.addMeasure(TaskMetric.COUNT);
341                taskInfo.addMeasure(TaskMetric.EVENT_COVERAGE);
342                taskInfo.addMeasure(TaskMetric.DEPTH);
343                taskMap.put(task, taskInfo);
344               
345                taskInfo.setCount(TaskMetric.DEPTH, getDepth(task));
346            }
347
348            taskInfo.increaseCount(TaskMetric.COUNT, 1);
349            taskInfo.increaseCount(TaskMetric.EVENT_COVERAGE, eventTaskInstancesCovered);
350
351            taskInfo.setCount(TaskMetric.DEPTH, depth);
352        }
353
354        /**
355         * <p>
356         * internal convenience method to calculate the maximum depth of a task
357         * </p>
358         */
359        private int getDepth(ITask task) {
360            if (task instanceof IMarkingTemporalRelationship) {
361                return getDepth(((IMarkingTemporalRelationship) task).getMarkedTask()) + 1;
362            }
363            else if (task instanceof IStructuringTemporalRelationship) {
364                int maxDepth = 0;
365               
366                for (ITask child : ((IStructuringTemporalRelationship) task).getChildren()) {
367                    maxDepth = Math.max(maxDepth, getDepth(child));
368                }
369               
370                return maxDepth + 1;
371            }
372            else {
373                // event tasks
374                return 1;
375            }
376        }
377
378        /**
379         *
380         */
381        /*private void dumpToCSV(PrintStream out) {
382            out.println("taskid;depth;count;eventcoverage;eventcoverageratio");
383           
384            for (Map.Entry<ITask, TaskInfo> entry : taskMap.entrySet()) {
385                out.print(entry.getKey().getId());
386                out.print(';');
387                out.print(entry.getValue().getMeasureValue(TaskMetric.DEPTH));
388                out.print(';');
389                out.print(entry.getValue().getMeasureValue(TaskMetric.COUNT));
390                out.print(';');
391                out.print(entry.getValue().getMeasureValue(TaskMetric.EVENT_COVERAGE));
392                out.print(';');
393                out.print(entry.getValue().getMeasureValue(TaskMetric.EVENT_COVERAGE_RATIO));
394                out.println();
395            }
396        }*/
397
398    }
399
400
401}
Note: See TracBrowser for help on using the repository browser.