source: branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/SequenceForTaskDetectionRuleAlignment.java @ 1702

Last change on this file since 1702 was 1702, checked in by rkrimmel, 10 years ago
File size: 27.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.temporalrelation;
16
17import java.util.ArrayList;
18import java.util.Collections;
19import java.util.Comparator;
20import java.util.HashMap;
21import java.util.HashSet;
22import java.util.Iterator;
23import java.util.LinkedList;
24import java.util.List;
25import java.util.Map;
26import java.util.Set;
27import java.util.logging.Level;
28
29import de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.Match;
30import de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.MatchOccurence;
31import de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.NumberSequence;
32import de.ugoe.cs.autoquest.tasktrees.alignment.matrix.PairwiseAlignmentGenerator;
33import de.ugoe.cs.autoquest.tasktrees.alignment.matrix.PairwiseAlignmentStorage;
34import de.ugoe.cs.autoquest.tasktrees.alignment.matrix.ObjectDistanceSubstitionMatrix;
35import de.ugoe.cs.autoquest.tasktrees.taskequality.TaskEquality;
36import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration;
37import de.ugoe.cs.autoquest.tasktrees.treeifc.IIterationInstance;
38import de.ugoe.cs.autoquest.tasktrees.treeifc.IOptional;
39import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelection;
40import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelectionInstance;
41import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
42import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequenceInstance;
43import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
44import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskBuilder;
45import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskFactory;
46import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
47import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession;
48import de.ugoe.cs.autoquest.usageprofiles.SymbolMap;
49import de.ugoe.cs.util.StopWatch;
50import de.ugoe.cs.util.console.Console;
51
52/**
53 * <p>
54 * This class implements the major rule for creating task trees based on a set
55 * of recorded user sessions. For this, it first harmonizes all tasks. This
56 * eases later comparison. Then it searches the sessions for iterations and
57 * replaces them accordingly. Then it searches for sub sequences being the
58 * longest and occurring most often. For each found sub sequence, it replaces
59 * the occurrences by creating appropriate {@link ISequence}s. Afterwards, again
60 * searches for iterations and then again for sub sequences until no more
61 * replacements are done.
62 * </p>
63 * <p>
64 *
65 *
66 * @author Patrick Harms
67 */
68class SequenceForTaskDetectionRuleAlignment implements ISessionScopeRule {
69
70        private int iteration = 0;
71        /**
72         * <p>
73         * the task factory to be used for creating substructures for the temporal
74         * relationships identified during rul application
75         * </p>
76         */
77        private ITaskFactory taskFactory;
78        /**
79         * <p>
80         * the task builder to be used for creating substructures for the temporal
81         * relationships identified during rule application
82         * </p>
83         */
84        private ITaskBuilder taskBuilder;
85
86        /**
87         * <p>
88         * the task handling strategy to be used for comparing tasks for
89         * preparation, i.e., before the tasks are harmonized
90         * </p>
91         */
92        private TaskHandlingStrategy preparationTaskHandlingStrategy;
93
94        /**
95         * <p>
96         * instantiates the rule and initializes it with a task equality to be
97         * considered when comparing tasks as well as a task factory and builder to
98         * be used for creating task structures.
99         * </p>
100         *
101         * @param minimalTaskEquality
102         *            the task equality to be considered when comparing tasks
103         * @param taskFactory
104         *            the task factory to be used for creating substructures
105         * @param taskBuilder
106         *            the task builder to be used for creating substructures
107         */
108
109        SequenceForTaskDetectionRuleAlignment(TaskEquality minimalTaskEquality,
110                        ITaskFactory taskFactory, ITaskBuilder taskBuilder) {
111                this.taskFactory = taskFactory;
112                this.taskBuilder = taskBuilder;
113
114                this.preparationTaskHandlingStrategy = new TaskHandlingStrategy(
115                                minimalTaskEquality);
116
117        }
118
119        /*
120         * (non-Javadoc)
121         *
122         * @see java.lang.Object#toString()
123         */
124        @Override
125        public String toString() {
126                return "SequenceForTaskDetectionRuleAlignment";
127        }
128
129        /*
130         * (non-Javadoc)
131         *
132         * @see
133         * de.ugoe.cs.autoquest.tasktrees.temporalrelation.ISessionScopeRule#apply
134         * (java.util.List)
135         */
136        @Override
137        public RuleApplicationResult apply(List<IUserSession> sessions) {
138                RuleApplicationData appData = new RuleApplicationData(sessions);
139
140                harmonizeEventTaskInstancesModel(appData);
141                // Generate a substitution matrix between all occurring events.
142                Console.traceln(Level.INFO, "generating substitution matrix");
143                Console.traceln(Level.INFO,"Got " + appData.getUniqueTasks().size() + "tasks");
144                appData.getSubmat().generate(appData.getUniqueTasks());
145               
146               
147                Console.traceln(Level.INFO, "Starting main loop");
148                do {
149                        Console.traceln(Level.INFO, "Iteration Number: " + iteration);
150                        iteration++;
151                       
152                        appData.detectedAndReplacedTasks = false;
153                        appData.getStopWatch().start("whole loop");
154                        detectAndReplaceIterations(appData);
155                        appData.getStopWatch().start("task replacement");
156                        appData.updateSubstitutionMatrix();
157                        detectAndReplaceTasks(appData); //
158                        appData.getStopWatch().stop("task replacement");
159                        appData.getStopWatch().stop("whole loop");
160                        appData.getStopWatch().dumpStatistics(System.out);
161                        appData.getStopWatch().reset();
162
163                } while (appData.detectedAndReplacedTasks());
164
165                Console.println("created "
166                                + appData.getResult().getNewlyCreatedTasks().size()
167                                + " new tasks and "
168                                + appData.getResult().getNewlyCreatedTaskInstances().size()
169                                + " appropriate instances\n");
170
171                if ((appData.getResult().getNewlyCreatedTasks().size() > 0)
172                                || (appData.getResult().getNewlyCreatedTaskInstances().size() > 0)) {
173                        appData.getResult().setRuleApplicationStatus(
174                                        RuleApplicationStatus.FINISHED);
175                }
176
177                return appData.getResult();
178        }
179
180
181        private ArrayList<NumberSequence> createNumberSequences(
182                        RuleApplicationData appData) {
183                ArrayList<NumberSequence> result = new ArrayList<NumberSequence>();
184                for (int i = 0; i < appData.getSessions().size(); i++) {
185                        IUserSession session = appData.getSessions().get(i);
186                        NumberSequence templist = new NumberSequence(session.size());
187                        for (int j = 0; j < session.size(); j++) {
188                                ITaskInstance taskInstance = session.get(j);
189                                templist.getSequence()[j] = taskInstance.getTask().getId();
190                        }
191                        // Each NumberSequence is identified by its id, beginning to count
192                        // at zero
193                        templist.setId(i);
194                        result.add(templist);
195                }
196                return result;
197        }
198
199        /**
200         * <p>
201         * harmonizes the event task instances by unifying tasks. This is done, as
202         * initially the event tasks being equal with respect to the considered task
203         * equality are distinct objects. The comparison of these distinct objects
204         * is more time consuming than comparing the object references.
205         * </p>
206         *
207         * @param appData
208         *            the rule application data combining all data used for applying
209         *            this rule
210         * @return Returns the unique tasks symbol map
211         */
212        private void harmonizeEventTaskInstancesModel(RuleApplicationData appData) {
213                Console.traceln(Level.INFO,
214                                "harmonizing task model of event task instances");
215                appData.getStopWatch().start("harmonizing event tasks");
216                SymbolMap<ITaskInstance, ITask> uniqueTasks = preparationTaskHandlingStrategy
217                                .createSymbolMap();
218
219                TaskInstanceComparator comparator = preparationTaskHandlingStrategy
220                                .getTaskComparator();
221
222                int unifiedTasks = 0;
223                ITask task;
224                List<IUserSession> sessions = appData.getSessions();
225                for (int j = 0; j < sessions.size(); j++) {
226                        IUserSession session = sessions.get(j);
227
228                        for (int i = 0; i < session.size(); i++) {
229                                ITaskInstance taskInstance = session.get(i);
230                                task = uniqueTasks.getValue(taskInstance);
231
232                                if (task == null) {
233                                        uniqueTasks.addSymbol(taskInstance, taskInstance.getTask());
234                                        appData.getUniqueTasks().add(taskInstance.getTask());
235                                        appData.getNumber2Task().put(
236                                                        taskInstance.getTask().getId(),
237                                                        taskInstance.getTask());
238                                } else {
239                                        taskBuilder.setTask(taskInstance, task);
240                                        unifiedTasks++;
241                                }
242                        }
243                        comparator.clearBuffers();
244                }
245
246                appData.getStopWatch().stop("harmonizing event tasks");
247                Console.traceln(Level.INFO, "harmonized " + unifiedTasks
248                                + " task occurrences (still " + appData.getUniqueTasks().size()
249                                + " different tasks)");
250
251                appData.getStopWatch().dumpStatistics(System.out);
252                appData.getStopWatch().reset();
253        }
254
255        /**
256         * <p>
257         * searches for direct iterations of single tasks in all sequences and
258         * replaces them with {@link IIteration}s, respectively appropriate
259         * instances. Also all single occurrences of a task that is iterated
260         * somewhen are replaced with iterations to have again an efficient way for
261         * task comparisons.
262         * </p>
263         *
264         * @param appData
265         *            the rule application data combining all data used for applying
266         *            this rule
267         */
268        private void detectAndReplaceIterations(RuleApplicationData appData) {
269                Console.traceln(Level.FINE, "detecting iterations");
270                appData.getStopWatch().start("detecting iterations");
271
272                List<IUserSession> sessions = appData.getSessions();
273
274                Set<ITask> iteratedTasks = searchIteratedTasks(sessions);
275
276                if (iteratedTasks.size() > 0) {
277                        replaceIterationsOf(iteratedTasks, sessions, appData);
278                }
279
280                appData.getStopWatch().stop("detecting iterations");
281                Console.traceln(Level.INFO, "replaced " + iteratedTasks.size()
282                                + " iterated tasks");
283        }
284
285        /**
286         * <p>
287         * searches the provided sessions for task iterations. If a task is
288         * iterated, it is added to the returned set.
289         * </p>
290         *
291         * @param the
292         *            session to search for iterations in
293         *
294         * @return a set of tasks being iterated somewhere
295         */
296        private Set<ITask> searchIteratedTasks(List<IUserSession> sessions) {
297                Set<ITask> iteratedTasks = new HashSet<ITask>();
298                for (IUserSession session : sessions) {
299                        for (int i = 0; i < (session.size() - 1); i++) {
300                                // we prepared the task instances to refer to unique tasks, if
301                                // they are treated
302                                // as equal. Therefore, we just compare the identity of the
303                                // tasks of the task
304                                // instances
305                                if (session.get(i).getTask() == session.get(i + 1).getTask()) {
306                                        iteratedTasks.add(session.get(i).getTask());
307                                }
308                        }
309                }
310                return iteratedTasks;
311        }
312
313        /**
314         * <p>
315         * replaces all occurrences of all tasks provided in the set with iterations
316         * </p>
317         *
318         * @param iteratedTasks
319         *            the tasks to be replaced with iterations
320         * @param sessions
321         *            the sessions in which the tasks are to be replaced
322         * @param appData
323         *            the rule application data combining all data used for applying
324         *            this rule
325         */
326        private void replaceIterationsOf(Set<ITask> iteratedTasks,
327                        List<IUserSession> sessions, RuleApplicationData appData) {
328                Map<ITask, IIteration> iterations = new HashMap<ITask, IIteration>();
329                Map<IIteration, List<IIterationInstance>> iterationInstances = new HashMap<IIteration, List<IIterationInstance>>();
330
331                for (ITask iteratedTask : iteratedTasks) {
332
333                        IIteration iteration = taskFactory.createNewIteration();
334                        appData.newTaskCreated(iteration);
335                        iterations.put(iteratedTask, iteration);
336                        iterationInstances.put(iteration,
337                                        new LinkedList<IIterationInstance>());
338                }
339
340                IIterationInstance iterationInstance;
341
342                for (IUserSession session : sessions) {
343                        int index = 0;
344                        iterationInstance = null;
345
346                        while (index < session.size()) {
347                                // we prepared the task instances to refer to unique tasks, if
348                                // they are treated
349                                // as equal. Therefore, we just compare the identity of the
350                                // tasks of the task
351                                // instances
352                                ITask currentTask = session.get(index).getTask();
353                                IIteration iteration = iterations.get(currentTask);
354                                if (iteration != null) {
355                                        if ((iterationInstance == null)
356                                                        || (iterationInstance.getTask() != iteration)) {
357                                                iterationInstance = taskFactory
358                                                                .createNewTaskInstance(iteration);
359                                                iterationInstances.get(iteration)
360                                                                .add(iterationInstance);// TODO:: Don't create
361                                                                                                                // TaskInstances here,
362                                                                                                                // use a set of tasks
363                                                                                                                // instead
364                                                taskBuilder.addTaskInstance(session, index,
365                                                                iterationInstance);
366                                                index++;
367                                        }
368
369                                        taskBuilder.addChild(iterationInstance, session.get(index));
370                                        taskBuilder.removeTaskInstance(session, index);
371                                } else {
372                                        if (iterationInstance != null) {
373                                                iterationInstance = null;
374                                        }
375                                        index++;
376                                }
377                        }
378                }
379
380                for (Map.Entry<IIteration, List<IIterationInstance>> entry : iterationInstances
381                                .entrySet()) {
382                        harmonizeIterationInstancesModel(entry.getKey(), entry.getValue());
383                }
384        }
385
386        /**
387         * <p>
388         * TODO clarify why this is done
389         * </p>
390         */
391        private void harmonizeIterationInstancesModel(IIteration iteration,
392                        List<IIterationInstance> iterationInstances) {
393                List<ITask> iteratedTaskVariants = new LinkedList<ITask>();
394                TaskInstanceComparator comparator = preparationTaskHandlingStrategy
395                                .getTaskComparator();
396
397                // merge the lexically different variants of iterated task to a unique
398                // list
399                for (IIterationInstance iterationInstance : iterationInstances) {
400                        for (ITaskInstance executionVariant : iterationInstance) {
401                                ITask candidate = executionVariant.getTask();
402
403                                boolean found = false;
404                                for (ITask taskVariant : iteratedTaskVariants) {
405                                        if (comparator.areLexicallyEqual(taskVariant, candidate)) {
406                                                taskBuilder.setTask(executionVariant, taskVariant);
407                                                found = true;
408                                                break;
409                                        }
410                                }
411
412                                if (!found) {
413                                        iteratedTaskVariants.add(candidate);
414                                }
415                        }
416                }
417
418                // if there are more than one lexically different variant of iterated
419                // tasks, adapt the
420                // iteration model to be a selection of different variants. In this case
421                // also adapt
422                // the generated iteration instances to correctly contain selection
423                // instances. If there
424                // is only one variant of an iterated task, simply set this as the
425                // marked task of the
426                // iteration. In this case, the instances can be preserved as is
427                if (iteratedTaskVariants.size() > 1) {
428                        ISelection selection = taskFactory.createNewSelection();
429
430                        for (ITask variant : iteratedTaskVariants) {
431                                taskBuilder.addChild(selection, variant);
432                        }
433
434                        taskBuilder.setMarkedTask(iteration, selection);
435
436                        for (IIterationInstance instance : iterationInstances) {
437                                for (int i = 0; i < instance.size(); i++) {
438                                        ISelectionInstance selectionInstance = taskFactory
439                                                        .createNewTaskInstance(selection);
440                                        taskBuilder.setChild(selectionInstance, instance.get(i));
441                                        taskBuilder.setTaskInstance(instance, i, selectionInstance);
442                                }
443                        }
444                } else {
445                        taskBuilder.setMarkedTask(iteration, iteratedTaskVariants.get(0));
446                }
447        }
448
449        /**
450         * @param appData
451         * @param m
452         * @return
453         */
454        public ISequence matchAsSequence(RuleApplicationData appData, Match m) {       
455                ISequence sequence = taskFactory.createNewSequence();
456                appData.newTaskCreated(sequence);
457
458                int[] first = m.getFirstSequence().getSequence();
459                int[] second = m.getSecondSequence().getSequence();
460
461                // Both sequences of a match are equally long
462                for (int i = 0; i < m.getFirstSequence().size(); i++) {
463
464                        // Two gaps aligned to each other: Have not seen it happening so
465                        // far, just to handle it
466                        if (first[i] == -1 && second[i] == -1) {
467                                // Do nothing here.
468                        }
469                        // Both events are equal, we can simply add the task referring to
470                        // the number
471                        else if (first[i] == second[i]) {
472                                taskBuilder.addChild(sequence,
473                                                appData.getNumber2Task().get(first[i]));
474                        }
475                        // We have a gap in the first sequence, we need to add the task of
476                        // the second sequence as optional
477                        else if (first[i] == -1 && second[i] != -1) {
478                                IOptional optional = taskFactory.createNewOptional();
479                                appData.newTaskCreated(optional);
480                                taskBuilder.setMarkedTask(optional, appData.getNumber2Task()
481                                                .get(second[i]));
482                                taskBuilder.addChild(sequence, optional);
483                        }
484                        // We have a gap in the second sequence, we need to add the task of
485                        // the first sequence as optional
486                        else if (first[i] != -1 && second[i] == -1) {
487                                IOptional optional = taskFactory.createNewOptional();
488                                appData.newTaskCreated(optional);
489                                taskBuilder.setMarkedTask(optional, appData.getNumber2Task()
490                                                .get(first[i]));
491                                taskBuilder.addChild(sequence, optional);
492                        }
493                        // Both tasks are not equal, we need to insert a selection here.
494                        // Check if the next position is not a selection
495                        else if (i < first.length - 1) {
496
497                                if ((first[i] != second[i])
498                                                && ((first[i + 1] == second[i + 1]
499                                                                || first[i + 1] == -1 || second[i + 1] == -1))) {
500
501                                        ISelection selection = taskFactory.createNewSelection();
502                                        appData.newTaskCreated(selection);
503                                        taskBuilder.addChild(selection, appData.getNumber2Task()
504                                                        .get(first[i]));
505                                        taskBuilder.addChild(selection, appData.getNumber2Task()
506                                                        .get(second[i]));
507                                        taskBuilder.addChild(sequence, selection);
508                                } else {
509                                        boolean selectionfound = true;
510                                        ISelection selection = taskFactory.createNewSelection();
511                                        appData.newTaskCreated(selection);
512
513                                        ISequence subsequence1 = taskFactory.createNewSequence();
514                                        appData.newTaskCreated(subsequence1);
515
516                                        ISequence subsequence2 = taskFactory.createNewSequence();
517                                        appData.newTaskCreated(subsequence2);
518
519                                        taskBuilder.addChild(selection, subsequence1);
520                                        taskBuilder.addChild(selection, subsequence2);
521                                        taskBuilder.addChild(sequence,selection);
522                                        while (i < first.length - 1 && selectionfound) {
523                                                selectionfound = false;
524                                                taskBuilder.addChild(subsequence1, appData
525                                                                .getNumber2Task().get(first[i]));
526                                                taskBuilder.addChild(subsequence2, appData
527                                                                .getNumber2Task().get(second[i]));
528                                                if (first[i + 1] != second[i + 1] && first[i + 1] != -1
529                                                                && second[i + 1] != -1) {
530                                                        selectionfound = true;
531                                                }
532                                                else{
533                                                        continue;
534                                                }
535                                                i++;
536                                        }
537                                        if(i==first.length-1 && selectionfound) {
538                                                taskBuilder.addChild(subsequence1, appData
539                                                                .getNumber2Task().get(first[i]));
540                                                taskBuilder.addChild(subsequence2, appData
541                                                                .getNumber2Task().get(second[i]));
542                                        }
543                                }
544                        }
545                        else {
546                                if ((first[i] != second[i])) {
547
548                                        ISelection selection = taskFactory.createNewSelection();
549                                        appData.newTaskCreated(selection);
550                                        taskBuilder.addChild(selection, appData.getNumber2Task()
551                                                        .get(first[i]));
552                                        taskBuilder.addChild(selection, appData.getNumber2Task()
553                                                        .get(second[i]));
554                                        taskBuilder.addChild(sequence, selection);
555                                }
556                        }
557
558                }
559                return sequence;
560        }
561
562        /**
563         *
564         * @param appData
565         *            the rule application data combining all data used for applying
566         *            this rule
567         */
568        private void detectAndReplaceTasks(RuleApplicationData appData) {
569                Console.traceln(Level.FINE, "detecting and replacing tasks");
570                appData.getStopWatch().start("detecting tasks");
571
572                // Create NumberSequences
573                appData.setNumberSequences(this.createNumberSequences(appData));
574               
575                // Generate pairwise alignments
576                Console.traceln(Level.INFO, "generating pairwise alignments");
577                LinkedList<Match> matchseqs = new LinkedList<Match>();
578                PairwiseAlignmentStorage alignments = PairwiseAlignmentGenerator
579                                .generate(appData.getNumberSequences(), appData.getSubmat(), 9);
580
581                // Retrieve all matches reached a specific threshold
582                Console.traceln(Level.INFO, "retrieving significant sequence pieces");
583                for (int i = 0; i < appData.getNumberSequences().size(); i++) {
584                        for (int j = 0; j < appData.getNumberSequences().size(); j++) {
585                                if (i != j) {
586                                        matchseqs.addAll(alignments.get(i, j).getMatches());
587                                }
588                        }
589                }
590
591
592                Console.traceln(Level.INFO, "searching for patterns occuring most");
593
594                // search each match in every other sequence
595                for (Iterator<Match> it = matchseqs.iterator(); it.hasNext();) {
596                        Match pattern = it.next();
597
598                        // Skip sequences with more 0 events (scrolls) than other events.
599                        // Both of the pattern sequences are equally long, so the zero
600                        // counts just need to be smaller than the length of one sequence
601                        if (pattern.getFirstSequence().eventCount(0)
602                                        + pattern.getSecondSequence().eventCount(0) + 1 > pattern
603                                        .getFirstSequence().size())
604                                continue;
605
606                        for (int j = 0; j < appData.getNumberSequences().size(); j++) {
607                                LinkedList<Integer> startpositions = appData
608                                                .getNumberSequences().get(j).containsPattern(pattern);
609                                if (startpositions.size() > 0) {
610                                        for (Iterator<Integer> jt = startpositions.iterator(); jt
611                                                        .hasNext();) {
612                                                int start = jt.next();
613                                                pattern.addOccurence(new MatchOccurence(start, start
614                                                                + pattern.size(), j));
615                                        }
616
617                                }
618                        }
619                }
620
621                Console.traceln(Level.INFO, "sorting results");
622                // Sort results to get the most occurring results
623                Comparator<Match> comparator = new Comparator<Match>() {
624                        public int compare(Match m1, Match m2) {
625                                return m2.occurenceCount() - m1.occurenceCount();
626
627                        }
628                };
629                Collections.sort(matchseqs, comparator);
630                appData.getStopWatch().stop("detecting tasks");
631
632                appData.getStopWatch().start("replacing tasks");
633                HashMap<Integer, List<MatchOccurence>> replacedOccurences = new HashMap<Integer, List<MatchOccurence>>();
634                // Replace matches in the sessions
635                for (int i = 0; i < matchseqs.size(); i++) {
636                        // Every pattern consists of 2 sequences, therefore the minimum
637                        // occurrences here is 2.
638                        // We just need the sequences also occurring in other sequences as
639                        // well
640                        if (matchseqs.get(i).occurenceCount() > 2) {
641
642                                appData.detectedAndReplacedTasks = true;
643                                ISequence task = matchAsSequence(appData, matchseqs.get(i));
644                                invalidOccurence: for (Iterator<MatchOccurence> it = matchseqs
645                                                .get(i).getOccurences().iterator(); it.hasNext();) {
646                                        MatchOccurence oc = it.next();
647                                       
648                                        /*
649                                        if (iteration > 1) {
650                                         
651                                        System.out.println("Trying to replace sequence: ");
652                                        matchseqs.get(i).getFirstSequence().printSequence();
653                                        matchseqs.get(i).getSecondSequence().printSequence();
654                                        System.out.println(" in session number: "
655                                                        + (oc.getSequenceId() + 1) + " at position "
656                                                        + (oc.getStartindex()) + "-" + oc.getEndindex());
657                                        System.out.println();
658
659                                        System.out.println("Printing session: ");
660                                        for (int j = 0; j < appData.getSessions()
661                                                        .get(oc.getSequenceId()).size(); j++) {
662                                                System.out.println(j
663                                                                + ": "
664                                                                + appData.getSessions().get(oc.getSequenceId())
665                                                                                .get(j));
666                                        }
667                                        }*/
668                                       
669                                        // Check if nothing has been replaced in the sequence we
670                                        // want to replace
671                                        if (replacedOccurences.get(oc.getSequenceId()) == null) {
672                                                replacedOccurences.put(oc.getSequenceId(),
673                                                                new LinkedList<MatchOccurence>());
674                                        } else {
675                                                // check if we have any replaced occurence with indexes
676                                                // smaller than ours. If so, we need to adjust our start
677                                                // and endpoints
678                                                // of the replacement.
679                                                // Also do a check if we have replaced this specific
680                                                // MatchOccurence in this sequence already. Jump to the
681                                                // next occurence if this is the case.
682                                                // This is no more neccessary once the matches are
683                                                // harmonized.
684                                                for (Iterator<MatchOccurence> jt = replacedOccurences
685                                                                .get(oc.getSequenceId()).iterator(); jt
686                                                                .hasNext();) {
687                                                        MatchOccurence tmpOC = jt.next();
688
689                                                        if (oc.getStartindex() >= tmpOC.getStartindex()
690                                                                        && oc.getStartindex() <= tmpOC
691                                                                                        .getEndindex()) {
692                                                                continue invalidOccurence;
693                                                        }
694                                                        if (oc.getEndindex() >= tmpOC.getStartindex()) {
695                                                                continue invalidOccurence;
696
697                                                        } else if (oc.getStartindex() > tmpOC.getEndindex()) {
698                                                                int diff = tmpOC.getEndindex()
699                                                                                - tmpOC.getStartindex();
700                                                                // Just to be sure.
701                                                                if (diff > 0) {
702                                                                        oc.setStartindex(oc.getStartindex() - diff
703                                                                                        + 1);
704                                                                        oc.setEndindex(oc.getEndindex() - diff + 1);
705                                                                } else {
706                                                                        Console.traceln(Level.WARNING,
707                                                                                        "End index of a Match before start. This should never happen");
708                                                                }
709                                                        }
710                                                }
711                                        }
712                                        ISequenceInstance sequenceInstances = RuleUtils
713                                                        .createNewSubSequenceInRange(appData.getSessions()
714                                                                        .get(oc.getSequenceId()), oc
715                                                                        .getStartindex(), oc.getEndindex(), task,
716                                                                        taskFactory, taskBuilder);
717                                        // Adjust the length of the match regarding to the length of
718                                        // instance. (OptionalInstances may be shorter)
719                                        oc.setEndindex(oc.getStartindex()
720                                                        + sequenceInstances.size()
721                                                        - RuleUtils.missedOptionals);
722                                        replacedOccurences.get(oc.getSequenceId()).add(oc);
723                                }
724                        }
725                }
726
727                alignments = null;
728                matchseqs = null;
729                appData.getStopWatch().stop("replacing tasks");
730        }
731
732        /**
733     *
734     */
735        private static class RuleApplicationData {
736
737                private HashMap<Integer, ITask> number2task;
738
739                // TODO: We Actually just need number2task here, this structure can be removed in the future.
740                private HashSet<ITask> uniqueTasks;
741               
742                ObjectDistanceSubstitionMatrix submat;
743
744       
745                private ArrayList<NumberSequence> numberseqs;
746
747                private LinkedList<ITask> newTasks;
748               
749                /**
750         *
751         */
752                private List<IUserSession> sessions;
753
754                /**
755         *
756         */
757                private boolean detectedAndReplacedTasks;
758
759                /**
760         *
761         */
762                private RuleApplicationResult result;
763
764                /**
765         *
766         */
767                private StopWatch stopWatch;
768
769                /**
770         *
771         */
772                private RuleApplicationData(List<IUserSession> sessions) {
773                        this.sessions = sessions;
774                        numberseqs = new ArrayList<NumberSequence>();
775                        uniqueTasks = new HashSet<ITask>();
776                        number2task = new HashMap<Integer, ITask>();
777                        stopWatch = new StopWatch();
778                        result = new RuleApplicationResult();
779                        submat= new ObjectDistanceSubstitionMatrix(6,-3,false);
780                        newTasks = new LinkedList<ITask>();
781                }
782
783                private ObjectDistanceSubstitionMatrix getSubmat() {
784                        return submat;
785                }
786               
787                private void resetNewlyCreatedTasks() {
788                        uniqueTasks.addAll(newTasks);
789                        newTasks.clear();
790                }
791               
792                private void newTaskCreated(ITask task) {
793                        number2task.put(task.getId(), task);
794                        newTasks.add(task);
795                }
796
797                /**
798                 * @return the UserSessions as List.
799                 */
800                private List<IUserSession> getSessions() {
801                        return sessions;
802                }
803
804                private HashSet<ITask> getUniqueTasks() {
805                        return uniqueTasks;
806                }
807
808                private void setNumberSequences(ArrayList<NumberSequence> numberseqs) {
809                        this.numberseqs = numberseqs;
810                }
811
812                private ArrayList<NumberSequence> getNumberSequences() {
813                        return numberseqs;
814                }
815
816                private void updateSubstitutionMatrix() {
817                        submat.update(getNewTasks());
818                        resetNewlyCreatedTasks();
819                }
820
821               
822                /**
823         *
824         */
825                private boolean detectedAndReplacedTasks() {
826                        return detectedAndReplacedTasks;
827                }
828
829                /**
830                 * @return the result
831                 */
832                private RuleApplicationResult getResult() {
833                        return result;
834                }
835
836                public LinkedList<ITask> getNewTasks() {
837                        return newTasks;
838                }
839               
840                /**
841                 * @return the stopWatch
842                 */
843                private StopWatch getStopWatch() {
844                        return stopWatch;
845                }
846
847                private HashMap<Integer, ITask> getNumber2Task() {
848                        return number2task;
849                }
850
851        }
852
853}
Note: See TracBrowser for help on using the repository browser.