source: branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/TaskModel.java @ 1733

Last change on this file since 1733 was 1733, checked in by rkrimmel, 10 years ago

Used Eclipse code cleanup

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