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

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