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

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

HarmonizeIterationinstancemodel? DOES need to be called after iteration detection....

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