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
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
[1494]17import java.util.Arrays;
[1146]18import java.util.Collection;
19import java.util.Collections;
[439]20import java.util.HashMap;
[1146]21import java.util.List;
[439]22import java.util.Map;
23
[1423]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;
[1146]34import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
35import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
[1287]36import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList;
[1146]37import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel;
38import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo;
39import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession;
[1423]40import de.ugoe.cs.autoquest.tasktrees.treeifc.TaskMetric;
[439]41
42/**
[1216]43 * <p>
44 * this is the default implementation of the interface {@link ITaskModel}. It
[1423]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
[1216]47 * </p>
[439]48 *
[1216]49 * @author Patrick Harms
[439]50 */
[1146]51class TaskModel implements ITaskModel {
[557]52   
[1216]53    /**
54     * <p>
55     * default serial version UID
56     * </p>
57     */
[1146]58    private static final long serialVersionUID = 1L;
[1423]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,
[1494]69          TaskMetric.EVENT_COVERAGE_RATIO,
70          TaskMetric.EVENT_COVERAGE_QUANTILE };
[439]71
[1216]72    /**
73     * <p>
74     * the user sessions belonging to the model
75     * </p>
76     */
[1146]77    private List<IUserSession> userSessions;
[439]78
[1216]79    /**
80     * <p>
[1423]81     * index for effectively accessing the model and calculating statistics about it
[1216]82     * </p>
83     */
[1423]84    private transient TaskModelIndex index = null;
85   
[557]86    /**
[1216]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
[557]92     */
[1146]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;
[439]99    }
100
[1287]101   
[1146]102    /* (non-Javadoc)
103     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel#getUserSessions()
[557]104     */
105    @Override
[1146]106    public List<IUserSession> getUserSessions() {
[1423]107        ensureInitialized();
[1146]108        return Collections.unmodifiableList(userSessions);
[439]109    }
[557]110
[1146]111
112    /* (non-Javadoc)
113     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel#getTasks()
[557]114     */
115    @Override
[1146]116    public Collection<ITask> getTasks() {
[1423]117        ensureInitialized();
118        return Collections.unmodifiableCollection(index.taskMap.keySet());
[439]119    }
[557]120
[1146]121
122    /* (non-Javadoc)
[1216]123     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel#getTaskInfo(ITask)
[1146]124     */
125    @Override
126    public ITaskInfo getTaskInfo(ITask task) {
[1423]127        ensureInitialized();
128        return index.taskMap.get(task);
[1146]129    }
130
[1216]131    /* (non-Javadoc)
[1423]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)
[1216]141     * @see java.lang.Object#clone()
142     */
143    @Override
144    public TaskModel clone() {
145        return new TaskModel(userSessions);
146    }
147
[1891]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
[557]157    /**
[1216]158     * <p>
[1423]159     * internal convenience method that initializes the internal index and calculates all measures
160     * for metrics available for the tasks
[1287]161     * </p>
162     */
[1423]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) {
[1891]169                    index.handleTaskInstance(taskInstance);
[1423]170                }
[1287]171            }
[1423]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           
[1494]182            int[] eventCoverageRatios = new int[tasks.size()];
183            int i = 0;
184
[1423]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);
[1494]191                int coverageRatio = 0;
[1423]192               
193                if (allEventsCovered > 0) {
[1494]194                    coverageRatio = (coveredEvents * 1000) / allEventsCovered;
[1423]195                }
[1494]196               
197                eventCoverageRatios[i++] = coverageRatio;
[1891]198                info.setCount(TaskMetric.EVENT_COVERAGE_RATIO, coverageRatio);
[1423]199            }
200           
[1494]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               
[1891]212                info.setCount(TaskMetric.EVENT_COVERAGE_QUANTILE, quantile);
[1494]213            }
214           
[1423]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            }*/
[1287]224        }
[1423]225       
[1287]226    }
227
228    /**
229     * <p>
[1423]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.
[1216]233     * </p>
[1423]234     *
235     * @author Patrick Harms
[557]236     */
[1423]237    private static class TaskModelIndex {
[557]238
[1423]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         */
[1891]253        private int[] handleTaskInstance(ITaskInstance taskInstance) {
[1423]254            int eventTaskInstancesCovered = 0;
255            int depth = 0;
256           
257            if (taskInstance instanceof ITaskInstanceList) {
258                for (ITaskInstance child : (ITaskInstanceList) taskInstance) {
[1891]259                    int[] measures = handleTaskInstance(child);
[1423]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
[1891]268                    ensureTaskInfo(((IIteration) taskInstance.getTask()).getMarkedTask());
[1423]269                }
270            }
271            else if (taskInstance instanceof ISelectionInstance) {
272                ITaskInstance child = ((ISelectionInstance) taskInstance).getChild();
[1891]273                int[] measures = handleTaskInstance(child);
[1423]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()) {
[1891]279                    ensureTaskInfo(otherChildTask);
[1423]280                }
281            }
282            else if (taskInstance instanceof IOptionalInstance) {
283                ITaskInstance child = ((IOptionalInstance) taskInstance).getChild();
284                if (child != null) {
[1891]285                    int[] measures = handleTaskInstance(child);
[1423]286                    eventTaskInstancesCovered += measures[0];
287                    depth = Math.max(depth, measures[1]);
288                }
289                else {
290                    // ensure also empty task infos for unselected variants
[1891]291                    ensureTaskInfo(((IOptional) taskInstance.getTask()).getMarkedTask());
[1423]292                }
293            }
294            else if (taskInstance instanceof IEventTaskInstance) {
295                eventTaskInstancesCovered = 1;
296            }
297           
298            depth++;
299           
[1891]300            ensureTaskInfo(taskInstance.getTask(), eventTaskInstancesCovered, depth);
[1423]301           
302            return new int[] { eventTaskInstancesCovered, depth };
[557]303        }
[1423]304       
305        /**
306         * <p>
307         * internal convenience method to build the task model during initialization
308         * </p>
309         */
[1891]310        private void ensureTaskInfo(ITask task) {
311            ensureTaskInfo(task, 0, 0);
[1423]312           
313            if (task instanceof IStructuringTemporalRelationship) {
314                for (ITask child : ((IStructuringTemporalRelationship) task).getChildren()) {
[1891]315                    ensureTaskInfo(child);
[1423]316                }
317            }
318            else if (task instanceof IMarkingTemporalRelationship) {
[1891]319                ensureTaskInfo(((IMarkingTemporalRelationship) task).getMarkedTask());
[1423]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);
[557]337
[1423]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               
[1891]345                taskInfo.setCount(TaskMetric.DEPTH, getDepth(task));
[1423]346            }
[1287]347
[1891]348            taskInfo.increaseCount(TaskMetric.COUNT, 1);
349            taskInfo.increaseCount(TaskMetric.EVENT_COVERAGE, eventTaskInstancesCovered);
[1423]350
[1891]351            taskInfo.setCount(TaskMetric.DEPTH, depth);
[1423]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;
[1146]362            }
[1423]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            }
[557]376        }
[1423]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            }
[1287]396        }*/
[1423]397
[439]398    }
399
[1423]400
[439]401}
Note: See TracBrowser for help on using the repository browser.