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
RevLine 
[1113]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
[922]15package de.ugoe.cs.autoquest.tasktrees.treeimpl;
[439]16
[1146]17import java.util.Collection;
18import java.util.Collections;
[439]19import java.util.HashMap;
[1146]20import java.util.List;
[439]21import java.util.Map;
22
[1423]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;
[1146]33import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
34import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
[1287]35import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList;
[1146]36import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel;
37import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo;
38import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession;
[1423]39import de.ugoe.cs.autoquest.tasktrees.treeifc.TaskMetric;
[439]40
41/**
[1216]42 * <p>
43 * this is the default implementation of the interface {@link ITaskModel}. It
[1423]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
[1216]46 * </p>
[439]47 *
[1216]48 * @author Patrick Harms
[439]49 */
[1146]50class TaskModel implements ITaskModel {
[557]51   
[1216]52    /**
53     * <p>
54     * default serial version UID
55     * </p>
56     */
[1146]57    private static final long serialVersionUID = 1L;
[1423]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 };
[439]69
[1216]70    /**
71     * <p>
72     * the user sessions belonging to the model
73     * </p>
74     */
[1146]75    private List<IUserSession> userSessions;
[439]76
[1216]77    /**
78     * <p>
[1423]79     * index for effectively accessing the model and calculating statistics about it
[1216]80     * </p>
81     */
[1423]82    private transient TaskModelIndex index = null;
83   
[557]84    /**
[1216]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
[557]90     */
[1146]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;
[439]97    }
98
[1287]99   
[1146]100    /* (non-Javadoc)
101     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel#getUserSessions()
[557]102     */
103    @Override
[1146]104    public List<IUserSession> getUserSessions() {
[1423]105        ensureInitialized();
[1146]106        return Collections.unmodifiableList(userSessions);
[439]107    }
[557]108
[1146]109
110    /* (non-Javadoc)
111     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel#getTasks()
[557]112     */
113    @Override
[1146]114    public Collection<ITask> getTasks() {
[1423]115        ensureInitialized();
116        return Collections.unmodifiableCollection(index.taskMap.keySet());
[439]117    }
[557]118
[1146]119
120    /* (non-Javadoc)
[1216]121     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel#getTaskInfo(ITask)
[1146]122     */
123    @Override
124    public ITaskInfo getTaskInfo(ITask task) {
[1423]125        ensureInitialized();
126        return index.taskMap.get(task);
[1146]127    }
128
[1216]129    /* (non-Javadoc)
[1423]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)
[1216]139     * @see java.lang.Object#clone()
140     */
141    @Override
142    public TaskModel clone() {
143        return new TaskModel(userSessions);
144    }
145
[557]146    /**
[1216]147     * <p>
[1423]148     * internal convenience method that initializes the internal index and calculates all measures
149     * for metrics available for the tasks
[1287]150     * </p>
151     */
[1423]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                }
[1287]160            }
[1423]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            }*/
[1287]193        }
[1423]194       
[1287]195    }
196
197    /**
198     * <p>
[1423]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.
[1216]202     * </p>
[1423]203     *
204     * @author Patrick Harms
[557]205     */
[1423]206    private static class TaskModelIndex {
[557]207
[1423]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 };
[557]272        }
[1423]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);
[557]307
[1423]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            }
[1287]317
[1423]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;
[1146]332            }
[1423]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            }
[557]346        }
[1423]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            }
[1287]366        }*/
[1423]367
[439]368    }
369
[1423]370
[439]371}
Note: See TracBrowser for help on using the repository browser.