Ignore:
Timestamp:
06/04/14 16:42:02 (10 years ago)
Author:
rkrimmel
Message:

Further adjustments of the smithWatermanRepeated algorithm

Location:
branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/MatrixEntry.java

    r1558 r1559  
    44        private float score; 
    55        private MatrixEntry previous; 
     6        private int xvalue; 
     7        private int yvalue; 
    68         
    79        public MatrixEntry(float score, MatrixEntry previous)   { 
     
    2527                this.previous = previous; 
    2628        } 
     29 
     30        public int getXvalue() { 
     31                return xvalue; 
     32        } 
     33 
     34        public void setXvalue(int xvalue) { 
     35                this.xvalue = xvalue; 
     36        } 
     37 
     38        public int getYvalue() { 
     39                return yvalue; 
     40        } 
     41 
     42        public void setYvalue(int yvalue) { 
     43                this.yvalue = yvalue; 
     44        } 
    2745} 
  • branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/NumberSequence.java

    r1558 r1559  
    2929        {        
    3030                for (int i = 0; i < sequence.length; i++) { 
    31                         System.out.format("%4d", sequence[i]); 
     31                        System.out.format("%5d", sequence[i]); 
    3232                } 
    3333                System.out.println(); 
  • branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/SmithWatermanRepeated.java

    r1558 r1559  
    5151                matrix = new MatrixEntry[length1+2][length2+1]; 
    5252                 
    53                 for (int i = 0; i <= length1; i++) { 
     53                for (int i = 0; i <= length1+1; i++) { 
    5454                        for(int j = 0; j< length2; j++) { 
    5555                                matrix[i][j] = new MatrixEntry(); 
     
    7171         * @return Cost of substitution of the character in str1 by the one in str2 
    7272         */ 
    73         private float similarity(int i, int j) { 
    74                 if (i == 0 || j == 0) { 
    75                         // it's a gap  
    76                         return submat.getGapPenalty(); 
    77                 } 
    78                 // System.out.println("Diag letters: " + input1[i-1] + " " + 
    79                 // input2[j-1]); 
    80                 // return (input1[i - 1] == input2[j - 1]) ? MATCH_SCORE : 
    81                 // MISMATCH_SCORE; 
     73        private float similarity(int i, int j) {  
    8274                return submat.getDistance(input1[i - 1], input2[j - 1]); 
    8375        } 
    8476 
    8577        /** 
    86          * Build the score matrix using dynamic programming. Note: The indel scores 
    87          * must be negative. Otherwise, the part handling the first row and column 
    88          * has to be modified. 
     78         * Build the score matrix using dynamic programming. 
    8979         */ 
    9080        private void buildMatrix() { 
     
    9383                } 
    9484                 
    95  
    96                 // base case 
     85                // it's a gap 
    9786                matrix[0][0].setScore(0); 
    9887                matrix[0][0].setPrevious(null); // starting point 
     
    10796                 
    10897                 
    109                 for (int i = 1; i <= length1; i++) { 
     98                for (int i = 1; i <= length1 + 1; i++) { 
    11099                 
    111100                        // Formula for first row: 
     
    113102                         
    114103                        float firstRowLeftScore = matrix[i-1][0].getScore(); 
    115                         float tempMax = matrix[i-1][1].getScore(); 
    116                          
    117                         //position of the maximal score of the previous row 
    118                         int maxRowIndex = 1; 
    119                          
    120                         for(int j = 2; j < length2;j++) { 
    121                                 if(matrix[i-1][j].getScore() > tempMax) { 
    122                                         tempMax = matrix[i-1][j].getScore(); 
    123                                         maxRowIndex = j; 
    124                                 } 
    125                         } 
    126                          
     104                        //for sequences of length 1 
     105                        float tempMax; 
     106                        int maxRowIndex; 
     107                        if(length2 == 1) { 
     108                                tempMax = matrix[i-1][0].getScore(); 
     109                                maxRowIndex = 0; 
     110                        } else { 
     111                                tempMax = matrix[i-1][1].getScore(); 
     112                                maxRowIndex = 1; 
     113                                //position of the maximal score of the previous row 
     114                                 
     115                                for(int j = 2; j < length2;j++) { 
     116                                        if(matrix[i-1][j].getScore() > tempMax) { 
     117                                                tempMax = matrix[i-1][j].getScore(); 
     118                                                maxRowIndex = j; 
     119                                        } 
     120                                } 
     121 
     122                        } 
     123                         
     124                                         
    127125                        tempMax -= scoreThreshold; 
    128126                        matrix[i][0].setScore(Math.max(firstRowLeftScore, tempMax)); 
     127                        if(tempMax ==matrix[i][0].getScore()){ 
     128                                matrix[i][0].setPrevious(matrix[i-1][maxRowIndex]); 
     129                        } 
     130                         
     131                        if(firstRowLeftScore == matrix[i][0].getScore()) { 
     132                                matrix[i][0].setPrevious(matrix[i-1][0]); 
     133                        } 
     134                         
     135                        //The last additional score is not related to a character in the input sequence, it's the total score. Therefore we don't need to save something for it 
     136                        if(i<length1+1)  
     137                        { 
     138                                matrix[i][0].setXvalue(input1[i-1]); 
     139                                matrix[i][0].setYvalue(-2); 
     140                                 
     141                        } 
     142                        else {  
     143                        //End after we calculated final score 
     144                                return; 
     145                        } 
    129146                         
    130147                         
    131148                        for (int j = 1; j < length2; j++) { 
    132149                                float diagScore = matrix[i - 1][j - 1].getScore() + similarity(i, j); 
    133                                 float upScore = matrix[i][j - 1].getScore() + similarity(0, j); 
    134                                 float leftScore = matrix[i - 1][j].getScore() + similarity(i, 0); 
     150                                float upScore = matrix[i][j - 1].getScore() + submat.getGapPenalty(); 
     151                                float leftScore = matrix[i - 1][j].getScore() + submat.getGapPenalty(); 
    135152 
    136153                                matrix[i][j].setScore(Math.max(diagScore,Math.max(upScore, Math.max(leftScore,matrix[i][0].getScore())))); 
     
    138155                                // find the directions that give the maximum scores. 
    139156                                // Multiple directions are ignored TODO 
     157                                //True if we had a match 
    140158                                if (diagScore == matrix[i][j].getScore()) { 
    141159                                        matrix[i][j].setPrevious(matrix[i-1][j-1]); 
    142                                 } 
     160                                        matrix[i][j].setXvalue(input1[i-1]); 
     161                                        matrix[i][j].setYvalue(input2[j-1]); 
     162                                } 
     163                                //true if we took an event from sequence x and not from y 
    143164                                if (leftScore == matrix[i][j].getScore()) { 
     165                                        matrix[i][j].setXvalue(input1[i-1]); 
     166                                        matrix[i][j].setYvalue(-1); 
    144167                                        matrix[i][j].setPrevious(matrix[i-1][j]); 
    145168                                } 
     169                                //true if we took an event from sequence y and not from x 
    146170                                if (upScore == matrix[i][j].getScore()) { 
     171                                        matrix[i][j].setXvalue(-1); 
     172                                        matrix[i][j].setYvalue(input2[j-1]); 
    147173                                        matrix[i][j].setPrevious(matrix[i][j-1]); 
    148174                                } 
     175                                //true if we ended a matching region  
    149176                                if (matrix[i][0].getScore() == matrix[i][j].getScore()) { 
    150                                         matrix[i][j].setPrevious(matrix[i-1][maxRowIndex]); 
    151                                 } 
    152                         } 
     177                                        matrix[i][j].setPrevious(matrix[i][0]); 
     178                                        matrix[i][j].setXvalue(input1[i-1]); 
     179                                        matrix[i][j].setYvalue(-2); 
     180                                } 
     181                        } 
     182                         
     183                        //Set the complete score cell 
     184                         
    153185                } 
    154186        } 
     
    175207         * Get the alignment score between the two input strings. 
    176208         */ 
    177         public double getAlignmentScore() { 
    178                 return getMaxScore(); 
     209        public float getAlignmentScore() { 
     210                return matrix[length1+1][0].getScore(); 
    179211        } 
    180212 
     
    188220         */ 
    189221        private int[] traceback(int i, int j) { 
    190  
     222                 
     223                         
    191224                return null; 
    192225        } 
     226         
     227        public void traceback() { 
     228                MatrixEntry tmp = matrix[length1+1][0]; 
     229                String aligned1 = ""; 
     230                String aligned2 = ""; 
     231                int count = 0; 
     232                do 
     233                { 
     234                        String append1=""; 
     235                        String append2=""; 
     236                                         
     237                        if(tmp.getXvalue() == -1) { 
     238                                append1 = "  ___"; 
     239                        } 
     240                        else if(tmp.getXvalue() == -2) { 
     241                                append1 = "  ..."; 
     242                        } 
     243                        else { 
     244                                append1 = String.format("%5d", tmp.getXvalue()); 
     245                        } 
     246 
     247                        if(tmp.getYvalue() == -1) { 
     248                                append2 = "  ___"; 
     249                        } 
     250                        else if(tmp.getYvalue() == -2) { 
     251                                append2 = "  ..."; 
     252                        } 
     253                        else { 
     254                                append2 = String.format("%5d", tmp.getYvalue()); 
     255                        } 
     256                        if(count != 0) 
     257                        { 
     258                                aligned1 = append1 + aligned1; 
     259                                aligned2 = append2 + aligned2; 
     260                        } 
     261                         
     262                        tmp = tmp.getPrevious(); 
     263                        count++; 
     264                         
     265                } while(tmp != null); 
     266                System.out.println(aligned1); 
     267                System.out.println(aligned2); 
     268        } 
     269         
    193270 
    194271         
     
    207284                                System.out.print("      "); 
    208285                        } 
    209                         for (int i = 0; i <= length1; i++) { 
    210                                 System.out.format("%4.1f ",matrix[i][j].getScore()); 
    211                         } 
     286                        for (int i = 0; i <= length1 + 1; i++) { 
     287                                if((i<length1+1) || (i==length1+1 && j==0))     { 
     288                                        System.out.format("%4.1f ",matrix[i][j].getScore()); 
     289                                } 
     290                                 
     291                        }                        
    212292                        System.out.println(); 
    213293                } 
  • branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/substitution/ObjectDistanceSubstitionMatrix.java

    r1558 r1559  
    3535                idmapping = new HashMap<Integer, Integer>(); 
    3636                matrix = new TriangleMatrix(uniqueTasks.size()+1); 
    37                 gapPenalty = -10; 
     37                gapPenalty = -5; 
    3838                 
    3939        } 
  • branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/SequenceForTaskDetectionRuleAlignment.java

    r1558 r1559  
    5151/** 
    5252 * <p> 
    53  * This class implements the major rule for creating task trees based on a set of recorded 
    54  * user sessions. For this, it first harmonizes all tasks. This eases later comparison. Then it 
    55  * searches the sessions for iterations and replaces them accordingly. Then it searches for sub 
    56  * sequences being the longest and occurring most often. For each found sub sequence, it replaces 
    57  * the occurrences by creating appropriate {@link ISequence}s. Afterwards, again searches for 
    58  * iterations and then again for sub sequences until no more replacements are done. 
     53 * This class implements the major rule for creating task trees based on a set 
     54 * of recorded user sessions. For this, it first harmonizes all tasks. This 
     55 * eases later comparison. Then it searches the sessions for iterations and 
     56 * replaces them accordingly. Then it searches for sub sequences being the 
     57 * longest and occurring most often. For each found sub sequence, it replaces 
     58 * the occurrences by creating appropriate {@link ISequence}s. Afterwards, again 
     59 * searches for iterations and then again for sub sequences until no more 
     60 * replacements are done. 
    5961 * </p> 
    6062 * <p> 
    61  * For determining the longest sequence occurring most often, the implementation uses a  
    62  * {@link Trie}. The depth of the tree is initially 3. If the algorithm has a longest sequence 
    63  * occurring most often whose length is equal to the depth of the trie, it recalculates the trie 
    64  * with an increased depth.  
     63 * For determining the longest sequence occurring most often, the implementation 
     64 * uses a {@link Trie}. The depth of the tree is initially 3. If the algorithm 
     65 * has a longest sequence occurring most often whose length is equal to the 
     66 * depth of the trie, it recalculates the trie with an increased depth. 
    6567 * </p> 
    6668 *  
     
    6870 */ 
    6971class SequenceForTaskDetectionRuleAlignment implements ISessionScopeRule { 
    70      
    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 relationships 
    81      * 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 preparation, i.e., before 
    89      * the tasks are harmonized 
    90      * </p> 
    91      */ 
    92     private TaskHandlingStrategy preparationTaskHandlingStrategy; 
    93      
    94     /** 
    95      * <p> 
    96      * the task handling strategy to be used for comparing tasks during iteration detection an trie 
    97      * generation, i.e., after the tasks are harmonized  
    98      * </p> 
    99      */ 
    100     private TaskHandlingStrategy identityTaskHandlingStrategy;; 
    101      
    102      
    103     private ArrayList<NumberSequence> numberseqs; 
    104      
    105     /** 
    106      * <p> 
    107      * instantiates the rule and initializes it with a task equality to be considered when 
    108      * comparing tasks as well as a task factory and builder to be used for creating task 
    109      * structures. 
    110      * </p> 
    111      *  
    112      * @param minimalTaskEquality the task equality to be considered when comparing tasks 
    113      * @param taskFactory         the task factory to be used for creating substructures 
    114      * @param taskBuilder         the task builder to be used for creating substructures 
    115      */ 
    116      
    117     
    118     SequenceForTaskDetectionRuleAlignment(TaskEquality minimalTaskEquality, 
    119                                  ITaskFactory taskFactory, 
    120                                  ITaskBuilder taskBuilder) 
    121     { 
    122         this.taskFactory = taskFactory; 
    123         this.taskBuilder = taskBuilder; 
    124          
    125         this.preparationTaskHandlingStrategy = new TaskHandlingStrategy(minimalTaskEquality); 
    126         this.identityTaskHandlingStrategy = new TaskHandlingStrategy(TaskEquality.IDENTICAL); 
    127         numberseqs = new ArrayList<NumberSequence>(); 
    128          
    129     } 
    130  
    131     /* (non-Javadoc) 
    132      * @see java.lang.Object#toString() 
    133      */ 
    134     @Override 
    135     public String toString() { 
    136         return "SequenceForTaskDetectionRuleAlignment"; 
    137     } 
    138  
    139     /* (non-Javadoc) 
    140      * @see de.ugoe.cs.autoquest.tasktrees.temporalrelation.ISessionScopeRule#apply(java.util.List) 
    141      */ 
    142     @Override 
    143     public RuleApplicationResult apply(List<IUserSession> sessions) { 
    144         RuleApplicationData appData = new RuleApplicationData(sessions); 
    145          
    146          
    147          
    148         // this is the real rule application. Loop while something is replaced. 
    149         SymbolMap<ITaskInstance, ITask> uniqueTasks = harmonizeEventTaskInstancesModel(appData); 
    150         ObjectDistanceSubstitionMatrix submat = new ObjectDistanceSubstitionMatrix(uniqueTasks,20); 
    151         submat.generate(); 
    152        
    153         
    154          
    155         System.out.print("Sequence 1: "); 
    156         NumberSequence ns1 = numberseqs.get(7); 
    157         NumberSequence ns2 = numberseqs.get(8); 
    158         ns1.printSequence(); 
    159         System.out.print("Sequence 2: "); 
    160         ns2.printSequence(); 
    161         //SmithWatermanRepeated sw = new SmithWatermanRepeated(numberseqs.get(20).getSequence(), numberseqs.get(24).getSequence(), submat,10); 
    162         SmithWatermanRepeated sw = new SmithWatermanRepeated(ns1.getSequence(), ns2.getSequence(), submat,15); 
    163         System.out.println("Max Scrore: " + sw.getMaxScore()); 
    164          
    165         sw.printDPMatrix(); 
    166     
    167          
    168          
    169  
    170         do { 
    171             System.out.println(); 
    172             FengDoolittle fd = new FengDoolittle(); 
    173              
    174              
    175             //appData.getStopWatch().start("whole loop"); 
    176             //detectAndReplaceIterations(appData); 
    177  
    178             //appData.getStopWatch().start("task replacement"); 
    179             //detectAndReplaceTasks(appData); 
    180             //appData.getStopWatch().stop("task replacement"); 
    181             //appData.getStopWatch().stop("whole loop"); 
    182              
    183              
    184             //appData.getStopWatch().dumpStatistics(System.out); 
    185             //appData.getStopWatch().reset(); 
    186              
    187         } 
    188         while (appData.detectedAndReplacedTasks()); 
    189          
    190         Console.println 
    191             ("created " + appData.getResult().getNewlyCreatedTasks().size() + 
    192              " new tasks and " + appData.getResult().getNewlyCreatedTaskInstances().size() + 
    193              " appropriate instances\n"); 
    194          
    195         if ((appData.getResult().getNewlyCreatedTasks().size() > 0) || 
    196             (appData.getResult().getNewlyCreatedTaskInstances().size() > 0)) 
    197         { 
    198             appData.getResult().setRuleApplicationStatus(RuleApplicationStatus.FINISHED); 
    199         } 
    200          
    201         return appData.getResult(); 
    202     } 
    203  
    204     /** 
    205      * <p> 
    206      * harmonizes the event task instances by unifying tasks. This is done, as initially the 
    207      * event tasks being equal with respect to the considered task equality are distinct objects. 
    208      * The comparison of these distinct objects is more time consuming than comparing the object 
    209      * references. 
    210      * </p> 
    211      * 
    212      * @param appData the rule application data combining all data used for applying this rule 
    213      * @return Returns the unique tasks symbol map 
    214      */ 
    215     private SymbolMap<ITaskInstance, ITask> harmonizeEventTaskInstancesModel(RuleApplicationData appData) { 
    216         Console.traceln(Level.INFO, "harmonizing task model of event task instances"); 
    217         appData.getStopWatch().start("harmonizing event tasks"); 
    218  
    219         SymbolMap<ITaskInstance, ITask> uniqueTasks = 
    220             preparationTaskHandlingStrategy.createSymbolMap(); 
    221         TaskInstanceComparator comparator = preparationTaskHandlingStrategy.getTaskComparator(); 
    222          
    223         int unifiedTasks = 0; 
    224         ITask task; 
    225         List<IUserSession> sessions = appData.getSessions(); 
    226         int sessionNo = 0; 
    227         numberseqs = new ArrayList<NumberSequence>(); 
    228         for (IUserSession session : sessions) { 
    229             Console.traceln(Level.FINE, "handling " + (++sessionNo) + ". " + session); 
    230                 NumberSequence templist = new NumberSequence(session.size()) ; 
    231              
    232             for (int i = 0; i < session.size(); i++) { 
    233                 ITaskInstance taskInstance = session.get(i);  
    234                 task = uniqueTasks.getValue(taskInstance); 
    235                  
    236                 if (task == null) { 
    237                     uniqueTasks.addSymbol(taskInstance, taskInstance.getTask()); 
    238                     templist.getSequence()[i]=taskInstance.getTask().getId(); 
    239                 } 
    240                 else { 
    241                     taskBuilder.setTask(taskInstance, task); 
    242                         templist.getSequence()[i]=task.getId(); 
    243                     unifiedTasks++; 
    244                 } 
    245             } 
    246             numberseqs.add(templist); 
    247             comparator.clearBuffers(); 
    248         } 
    249          
    250         appData.getStopWatch().stop("harmonizing event tasks"); 
    251         Console.traceln(Level.INFO, "harmonized " + unifiedTasks + " task occurrences (still " + 
    252                         uniqueTasks.size() + " different tasks)"); 
    253  
    254         appData.getStopWatch().dumpStatistics(System.out); 
    255         appData.getStopWatch().reset(); 
     72 
     73        /** 
     74         * <p> 
     75         * the task factory to be used for creating substructures for the temporal 
     76         * relationships identified during rul application 
     77         * </p> 
     78         */ 
     79        private ITaskFactory taskFactory; 
     80        /** 
     81         * <p> 
     82         * the task builder to be used for creating substructures for the temporal 
     83         * relationships identified during rule application 
     84         * </p> 
     85         */ 
     86        private ITaskBuilder taskBuilder; 
     87 
     88        /** 
     89         * <p> 
     90         * the task handling strategy to be used for comparing tasks for 
     91         * preparation, i.e., before the tasks are harmonized 
     92         * </p> 
     93         */ 
     94        private TaskHandlingStrategy preparationTaskHandlingStrategy; 
     95 
     96        /** 
     97         * <p> 
     98         * the task handling strategy to be used for comparing tasks during 
     99         * iteration detection an trie generation, i.e., after the tasks are 
     100         * harmonized 
     101         * </p> 
     102         */ 
     103        private TaskHandlingStrategy identityTaskHandlingStrategy;; 
     104 
     105        private ArrayList<NumberSequence> numberseqs; 
     106 
     107        /** 
     108         * <p> 
     109         * instantiates the rule and initializes it with a task equality to be 
     110         * considered when comparing tasks as well as a task factory and builder to 
     111         * be used for creating task structures. 
     112         * </p> 
     113         *  
     114         * @param minimalTaskEquality 
     115         *            the task equality to be considered when comparing tasks 
     116         * @param taskFactory 
     117         *            the task factory to be used for creating substructures 
     118         * @param taskBuilder 
     119         *            the task builder to be used for creating substructures 
     120         */ 
     121 
     122        SequenceForTaskDetectionRuleAlignment(TaskEquality minimalTaskEquality, 
     123                        ITaskFactory taskFactory, ITaskBuilder taskBuilder) { 
     124                this.taskFactory = taskFactory; 
     125                this.taskBuilder = taskBuilder; 
     126 
     127                this.preparationTaskHandlingStrategy = new TaskHandlingStrategy( 
     128                                minimalTaskEquality); 
     129                this.identityTaskHandlingStrategy = new TaskHandlingStrategy( 
     130                                TaskEquality.IDENTICAL); 
     131                numberseqs = new ArrayList<NumberSequence>(); 
     132 
     133        } 
     134 
     135        /* 
     136         * (non-Javadoc) 
     137         *  
     138         * @see java.lang.Object#toString() 
     139         */ 
     140        @Override 
     141        public String toString() { 
     142                return "SequenceForTaskDetectionRuleAlignment"; 
     143        } 
     144 
     145        /* 
     146         * (non-Javadoc) 
     147         *  
     148         * @see 
     149         * de.ugoe.cs.autoquest.tasktrees.temporalrelation.ISessionScopeRule#apply 
     150         * (java.util.List) 
     151         */ 
     152        @Override 
     153        public RuleApplicationResult apply(List<IUserSession> sessions) { 
     154                RuleApplicationData appData = new RuleApplicationData(sessions); 
     155 
     156                // this is the real rule application. Loop while something is replaced. 
     157                SymbolMap<ITaskInstance, ITask> uniqueTasks = harmonizeEventTaskInstancesModel(appData); 
     158                ObjectDistanceSubstitionMatrix submat = new ObjectDistanceSubstitionMatrix( 
     159                                uniqueTasks, 5); 
     160                submat.generate(); 
     161 
     162                // good tests: 7/8 20/24 
     163                for (int i = 0; i < numberseqs.size(); i++) { 
     164                        for (int j = 0; j < numberseqs.size(); j++) { 
     165                                 
     166                                NumberSequence ns1 = numberseqs.get(i); 
     167                                NumberSequence ns2 = numberseqs.get(j); 
     168                                 
     169                                 
     170                                 
     171                                SmithWatermanRepeated sw = new SmithWatermanRepeated( 
     172                                                ns1.getSequence(), ns2.getSequence(), submat, 10); 
     173                                 
     174                                if(sw.getAlignmentScore() > 0) 
     175                                {    
     176                                        System.out.println("================================================="); 
     177                                        System.out.println("| Sequence " + String.format("%3d", i) +" Sequence " + String.format("%3d", j)  + "                     |"); 
     178                                        System.out.println("================================================="); 
     179                                        //System.out.print("Sequence " + i + ": "); 
     180                                        //ns1.printSequence(); 
     181                                        //System.out.print("Sequence " + j + ": "); 
     182                                        //ns2.printSequence(); 
     183                                        //System.out.println("Max Scrore: " + sw.getMaxScore()); 
     184                                        System.out.println("Alignment Score: " + sw.getAlignmentScore()); 
     185                                        //sw.printDPMatrix(); 
     186                                        sw.traceback(); 
     187                                        System.out.println(); 
     188                                        System.out.println(); 
     189                                } 
     190                        } 
     191                } 
     192 
     193                do { 
     194                        System.out.println(); 
     195                        FengDoolittle fd = new FengDoolittle(); 
     196 
     197                        // appData.getStopWatch().start("whole loop"); 
     198                        // detectAndReplaceIterations(appData); 
     199 
     200                        // appData.getStopWatch().start("task replacement"); 
     201                        // detectAndReplaceTasks(appData); 
     202                        // appData.getStopWatch().stop("task replacement"); 
     203                        // appData.getStopWatch().stop("whole loop"); 
     204 
     205                        // appData.getStopWatch().dumpStatistics(System.out); 
     206                        // appData.getStopWatch().reset(); 
     207 
     208                } while (appData.detectedAndReplacedTasks()); 
     209 
     210                Console.println("created " 
     211                                + appData.getResult().getNewlyCreatedTasks().size() 
     212                                + " new tasks and " 
     213                                + appData.getResult().getNewlyCreatedTaskInstances().size() 
     214                                + " appropriate instances\n"); 
     215 
     216                if ((appData.getResult().getNewlyCreatedTasks().size() > 0) 
     217                                || (appData.getResult().getNewlyCreatedTaskInstances().size() > 0)) { 
     218                        appData.getResult().setRuleApplicationStatus( 
     219                                        RuleApplicationStatus.FINISHED); 
     220                } 
     221 
     222                return appData.getResult(); 
     223        } 
     224 
     225        /** 
     226         * <p> 
     227         * harmonizes the event task instances by unifying tasks. This is done, as 
     228         * initially the event tasks being equal with respect to the considered task 
     229         * equality are distinct objects. The comparison of these distinct objects 
     230         * is more time consuming than comparing the object references. 
     231         * </p> 
     232         *  
     233         * @param appData 
     234         *            the rule application data combining all data used for applying 
     235         *            this rule 
     236         * @return Returns the unique tasks symbol map 
     237         */ 
     238        private SymbolMap<ITaskInstance, ITask> harmonizeEventTaskInstancesModel( 
     239                        RuleApplicationData appData) { 
     240                Console.traceln(Level.INFO, 
     241                                "harmonizing task model of event task instances"); 
     242                appData.getStopWatch().start("harmonizing event tasks"); 
     243 
     244                SymbolMap<ITaskInstance, ITask> uniqueTasks = preparationTaskHandlingStrategy 
     245                                .createSymbolMap(); 
     246                TaskInstanceComparator comparator = preparationTaskHandlingStrategy 
     247                                .getTaskComparator(); 
     248 
     249                int unifiedTasks = 0; 
     250                ITask task; 
     251                List<IUserSession> sessions = appData.getSessions(); 
     252                int sessionNo = 0; 
     253                numberseqs = new ArrayList<NumberSequence>(); 
     254                for (IUserSession session : sessions) { 
     255                        Console.traceln(Level.FINE, "handling " + (++sessionNo) + ". " 
     256                                        + session); 
     257                        NumberSequence templist = new NumberSequence(session.size()); 
     258 
     259                        for (int i = 0; i < session.size(); i++) { 
     260                                ITaskInstance taskInstance = session.get(i); 
     261                                task = uniqueTasks.getValue(taskInstance); 
     262 
     263                                if (task == null) { 
     264                                        uniqueTasks.addSymbol(taskInstance, taskInstance.getTask()); 
     265                                        templist.getSequence()[i] = taskInstance.getTask().getId(); 
     266                                } else { 
     267                                        taskBuilder.setTask(taskInstance, task); 
     268                                        templist.getSequence()[i] = task.getId(); 
     269                                        unifiedTasks++; 
     270                                } 
     271                        } 
     272                        numberseqs.add(templist); 
     273                        comparator.clearBuffers(); 
     274                } 
     275 
     276                appData.getStopWatch().stop("harmonizing event tasks"); 
     277                Console.traceln(Level.INFO, "harmonized " + unifiedTasks 
     278                                + " task occurrences (still " + uniqueTasks.size() 
     279                                + " different tasks)"); 
     280 
     281                appData.getStopWatch().dumpStatistics(System.out); 
     282                appData.getStopWatch().reset(); 
    256283                return uniqueTasks; 
    257     } 
    258  
    259     /** 
    260      * <p> 
    261      * searches for direct iterations of single tasks in all sequences and replaces them with 
    262      * {@link IIteration}s, respectively appropriate instances. Also all single occurrences of 
    263      * a task that is iterated somewhen are replaced with iterations to have again an efficient 
    264      * way for task comparisons.  
    265      * </p> 
    266      *  
    267      * @param appData the rule application data combining all data used for applying this rule 
    268      */ 
    269     private void detectAndReplaceIterations(RuleApplicationData appData) { 
    270         Console.traceln(Level.FINE, "detecting iterations"); 
    271         appData.getStopWatch().start("detecting iterations"); 
    272          
    273         List<IUserSession> sessions = appData.getSessions(); 
    274          
    275         Set<ITask> iteratedTasks = searchIteratedTasks(sessions); 
    276          
    277         if (iteratedTasks.size() > 0) { 
    278             replaceIterationsOf(iteratedTasks, sessions, appData); 
    279         } 
    280          
    281         appData.getStopWatch().stop("detecting iterations"); 
    282         Console.traceln(Level.INFO, "replaced " + iteratedTasks.size() + " iterated tasks"); 
    283     } 
    284  
    285     /** 
    286      * <p> 
    287      * searches the provided sessions for task iterations. If a task is iterated, it is added 
    288      * to the returned set. 
    289      * </p> 
    290      *  
    291      * @param the session to search for iterations in 
    292      *  
    293      * @return a set of tasks being iterated somewhere 
    294      */ 
    295     private Set<ITask> searchIteratedTasks(List<IUserSession> sessions) { 
    296         Set<ITask> iteratedTasks = new HashSet<ITask>(); 
    297         for (IUserSession session : sessions) { 
    298             for (int i = 0; i < (session.size() - 1); i++) { 
    299                 // we prepared the task instances to refer to unique tasks, if they are treated 
    300                 // as equal. Therefore, we just compare the identity of the tasks of the task 
    301                 // instances 
    302                 if (session.get(i).getTask() == session.get(i + 1).getTask()) { 
    303                     iteratedTasks.add(session.get(i).getTask()); 
    304                 } 
    305             } 
    306         } 
    307          
    308         return iteratedTasks; 
    309     } 
    310  
    311     /** 
    312      * <p> 
    313      * replaces all occurrences of all tasks provided in the set with iterations 
    314      * </p> 
    315      * 
    316      * @param iteratedTasks the tasks to be replaced with iterations 
    317      * @param sessions      the sessions in which the tasks are to be replaced 
    318      * @param appData       the rule application data combining all data used for applying this rule 
    319      */ 
    320     private void replaceIterationsOf(Set<ITask>          iteratedTasks, 
    321                                      List<IUserSession>  sessions, 
    322                                      RuleApplicationData appData) 
    323     { 
    324         Map<ITask, IIteration> iterations = new HashMap<ITask, IIteration>(); 
    325         Map<IIteration, List<IIterationInstance>> iterationInstances = 
    326                 new HashMap<IIteration, List<IIterationInstance>>(); 
    327              
    328         for (ITask iteratedTask : iteratedTasks) { 
    329             IIteration iteration = taskFactory.createNewIteration(); 
    330             iterations.put(iteratedTask, iteration); 
    331             iterationInstances.put(iteration, new LinkedList<IIterationInstance>()); 
    332         } 
    333          
    334         IIterationInstance iterationInstance; 
    335          
    336         for (IUserSession session : sessions) { 
    337             int index = 0; 
    338             iterationInstance = null; 
    339  
    340             while (index < session.size()) { 
    341                 // we prepared the task instances to refer to unique tasks, if they are treated 
    342                 // as equal. Therefore, we just compare the identity of the 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) || (iterationInstance.getTask() != iteration)) 
    348                     { 
    349                         iterationInstance = taskFactory.createNewTaskInstance(iteration); 
    350                         iterationInstances.get(iteration).add(iterationInstance); 
    351                         taskBuilder.addTaskInstance(session, index, iterationInstance); 
    352                         index++; 
    353                     } 
    354                      
    355                     taskBuilder.addChild(iterationInstance, session.get(index)); 
    356                     taskBuilder.removeTaskInstance(session, index); 
    357                 } 
    358                 else { 
    359                     if (iterationInstance != null) { 
    360                         iterationInstance = null; 
    361                     } 
    362                     index++; 
    363                 } 
    364             } 
    365         } 
    366          
    367         for (Map.Entry<IIteration, List<IIterationInstance>> entry : iterationInstances.entrySet()) 
    368         { 
    369             harmonizeIterationInstancesModel(entry.getKey(), entry.getValue()); 
    370         } 
    371     } 
    372  
    373     /** 
    374      * <p> 
    375      * TODO clarify why this is done 
    376      * </p> 
    377      */ 
    378     private void harmonizeIterationInstancesModel(IIteration               iteration, 
    379                                                   List<IIterationInstance> iterationInstances) 
    380     { 
    381         List<ITask> iteratedTaskVariants = new LinkedList<ITask>(); 
    382         TaskInstanceComparator comparator = preparationTaskHandlingStrategy.getTaskComparator(); 
    383          
    384         // merge the lexically different variants of iterated task to a unique list  
    385         for (IIterationInstance iterationInstance : iterationInstances) { 
    386             for (ITaskInstance executionVariant : iterationInstance) { 
    387                 ITask candidate = executionVariant.getTask(); 
    388              
    389                 boolean found = false; 
    390                 for (ITask taskVariant : iteratedTaskVariants) { 
    391                     if (comparator.areLexicallyEqual(taskVariant, candidate)) { 
    392                         taskBuilder.setTask(executionVariant, taskVariant); 
    393                         found = true; 
    394                         break; 
    395                     } 
    396                 } 
    397                  
    398                 if (!found) { 
    399                     iteratedTaskVariants.add(candidate); 
    400                 } 
    401             } 
    402         } 
    403          
    404         // if there are more than one lexically different variant of iterated tasks, adapt the 
    405         // iteration model to be a selection of different variants. In this case also adapt 
    406         // the generated iteration instances to correctly contain selection instances. If there 
    407         // is only one variant of an iterated task, simply set this as the marked task of the 
    408         // iteration. In this case, the instances can be preserved as is 
    409         if (iteratedTaskVariants.size() > 1) { 
    410             ISelection selection = taskFactory.createNewSelection(); 
    411              
    412             for (ITask variant : iteratedTaskVariants) { 
    413                 taskBuilder.addChild(selection, variant); 
    414             } 
    415              
    416             taskBuilder.setMarkedTask(iteration, selection); 
    417              
    418             for (IIterationInstance instance : iterationInstances) { 
    419                 for (int i = 0; i < instance.size(); i++) { 
    420                     ISelectionInstance selectionInstance = 
    421                         taskFactory.createNewTaskInstance(selection); 
    422                     taskBuilder.setChild(selectionInstance, instance.get(i)); 
    423                     taskBuilder.setTaskInstance(instance, i, selectionInstance); 
    424                 } 
    425             } 
    426         } 
    427         else { 
    428             taskBuilder.setMarkedTask(iteration, iteratedTaskVariants.get(0)); 
    429         } 
    430     } 
    431  
    432     /** 
    433      * TODO go on commenting 
    434      * @param appData the rule application data combining all data used for applying this rule 
    435      */ 
    436     private void detectAndReplaceTasks(RuleApplicationData appData) { 
    437         Console.traceln(Level.FINE, "detecting and replacing tasks"); 
    438         appData.getStopWatch().start("detecting tasks"); 
    439          
    440         getSequencesOccuringMostOften(appData); 
    441  
    442         appData.getStopWatch().stop("detecting tasks"); 
    443         appData.getStopWatch().start("replacing tasks"); 
    444          
    445         replaceSequencesOccurringMostOften(appData); 
    446          
    447         appData.getStopWatch().stop("replacing tasks"); 
    448         Console.traceln(Level.INFO, "detected and replaced " + appData.getLastFoundTasks().size() + 
    449                         " tasks occuring " + appData.getLastFoundTasks().getOccurrenceCount() + 
    450                         " times"); 
    451     } 
    452  
    453     /** 
    454      * @param appData the rule application data combining all data used for applying this rule 
    455      */ 
    456     private void getSequencesOccuringMostOften(RuleApplicationData appData) { 
    457         Console.traceln(Level.FINE, "determining most prominent tasks"); 
    458  
    459         Tasks tasks; 
    460         boolean createNewTrie = (appData.getLastTrie() == null) || 
    461             appData.detectedAndReplacedTasks(); // tree has changed 
    462          
    463         do { 
    464             if (createNewTrie) { 
    465                 createNewTrie(appData); 
    466             } 
    467              
    468             MaxCountAndLongestTasksFinder finder = new MaxCountAndLongestTasksFinder(); 
    469             appData.getLastTrie().process(finder); 
    470          
    471             tasks = finder.getFoundTasks(); 
    472              
    473             createNewTrie = false; 
    474              
    475             for (List<ITaskInstance> task : tasks) { 
    476                 if (task.size() >= appData.getTrainedSequenceLength()) { 
    477                     // Trie must be recreated with a longer sequence length to be sure that 
    478                     // the found sequences occurring most often are found in their whole length 
    479                     appData.setTrainedSequenceLength(appData.getTrainedSequenceLength() + 1); 
    480                     createNewTrie = true; 
    481                     break; 
    482                 } 
    483             } 
    484         } 
    485         while (createNewTrie); 
    486          
    487         // create a normal trie for comparison 
    488         /*System.out.println("creating test trie for comparison"); 
    489          
    490         appData.getStopWatch().start("testtrie"); 
    491         Trie<ITaskInstance> trie = new Trie<ITaskInstance>(identityTaskComparator); 
    492          
    493         for (IUserSession session : appData.getSessions()) { 
    494             trie.train(session.getExecutedTasks(), appData.getTrainedSequenceLength()); 
    495         } 
    496          
    497         appData.getStopWatch().stop("testtrie"); 
    498          
    499         MaxCountAndLongestTasksFinder finder = new MaxCountAndLongestTasksFinder(); 
    500         trie.process(finder); 
    501  
    502         boolean allTasksEqual = finder.getFoundTasks().size() == tasks.size(); 
    503          
    504         allTasksEqual &= finder.getFoundTasks().occurrenceCount == tasks.occurrenceCount; 
    505          
    506         for (List<ITaskInstance> task1 : finder.getFoundTasks()) { 
    507             boolean foundTask = false; 
    508             for (List<ITaskInstance> task2 : tasks) { 
    509                 boolean tasksEqual = false; 
    510                 if (task1.size() == task2.size()) { 
    511                     tasksEqual = true; 
    512                     for (int i = 0; i < task1.size(); i++) { 
    513                         if (!identityTaskComparator.equals(task1.get(i).getTask(), task2.get(i).getTask())) 
    514                         { 
    515                             tasksEqual = false; 
    516                         } 
    517                     } 
    518                 } 
    519                  
    520                 if (tasksEqual) { 
    521                     foundTask = true; 
    522                     break; 
    523                 } 
    524             } 
    525              
    526             if (!foundTask) { 
    527                 System.out.println("different is " + task1); 
    528                 allTasksEqual = false; 
    529                 break; 
    530             } 
    531         } 
    532          
    533         if (!allTasksEqual) { 
    534             System.out.println(finder.getFoundTasks()); 
    535             System.out.println(tasks); 
    536              
    537             throw new IllegalArgumentException("both tries calculated different subsequences"); 
    538         } 
    539          
    540         /*TrieStatisticsDumper dumper = new TrieStatisticsDumper(); 
    541         appData.getLastTrie().process(dumper); 
    542         dumper.dumpCounters();*/ 
    543          
    544         appData.setLastFoundTasks(tasks); 
    545  
    546         Console.traceln(Level.FINE, "found " + appData.getLastFoundTasks().size() + " tasks " + 
    547                         "occurring " + appData.getLastFoundTasks().getOccurrenceCount() + " times"); 
    548     } 
    549  
    550     /** 
    551      * @param appData the rule application data combining all data used for applying this rule 
    552      */ 
    553     private void createNewTrie(RuleApplicationData appData) { 
    554         Console.traceln(Level.FINER, "training trie with a maximum sequence length of " + 
    555                         appData.getTrainedSequenceLength()); 
    556  
    557         appData.getStopWatch().start("training trie"); 
    558          
    559         // we prepared the task instances to refer to unique tasks, if they are treated 
    560         // as equal. Therefore, we just compare the identity of the tasks of the task 
    561         // instances 
    562         appData.setLastTrie(new TaskInstanceTrie(identityTaskHandlingStrategy)); 
    563      
    564         appData.getLastTrie().trainSessions 
    565             (appData.getSessions(), appData.getTrainedSequenceLength()); 
    566          
    567         appData.getStopWatch().stop("training trie"); 
    568     } 
    569  
    570     /** 
    571      * @param appData the rule application data combining all data used for applying this rule 
    572      */ 
    573     private void replaceSequencesOccurringMostOften(RuleApplicationData appData) { 
    574         appData.detectedAndReplacedTasks(false); 
    575  
    576         if ((appData.getLastFoundTasks().size() > 0) && 
    577             (appData.getLastFoundTasks().getOccurrenceCount() > 1)) 
    578         { 
    579             Console.traceln(Level.FINER, "replacing tasks occurrences"); 
    580  
    581             for (List<ITaskInstance> task : appData.getLastFoundTasks()) { 
    582                 ISequence sequence = taskFactory.createNewSequence(); 
    583                  
    584                 Console.traceln(Level.FINEST, "replacing " + sequence.getId() + ": " + task); 
    585  
    586                 List<ISequenceInstance> sequenceInstances = 
    587                     replaceTaskOccurrences(task, appData.getSessions(), sequence); 
    588                  
    589                 harmonizeSequenceInstancesModel(sequence, sequenceInstances,task.size()); 
    590                 appData.detectedAndReplacedTasks 
    591                     (appData.detectedAndReplacedTasks() || (sequenceInstances.size() > 0)); 
    592  
    593                 if (sequenceInstances.size() < appData.getLastFoundTasks().getOccurrenceCount()) { 
    594                     Console.traceln(Level.FINE, sequence.getId() + ": replaced task only " + 
    595                                     sequenceInstances.size() + " times instead of expected " + 
    596                                     appData.getLastFoundTasks().getOccurrenceCount()); 
    597                 } 
    598             } 
    599         } 
    600          
    601     } 
    602  
    603     /** 
     284        } 
     285 
     286        /** 
     287         * <p> 
     288         * searches for direct iterations of single tasks in all sequences and 
     289         * replaces them with {@link IIteration}s, respectively appropriate 
     290         * instances. Also all single occurrences of a task that is iterated 
     291         * somewhen are replaced with iterations to have again an efficient way for 
     292         * task comparisons. 
     293         * </p> 
     294         *  
     295         * @param appData 
     296         *            the rule application data combining all data used for applying 
     297         *            this rule 
     298         */ 
     299        private void detectAndReplaceIterations(RuleApplicationData appData) { 
     300                Console.traceln(Level.FINE, "detecting iterations"); 
     301                appData.getStopWatch().start("detecting iterations"); 
     302 
     303                List<IUserSession> sessions = appData.getSessions(); 
     304 
     305                Set<ITask> iteratedTasks = searchIteratedTasks(sessions); 
     306 
     307                if (iteratedTasks.size() > 0) { 
     308                        replaceIterationsOf(iteratedTasks, sessions, appData); 
     309                } 
     310 
     311                appData.getStopWatch().stop("detecting iterations"); 
     312                Console.traceln(Level.INFO, "replaced " + iteratedTasks.size() 
     313                                + " iterated tasks"); 
     314        } 
     315 
     316        /** 
     317         * <p> 
     318         * searches the provided sessions for task iterations. If a task is 
     319         * iterated, it is added to the returned set. 
     320         * </p> 
     321         *  
     322         * @param the 
     323         *            session to search for iterations in 
     324         *  
     325         * @return a set of tasks being iterated somewhere 
     326         */ 
     327        private Set<ITask> searchIteratedTasks(List<IUserSession> sessions) { 
     328                Set<ITask> iteratedTasks = new HashSet<ITask>(); 
     329                for (IUserSession session : sessions) { 
     330                        for (int i = 0; i < (session.size() - 1); i++) { 
     331                                // we prepared the task instances to refer to unique tasks, if 
     332                                // they are treated 
     333                                // as equal. Therefore, we just compare the identity of the 
     334                                // tasks of the task 
     335                                // instances 
     336                                if (session.get(i).getTask() == session.get(i + 1).getTask()) { 
     337                                        iteratedTasks.add(session.get(i).getTask()); 
     338                                } 
     339                        } 
     340                } 
     341 
     342                return iteratedTasks; 
     343        } 
     344 
     345        /** 
     346         * <p> 
     347         * replaces all occurrences of all tasks provided in the set with iterations 
     348         * </p> 
     349         *  
     350         * @param iteratedTasks 
     351         *            the tasks to be replaced with iterations 
     352         * @param sessions 
     353         *            the sessions in which the tasks are to be replaced 
     354         * @param appData 
     355         *            the rule application data combining all data used for applying 
     356         *            this rule 
     357         */ 
     358        private void replaceIterationsOf(Set<ITask> iteratedTasks, 
     359                        List<IUserSession> sessions, RuleApplicationData appData) { 
     360                Map<ITask, IIteration> iterations = new HashMap<ITask, IIteration>(); 
     361                Map<IIteration, List<IIterationInstance>> iterationInstances = new HashMap<IIteration, List<IIterationInstance>>(); 
     362 
     363                for (ITask iteratedTask : iteratedTasks) { 
     364                        IIteration iteration = taskFactory.createNewIteration(); 
     365                        iterations.put(iteratedTask, iteration); 
     366                        iterationInstances.put(iteration, 
     367                                        new LinkedList<IIterationInstance>()); 
     368                } 
     369 
     370                IIterationInstance iterationInstance; 
     371 
     372                for (IUserSession session : sessions) { 
     373                        int index = 0; 
     374                        iterationInstance = null; 
     375 
     376                        while (index < session.size()) { 
     377                                // we prepared the task instances to refer to unique tasks, if 
     378                                // they are treated 
     379                                // as equal. Therefore, we just compare the identity of the 
     380                                // tasks of the task 
     381                                // instances 
     382                                ITask currentTask = session.get(index).getTask(); 
     383                                IIteration iteration = iterations.get(currentTask); 
     384                                if (iteration != null) { 
     385                                        if ((iterationInstance == null) 
     386                                                        || (iterationInstance.getTask() != iteration)) { 
     387                                                iterationInstance = taskFactory 
     388                                                                .createNewTaskInstance(iteration); 
     389                                                iterationInstances.get(iteration) 
     390                                                                .add(iterationInstance); 
     391                                                taskBuilder.addTaskInstance(session, index, 
     392                                                                iterationInstance); 
     393                                                index++; 
     394                                        } 
     395 
     396                                        taskBuilder.addChild(iterationInstance, session.get(index)); 
     397                                        taskBuilder.removeTaskInstance(session, index); 
     398                                } else { 
     399                                        if (iterationInstance != null) { 
     400                                                iterationInstance = null; 
     401                                        } 
     402                                        index++; 
     403                                } 
     404                        } 
     405                } 
     406 
     407                for (Map.Entry<IIteration, List<IIterationInstance>> entry : iterationInstances 
     408                                .entrySet()) { 
     409                        harmonizeIterationInstancesModel(entry.getKey(), entry.getValue()); 
     410                } 
     411        } 
     412 
     413        /** 
     414         * <p> 
     415         * TODO clarify why this is done 
     416         * </p> 
     417         */ 
     418        private void harmonizeIterationInstancesModel(IIteration iteration, 
     419                        List<IIterationInstance> iterationInstances) { 
     420                List<ITask> iteratedTaskVariants = new LinkedList<ITask>(); 
     421                TaskInstanceComparator comparator = preparationTaskHandlingStrategy 
     422                                .getTaskComparator(); 
     423 
     424                // merge the lexically different variants of iterated task to a unique 
     425                // list 
     426                for (IIterationInstance iterationInstance : iterationInstances) { 
     427                        for (ITaskInstance executionVariant : iterationInstance) { 
     428                                ITask candidate = executionVariant.getTask(); 
     429 
     430                                boolean found = false; 
     431                                for (ITask taskVariant : iteratedTaskVariants) { 
     432                                        if (comparator.areLexicallyEqual(taskVariant, candidate)) { 
     433                                                taskBuilder.setTask(executionVariant, taskVariant); 
     434                                                found = true; 
     435                                                break; 
     436                                        } 
     437                                } 
     438 
     439                                if (!found) { 
     440                                        iteratedTaskVariants.add(candidate); 
     441                                } 
     442                        } 
     443                } 
     444 
     445                // if there are more than one lexically different variant of iterated 
     446                // tasks, adapt the 
     447                // iteration model to be a selection of different variants. In this case 
     448                // also adapt 
     449                // the generated iteration instances to correctly contain selection 
     450                // instances. If there 
     451                // is only one variant of an iterated task, simply set this as the 
     452                // marked task of the 
     453                // iteration. In this case, the instances can be preserved as is 
     454                if (iteratedTaskVariants.size() > 1) { 
     455                        ISelection selection = taskFactory.createNewSelection(); 
     456 
     457                        for (ITask variant : iteratedTaskVariants) { 
     458                                taskBuilder.addChild(selection, variant); 
     459                        } 
     460 
     461                        taskBuilder.setMarkedTask(iteration, selection); 
     462 
     463                        for (IIterationInstance instance : iterationInstances) { 
     464                                for (int i = 0; i < instance.size(); i++) { 
     465                                        ISelectionInstance selectionInstance = taskFactory 
     466                                                        .createNewTaskInstance(selection); 
     467                                        taskBuilder.setChild(selectionInstance, instance.get(i)); 
     468                                        taskBuilder.setTaskInstance(instance, i, selectionInstance); 
     469                                } 
     470                        } 
     471                } else { 
     472                        taskBuilder.setMarkedTask(iteration, iteratedTaskVariants.get(0)); 
     473                } 
     474        } 
     475 
     476        /** 
     477         * TODO go on commenting 
     478         *  
     479         * @param appData 
     480         *            the rule application data combining all data used for applying 
     481         *            this rule 
     482         */ 
     483        private void detectAndReplaceTasks(RuleApplicationData appData) { 
     484                Console.traceln(Level.FINE, "detecting and replacing tasks"); 
     485                appData.getStopWatch().start("detecting tasks"); 
     486 
     487                getSequencesOccuringMostOften(appData); 
     488 
     489                appData.getStopWatch().stop("detecting tasks"); 
     490                appData.getStopWatch().start("replacing tasks"); 
     491 
     492                replaceSequencesOccurringMostOften(appData); 
     493 
     494                appData.getStopWatch().stop("replacing tasks"); 
     495                Console.traceln(Level.INFO, "detected and replaced " 
     496                                + appData.getLastFoundTasks().size() + " tasks occuring " 
     497                                + appData.getLastFoundTasks().getOccurrenceCount() + " times"); 
     498        } 
     499 
     500        /** 
     501         * @param appData 
     502         *            the rule application data combining all data used for applying 
     503         *            this rule 
     504         */ 
     505        private void getSequencesOccuringMostOften(RuleApplicationData appData) { 
     506                Console.traceln(Level.FINE, "determining most prominent tasks"); 
     507 
     508                Tasks tasks; 
     509                boolean createNewTrie = (appData.getLastTrie() == null) 
     510                                || appData.detectedAndReplacedTasks(); // tree has changed 
     511 
     512                do { 
     513                        if (createNewTrie) { 
     514                                createNewTrie(appData); 
     515                        } 
     516 
     517                        MaxCountAndLongestTasksFinder finder = new MaxCountAndLongestTasksFinder(); 
     518                        appData.getLastTrie().process(finder); 
     519 
     520                        tasks = finder.getFoundTasks(); 
     521 
     522                        createNewTrie = false; 
     523 
     524                        for (List<ITaskInstance> task : tasks) { 
     525                                if (task.size() >= appData.getTrainedSequenceLength()) { 
     526                                        // Trie must be recreated with a longer sequence length to 
     527                                        // be sure that 
     528                                        // the found sequences occurring most often are found in 
     529                                        // their whole length 
     530                                        appData.setTrainedSequenceLength(appData 
     531                                                        .getTrainedSequenceLength() + 1); 
     532                                        createNewTrie = true; 
     533                                        break; 
     534                                } 
     535                        } 
     536                } while (createNewTrie); 
     537 
     538                // create a normal trie for comparison 
     539                /* 
     540                 * System.out.println("creating test trie for comparison"); 
     541                 *  
     542                 * appData.getStopWatch().start("testtrie"); Trie<ITaskInstance> trie = 
     543                 * new Trie<ITaskInstance>(identityTaskComparator); 
     544                 *  
     545                 * for (IUserSession session : appData.getSessions()) { 
     546                 * trie.train(session.getExecutedTasks(), 
     547                 * appData.getTrainedSequenceLength()); } 
     548                 *  
     549                 * appData.getStopWatch().stop("testtrie"); 
     550                 *  
     551                 * MaxCountAndLongestTasksFinder finder = new 
     552                 * MaxCountAndLongestTasksFinder(); trie.process(finder); 
     553                 *  
     554                 * boolean allTasksEqual = finder.getFoundTasks().size() == 
     555                 * tasks.size(); 
     556                 *  
     557                 * allTasksEqual &= finder.getFoundTasks().occurrenceCount == 
     558                 * tasks.occurrenceCount; 
     559                 *  
     560                 * for (List<ITaskInstance> task1 : finder.getFoundTasks()) { boolean 
     561                 * foundTask = false; for (List<ITaskInstance> task2 : tasks) { boolean 
     562                 * tasksEqual = false; if (task1.size() == task2.size()) { tasksEqual = 
     563                 * true; for (int i = 0; i < task1.size(); i++) { if 
     564                 * (!identityTaskComparator.equals(task1.get(i).getTask(), 
     565                 * task2.get(i).getTask())) { tasksEqual = false; } } } 
     566                 *  
     567                 * if (tasksEqual) { foundTask = true; break; } } 
     568                 *  
     569                 * if (!foundTask) { System.out.println("different is " + task1); 
     570                 * allTasksEqual = false; break; } } 
     571                 *  
     572                 * if (!allTasksEqual) { System.out.println(finder.getFoundTasks()); 
     573                 * System.out.println(tasks); 
     574                 *  
     575                 * throw new 
     576                 * IllegalArgumentException("both tries calculated different subsequences" 
     577                 * ); } 
     578                 *  
     579                 * /*TrieStatisticsDumper dumper = new TrieStatisticsDumper(); 
     580                 * appData.getLastTrie().process(dumper); dumper.dumpCounters(); 
     581                 */ 
     582 
     583                appData.setLastFoundTasks(tasks); 
     584 
     585                Console.traceln(Level.FINE, "found " 
     586                                + appData.getLastFoundTasks().size() + " tasks " + "occurring " 
     587                                + appData.getLastFoundTasks().getOccurrenceCount() + " times"); 
     588        } 
     589 
     590        /** 
     591         * @param appData 
     592         *            the rule application data combining all data used for applying 
     593         *            this rule 
     594         */ 
     595        private void createNewTrie(RuleApplicationData appData) { 
     596                Console.traceln( 
     597                                Level.FINER, 
     598                                "training trie with a maximum sequence length of " 
     599                                                + appData.getTrainedSequenceLength()); 
     600 
     601                appData.getStopWatch().start("training trie"); 
     602 
     603                // we prepared the task instances to refer to unique tasks, if they are 
     604                // treated 
     605                // as equal. Therefore, we just compare the identity of the tasks of the 
     606                // task 
     607                // instances 
     608                appData.setLastTrie(new TaskInstanceTrie(identityTaskHandlingStrategy)); 
     609 
     610                appData.getLastTrie().trainSessions(appData.getSessions(), 
     611                                appData.getTrainedSequenceLength()); 
     612 
     613                appData.getStopWatch().stop("training trie"); 
     614        } 
     615 
     616        /** 
     617         * @param appData 
     618         *            the rule application data combining all data used for applying 
     619         *            this rule 
     620         */ 
     621        private void replaceSequencesOccurringMostOften(RuleApplicationData appData) { 
     622                appData.detectedAndReplacedTasks(false); 
     623 
     624                if ((appData.getLastFoundTasks().size() > 0) 
     625                                && (appData.getLastFoundTasks().getOccurrenceCount() > 1)) { 
     626                        Console.traceln(Level.FINER, "replacing tasks occurrences"); 
     627 
     628                        for (List<ITaskInstance> task : appData.getLastFoundTasks()) { 
     629                                ISequence sequence = taskFactory.createNewSequence(); 
     630 
     631                                Console.traceln(Level.FINEST, "replacing " + sequence.getId() 
     632                                                + ": " + task); 
     633 
     634                                List<ISequenceInstance> sequenceInstances = replaceTaskOccurrences( 
     635                                                task, appData.getSessions(), sequence); 
     636 
     637                                harmonizeSequenceInstancesModel(sequence, sequenceInstances, 
     638                                                task.size()); 
     639                                appData.detectedAndReplacedTasks(appData 
     640                                                .detectedAndReplacedTasks() 
     641                                                || (sequenceInstances.size() > 0)); 
     642 
     643                                if (sequenceInstances.size() < appData.getLastFoundTasks() 
     644                                                .getOccurrenceCount()) { 
     645                                        Console.traceln(Level.FINE, 
     646                                                        sequence.getId() 
     647                                                                        + ": replaced task only " 
     648                                                                        + sequenceInstances.size() 
     649                                                                        + " times instead of expected " 
     650                                                                        + appData.getLastFoundTasks() 
     651                                                                                        .getOccurrenceCount()); 
     652                                } 
     653                        } 
     654                } 
     655 
     656        } 
     657 
     658        /** 
    604659     * 
    605660     */ 
    606     private void harmonizeSequenceInstancesModel(ISequence               sequence, 
    607                                                  List<ISequenceInstance> sequenceInstances, 
    608                                                  int                     sequenceLength) 
    609     { 
    610         TaskInstanceComparator comparator = preparationTaskHandlingStrategy.getTaskComparator(); 
    611          
    612         // ensure for each subtask that lexically different variants are preserved 
    613         for (int subTaskIndex = 0; subTaskIndex < sequenceLength; subTaskIndex++) { 
    614             List<ITask> subTaskVariants = new LinkedList<ITask>(); 
    615              
    616             for (ISequenceInstance sequenceInstance : sequenceInstances) { 
    617                 ITask candidate = sequenceInstance.get(subTaskIndex).getTask(); 
    618                  
    619                 boolean found = false; 
    620                  
    621                 for (int i = 0; i < subTaskVariants.size(); i++) { 
    622                     if (comparator.areLexicallyEqual(subTaskVariants.get(i), candidate)) { 
    623                         taskBuilder.setTask 
    624                             (sequenceInstance.get(subTaskIndex), subTaskVariants.get(i)); 
    625                          
    626                         found = true; 
    627                         break; 
    628                     } 
    629                 } 
    630                  
    631                 if (!found) { 
    632                     subTaskVariants.add(candidate); 
    633                 } 
    634             } 
    635              
    636             // if there are more than one lexically different variant of the sub task at 
    637             // the considered position, adapt the sequence model at that position to have 
    638             // a selection of the different variants. In this case also adapt the 
    639             // generated sequence instances to correctly contain selection instances. If 
    640             // there is only one variant of sub tasks at the given position, simply set 
    641             // this variant as the sub task of the selection. In this case, the instances 
    642             // can be preserved as is 
    643             if (subTaskVariants.size() > 1) { 
    644                 ISelection selection = taskFactory.createNewSelection(); 
    645                  
    646                 for (ITask variant : subTaskVariants) { 
    647                     taskBuilder.addChild(selection, variant); 
    648                 } 
    649                  
    650                 taskBuilder.addChild(sequence, selection); 
    651                  
    652                 for (ISequenceInstance instance : sequenceInstances) { 
    653                     ISelectionInstance selectionInstance = 
    654                         taskFactory.createNewTaskInstance(selection); 
    655                     taskBuilder.setChild(selectionInstance, instance.get(subTaskIndex)); 
    656                     taskBuilder.setTaskInstance(instance, subTaskIndex, selectionInstance); 
    657                 } 
    658             } 
    659             else if (subTaskVariants.size() == 1) { 
    660                 taskBuilder.addChild(sequence, subTaskVariants.get(0)); 
    661             } 
    662         } 
    663     } 
    664  
    665     /** 
    666      * @param tree 
    667      */ 
    668     private List<ISequenceInstance> replaceTaskOccurrences(List<ITaskInstance> task, 
    669                                                            List<IUserSession>  sessions, 
    670                                                            ISequence           temporalTaskModel) 
    671     { 
    672         List<ISequenceInstance> sequenceInstances = new LinkedList<ISequenceInstance>(); 
    673          
    674         for (IUserSession session : sessions) { 
    675             int index = -1; 
    676                  
    677             do { 
    678                 index = getSubListIndex(session, task, ++index); 
    679  
    680                 if (index > -1) { 
    681                     sequenceInstances.add 
    682                         (RuleUtils.createNewSubSequenceInRange 
    683                              (session, index, index + task.size() - 1, temporalTaskModel, 
    684                               taskFactory, taskBuilder)); 
    685                 } 
    686             } 
    687             while (index > -1); 
    688         } 
    689          
    690         return sequenceInstances; 
    691     } 
    692  
    693     /** 
    694      * @param trie 
    695      * @param object 
    696      * @return 
    697      */ 
    698     private int getSubListIndex(ITaskInstanceList   list, 
    699                                 List<ITaskInstance> subList, 
    700                                 int                 startIndex) 
    701     { 
    702         boolean matchFound; 
    703         int result = -1; 
    704          
    705         for (int i = startIndex; i <= list.size() - subList.size(); i++) { 
    706             matchFound = true; 
    707              
    708             for (int j = 0; j < subList.size(); j++) { 
    709                 // we prepared the task instances to refer to unique tasks, if they are treated 
    710                 // as equal. Therefore, we just compare the identity of the tasks of the task 
    711                 // instances 
    712                 if (list.get(i + j).getTask() != subList.get(j).getTask()) { 
    713                     matchFound = false; 
    714                     break; 
    715                 } 
    716             } 
    717              
    718             if (matchFound) { 
    719                 result = i; 
    720                 break; 
    721             } 
    722         } 
    723          
    724         return result; 
    725     } 
    726  
    727     /** 
    728      * @param trie 
    729      * @param object 
    730      * @return 
    731      */ 
    732     private int getSubListIndex(List<ITaskInstance> list, 
    733                                 List<ITaskInstance> subList, 
    734                                 int                 startIndex) 
    735     { 
    736         boolean matchFound; 
    737         int result = -1; 
    738          
    739         for (int i = startIndex; i <= list.size() - subList.size(); i++) { 
    740             matchFound = true; 
    741              
    742             for (int j = 0; j < subList.size(); j++) { 
    743                 // we prepared the task instances to refer to unique tasks, if they are treated 
    744                 // as equal. Therefore, we just compare the identity of the tasks of the task 
    745                 // instances 
    746                 if (list.get(i + j) != subList.get(j)) { 
    747                     matchFound = false; 
    748                     break; 
    749                 } 
    750             } 
    751              
    752             if (matchFound) { 
    753                 result = i; 
    754                 break; 
    755             } 
    756         } 
    757          
    758         return result; 
    759     } 
    760      
    761     /** 
    762      * @author Patrick Harms 
    763      */ 
    764     private class MaxCountAndLongestTasksFinder implements TrieProcessor<ITaskInstance> { 
    765          
    766         /** 
     661        private void harmonizeSequenceInstancesModel(ISequence sequence, 
     662                        List<ISequenceInstance> sequenceInstances, int sequenceLength) { 
     663                TaskInstanceComparator comparator = preparationTaskHandlingStrategy 
     664                                .getTaskComparator(); 
     665 
     666                // ensure for each subtask that lexically different variants are 
     667                // preserved 
     668                for (int subTaskIndex = 0; subTaskIndex < sequenceLength; subTaskIndex++) { 
     669                        List<ITask> subTaskVariants = new LinkedList<ITask>(); 
     670 
     671                        for (ISequenceInstance sequenceInstance : sequenceInstances) { 
     672                                ITask candidate = sequenceInstance.get(subTaskIndex).getTask(); 
     673 
     674                                boolean found = false; 
     675 
     676                                for (int i = 0; i < subTaskVariants.size(); i++) { 
     677                                        if (comparator.areLexicallyEqual(subTaskVariants.get(i), 
     678                                                        candidate)) { 
     679                                                taskBuilder.setTask(sequenceInstance.get(subTaskIndex), 
     680                                                                subTaskVariants.get(i)); 
     681 
     682                                                found = true; 
     683                                                break; 
     684                                        } 
     685                                } 
     686 
     687                                if (!found) { 
     688                                        subTaskVariants.add(candidate); 
     689                                } 
     690                        } 
     691 
     692                        // if there are more than one lexically different variant of the sub 
     693                        // task at 
     694                        // the considered position, adapt the sequence model at that 
     695                        // position to have 
     696                        // a selection of the different variants. In this case also adapt 
     697                        // the 
     698                        // generated sequence instances to correctly contain selection 
     699                        // instances. If 
     700                        // there is only one variant of sub tasks at the given position, 
     701                        // simply set 
     702                        // this variant as the sub task of the selection. In this case, the 
     703                        // instances 
     704                        // can be preserved as is 
     705                        if (subTaskVariants.size() > 1) { 
     706                                ISelection selection = taskFactory.createNewSelection(); 
     707 
     708                                for (ITask variant : subTaskVariants) { 
     709                                        taskBuilder.addChild(selection, variant); 
     710                                } 
     711 
     712                                taskBuilder.addChild(sequence, selection); 
     713 
     714                                for (ISequenceInstance instance : sequenceInstances) { 
     715                                        ISelectionInstance selectionInstance = taskFactory 
     716                                                        .createNewTaskInstance(selection); 
     717                                        taskBuilder.setChild(selectionInstance, 
     718                                                        instance.get(subTaskIndex)); 
     719                                        taskBuilder.setTaskInstance(instance, subTaskIndex, 
     720                                                        selectionInstance); 
     721                                } 
     722                        } else if (subTaskVariants.size() == 1) { 
     723                                taskBuilder.addChild(sequence, subTaskVariants.get(0)); 
     724                        } 
     725                } 
     726        } 
     727 
     728        /** 
     729         * @param tree 
     730         */ 
     731        private List<ISequenceInstance> replaceTaskOccurrences( 
     732                        List<ITaskInstance> task, List<IUserSession> sessions, 
     733                        ISequence temporalTaskModel) { 
     734                List<ISequenceInstance> sequenceInstances = new LinkedList<ISequenceInstance>(); 
     735 
     736                for (IUserSession session : sessions) { 
     737                        int index = -1; 
     738 
     739                        do { 
     740                                index = getSubListIndex(session, task, ++index); 
     741 
     742                                if (index > -1) { 
     743                                        sequenceInstances.add(RuleUtils 
     744                                                        .createNewSubSequenceInRange(session, index, index 
     745                                                                        + task.size() - 1, temporalTaskModel, 
     746                                                                        taskFactory, taskBuilder)); 
     747                                } 
     748                        } while (index > -1); 
     749                } 
     750 
     751                return sequenceInstances; 
     752        } 
     753 
     754        /** 
     755         * @param trie 
     756         * @param object 
     757         * @return 
     758         */ 
     759        private int getSubListIndex(ITaskInstanceList list, 
     760                        List<ITaskInstance> subList, int startIndex) { 
     761                boolean matchFound; 
     762                int result = -1; 
     763 
     764                for (int i = startIndex; i <= list.size() - subList.size(); i++) { 
     765                        matchFound = true; 
     766 
     767                        for (int j = 0; j < subList.size(); j++) { 
     768                                // we prepared the task instances to refer to unique tasks, if 
     769                                // they are treated 
     770                                // as equal. Therefore, we just compare the identity of the 
     771                                // tasks of the task 
     772                                // instances 
     773                                if (list.get(i + j).getTask() != subList.get(j).getTask()) { 
     774                                        matchFound = false; 
     775                                        break; 
     776                                } 
     777                        } 
     778 
     779                        if (matchFound) { 
     780                                result = i; 
     781                                break; 
     782                        } 
     783                } 
     784 
     785                return result; 
     786        } 
     787 
     788        /** 
     789         * @param trie 
     790         * @param object 
     791         * @return 
     792         */ 
     793        private int getSubListIndex(List<ITaskInstance> list, 
     794                        List<ITaskInstance> subList, int startIndex) { 
     795                boolean matchFound; 
     796                int result = -1; 
     797 
     798                for (int i = startIndex; i <= list.size() - subList.size(); i++) { 
     799                        matchFound = true; 
     800 
     801                        for (int j = 0; j < subList.size(); j++) { 
     802                                // we prepared the task instances to refer to unique tasks, if 
     803                                // they are treated 
     804                                // as equal. Therefore, we just compare the identity of the 
     805                                // tasks of the task 
     806                                // instances 
     807                                if (list.get(i + j) != subList.get(j)) { 
     808                                        matchFound = false; 
     809                                        break; 
     810                                } 
     811                        } 
     812 
     813                        if (matchFound) { 
     814                                result = i; 
     815                                break; 
     816                        } 
     817                } 
     818 
     819                return result; 
     820        } 
     821 
     822        /** 
     823         * @author Patrick Harms 
     824         */ 
     825        private class MaxCountAndLongestTasksFinder implements 
     826                        TrieProcessor<ITaskInstance> { 
     827 
     828                /** 
    767829         *  
    768830         */ 
    769         private int currentCount; 
    770          
    771         /** 
     831                private int currentCount; 
     832 
     833                /** 
    772834         *  
    773835         */ 
    774         private List<List<ITaskInstance>> foundTasks = new LinkedList<List<ITaskInstance>>(); 
    775  
    776         /** 
     836                private List<List<ITaskInstance>> foundTasks = new LinkedList<List<ITaskInstance>>(); 
     837 
     838                /** 
    777839         * 
    778840         */ 
    779         public MaxCountAndLongestTasksFinder() { 
    780             super(); 
    781             this.currentCount = 0; 
    782         } 
    783  
    784         /* (non-Javadoc) 
    785          * @see de.ugoe.cs.autoquest.usageprofiles.TrieProcessor#process(java.util.List, int) 
    786          */ 
    787         @Override 
    788         public TrieProcessor.Result process(List<ITaskInstance> foundTask, int count) { 
    789             if (foundTask.size() < 2) { 
    790                 // ignore single tasks 
    791                 return TrieProcessor.Result.CONTINUE; 
    792             } 
    793              
    794             if (count < 2) { 
    795                 // ignore singular occurrences 
    796                 return TrieProcessor.Result.SKIP_NODE; 
    797             } 
    798  
    799             if (this.currentCount > count) { 
    800                 // ignore this children of this task, as they may have only smaller counts than 
    801                 // the already found tasks 
    802                 return TrieProcessor.Result.SKIP_NODE; 
    803             } 
    804              
    805             if (this.currentCount < count) { 
    806                 // the provided task occurs more often that all tasks found so far. 
    807                 // clear all found tasks and use the new count as the one searched for 
    808                 foundTasks.clear(); 
    809                 this.currentCount = count; 
    810             } 
    811              
    812             if (this.currentCount == count) { 
    813                 // the task is of interest. Sort it into the other found tasks so that 
    814                 // the longest come first 
    815                 boolean added = false; 
    816                 for (int i = 0; i < foundTasks.size(); i++) { 
    817                     if (foundTasks.get(i).size() < foundTask.size()) { 
    818                         // defensive copy 
    819                         foundTasks.add(i, new LinkedList<ITaskInstance>(foundTask)); // defensive copy 
    820                         added = true; 
    821                         break; 
    822                     } 
    823                 } 
    824                  
    825                 if (!added) { 
    826                     foundTasks.add(new LinkedList<ITaskInstance>(foundTask)); // defensive copy 
    827                 } 
    828             } 
    829              
    830             return TrieProcessor.Result.CONTINUE; 
    831         } 
    832  
    833         /** 
    834          *  @return 
    835          */ 
    836         public Tasks getFoundTasks() { 
    837             removePermutationsOfShorterTasks(); 
    838             return new Tasks(currentCount, foundTasks); 
    839         } 
    840  
    841         /** 
     841                public MaxCountAndLongestTasksFinder() { 
     842                        super(); 
     843                        this.currentCount = 0; 
     844                } 
     845 
     846                /* 
     847                 * (non-Javadoc) 
     848                 *  
     849                 * @see 
     850                 * de.ugoe.cs.autoquest.usageprofiles.TrieProcessor#process(java.util 
     851                 * .List, int) 
     852                 */ 
     853                @Override 
     854                public TrieProcessor.Result process(List<ITaskInstance> foundTask, 
     855                                int count) { 
     856                        if (foundTask.size() < 2) { 
     857                                // ignore single tasks 
     858                                return TrieProcessor.Result.CONTINUE; 
     859                        } 
     860 
     861                        if (count < 2) { 
     862                                // ignore singular occurrences 
     863                                return TrieProcessor.Result.SKIP_NODE; 
     864                        } 
     865 
     866                        if (this.currentCount > count) { 
     867                                // ignore this children of this task, as they may have only 
     868                                // smaller counts than 
     869                                // the already found tasks 
     870                                return TrieProcessor.Result.SKIP_NODE; 
     871                        } 
     872 
     873                        if (this.currentCount < count) { 
     874                                // the provided task occurs more often that all tasks found so 
     875                                // far. 
     876                                // clear all found tasks and use the new count as the one 
     877                                // searched for 
     878                                foundTasks.clear(); 
     879                                this.currentCount = count; 
     880                        } 
     881 
     882                        if (this.currentCount == count) { 
     883                                // the task is of interest. Sort it into the other found tasks 
     884                                // so that 
     885                                // the longest come first 
     886                                boolean added = false; 
     887                                for (int i = 0; i < foundTasks.size(); i++) { 
     888                                        if (foundTasks.get(i).size() < foundTask.size()) { 
     889                                                // defensive copy 
     890                                                foundTasks.add(i, new LinkedList<ITaskInstance>( 
     891                                                                foundTask)); // defensive copy 
     892                                                added = true; 
     893                                                break; 
     894                                        } 
     895                                } 
     896 
     897                                if (!added) { 
     898                                        foundTasks.add(new LinkedList<ITaskInstance>(foundTask)); // defensive 
     899                                                                                                                                                                // copy 
     900                                } 
     901                        } 
     902 
     903                        return TrieProcessor.Result.CONTINUE; 
     904                } 
     905 
     906                /** 
     907                 * @return 
     908                 */ 
     909                public Tasks getFoundTasks() { 
     910                        removePermutationsOfShorterTasks(); 
     911                        return new Tasks(currentCount, foundTasks); 
     912                } 
     913 
     914                /** 
    842915         * 
    843916         */ 
    844         private void removePermutationsOfShorterTasks() { 
    845             // now iterate the sorted list and for each task remove all other tasks that are shorter 
    846             // (i.e. come later in the sorted list) and that represent a subpart of the task 
    847             for (int i = 0; i < foundTasks.size(); i++) { 
    848                 for (int j = i + 1; j < foundTasks.size();) { 
    849                     if (foundTasks.get(j).size() < foundTasks.get(i).size()) { 
    850                         // found a task that is a potential subtask. Check for this and remove the 
    851                         // subtask if needed 
    852                         List<ITaskInstance> longTask = foundTasks.get(i); 
    853                         List<ITaskInstance> shortTask = foundTasks.get(j); 
    854                          
    855                         if (getSubListIndex(longTask, shortTask, 0) > -1) { 
    856                             foundTasks.remove(j); 
    857                         } 
    858                         else { 
    859                             j++; 
    860                         } 
    861                     } 
    862                     else { 
    863                         j++; 
    864                     } 
    865                 } 
    866             } 
    867         } 
    868  
    869     } 
    870      
    871 //    /** 
    872 //     * @author Patrick Harms 
    873 //     */ 
    874 //    private class TrieStatisticsDumper implements TrieProcessor<ITaskInstance> { 
    875 //         
    876 //        /** 
    877 //         *  
    878 //         */ 
    879 //        private Map<Integer, Integer> counters = new HashMap<Integer, Integer>(); 
    880 //         
    881 //        /* (non-Javadoc) 
    882 //         * @see de.ugoe.cs.autoquest.usageprofiles.TrieProcessor#process(java.util.List, int) 
    883 //         */ 
    884 //        @Override 
    885 //        public TrieProcessor.Result process(List<ITaskInstance> subsequence, int count) { 
    886 //            if (subsequence.size() == 1) { 
    887 //                Integer value = counters.get(count); 
    888 //                 
    889 //                if (value == null) { 
    890 //                    value = 0; 
    891 //                } 
    892 //                 
    893 //                counters.put(count, value + 1); 
    894 //                 
    895 //                return TrieProcessor.Result.CONTINUE; 
    896 //            } 
    897 //            else { 
    898 //                // ignore singular occurrences 
    899 //                return TrieProcessor.Result.SKIP_NODE; 
    900 //            } 
    901 //        } 
    902 // 
    903 //        /** 
    904 //         *  @return 
    905 //         */ 
    906 //        public void dumpCounters() { 
    907 //            int dumpedCounters = 0; 
    908 //             
    909 //            int count = 1; 
    910 //            while (dumpedCounters < counters.size()) { 
    911 //                Integer value = counters.get(count++); 
    912 //                if (value != null) { 
    913 //                    System.out.println(value + " symbols occurred " + count + " times"); 
    914 //                    dumpedCounters++; 
    915 //                } 
    916 //            } 
    917 //        } 
    918 // 
    919 //    } 
    920      
    921     /** 
     917                private void removePermutationsOfShorterTasks() { 
     918                        // now iterate the sorted list and for each task remove all other 
     919                        // tasks that are shorter 
     920                        // (i.e. come later in the sorted list) and that represent a subpart 
     921                        // of the task 
     922                        for (int i = 0; i < foundTasks.size(); i++) { 
     923                                for (int j = i + 1; j < foundTasks.size();) { 
     924                                        if (foundTasks.get(j).size() < foundTasks.get(i).size()) { 
     925                                                // found a task that is a potential subtask. Check for 
     926                                                // this and remove the 
     927                                                // subtask if needed 
     928                                                List<ITaskInstance> longTask = foundTasks.get(i); 
     929                                                List<ITaskInstance> shortTask = foundTasks.get(j); 
     930 
     931                                                if (getSubListIndex(longTask, shortTask, 0) > -1) { 
     932                                                        foundTasks.remove(j); 
     933                                                } else { 
     934                                                        j++; 
     935                                                } 
     936                                        } else { 
     937                                                j++; 
     938                                        } 
     939                                } 
     940                        } 
     941                } 
     942 
     943        } 
     944 
     945        // /** 
     946        // * @author Patrick Harms 
     947        // */ 
     948        // private class TrieStatisticsDumper implements 
     949        // TrieProcessor<ITaskInstance> { 
     950        // 
     951        // /** 
     952        // * 
     953        // */ 
     954        // private Map<Integer, Integer> counters = new HashMap<Integer, Integer>(); 
     955        // 
     956        // /* (non-Javadoc) 
     957        // * @see 
     958        // de.ugoe.cs.autoquest.usageprofiles.TrieProcessor#process(java.util.List, 
     959        // int) 
     960        // */ 
     961        // @Override 
     962        // public TrieProcessor.Result process(List<ITaskInstance> subsequence, int 
     963        // count) { 
     964        // if (subsequence.size() == 1) { 
     965        // Integer value = counters.get(count); 
     966        // 
     967        // if (value == null) { 
     968        // value = 0; 
     969        // } 
     970        // 
     971        // counters.put(count, value + 1); 
     972        // 
     973        // return TrieProcessor.Result.CONTINUE; 
     974        // } 
     975        // else { 
     976        // // ignore singular occurrences 
     977        // return TrieProcessor.Result.SKIP_NODE; 
     978        // } 
     979        // } 
     980        // 
     981        // /** 
     982        // * @return 
     983        // */ 
     984        // public void dumpCounters() { 
     985        // int dumpedCounters = 0; 
     986        // 
     987        // int count = 1; 
     988        // while (dumpedCounters < counters.size()) { 
     989        // Integer value = counters.get(count++); 
     990        // if (value != null) { 
     991        // System.out.println(value + " symbols occurred " + count + " times"); 
     992        // dumpedCounters++; 
     993        // } 
     994        // } 
     995        // } 
     996        // 
     997        // } 
     998 
     999        /** 
    9221000     *  
    9231001     */ 
    924     private static class RuleApplicationData { 
    925          
    926         /** 
     1002        private static class RuleApplicationData { 
     1003 
     1004                /** 
    9271005         *  
    9281006         */ 
    929         private List<IUserSession> sessions; 
    930          
    931         /** 
     1007                private List<IUserSession> sessions; 
     1008 
     1009                /** 
    9321010         *  
    9331011         */ 
    934         private TaskInstanceTrie lastTrie; 
    935          
    936         /** 
    937         * default and minimum trained sequence length is 3 
    938         */ 
    939         private int trainedSequenceLength = 3; 
    940          
    941         /** 
     1012                private TaskInstanceTrie lastTrie; 
     1013 
     1014                /** 
     1015                * default and minimum trained sequence length is 3 
     1016                */ 
     1017                private int trainedSequenceLength = 3; 
     1018 
     1019                /** 
    9421020         *  
    9431021         */ 
    944         private Tasks lastFoundTasks = new Tasks(Integer.MAX_VALUE, null); 
    945          
    946         /** 
     1022                private Tasks lastFoundTasks = new Tasks(Integer.MAX_VALUE, null); 
     1023 
     1024                /** 
    9471025         *  
    9481026         */ 
    949         private boolean detectedAndReplacedTasks; 
    950          
    951         /** 
     1027                private boolean detectedAndReplacedTasks; 
     1028 
     1029                /** 
    9521030         *  
    9531031         */ 
    954         private RuleApplicationResult result = new RuleApplicationResult(); 
    955          
    956         /** 
     1032                private RuleApplicationResult result = new RuleApplicationResult(); 
     1033 
     1034                /** 
    9571035         *  
    9581036         */ 
    959         private StopWatch stopWatch = new StopWatch(); 
    960          
    961         /** 
     1037                private StopWatch stopWatch = new StopWatch(); 
     1038 
     1039                /** 
    9621040         *  
    9631041         */ 
    964         private RuleApplicationData(List<IUserSession> sessions) { 
    965             this.sessions = sessions; 
    966         } 
    967  
    968         /** 
    969          * @return the tree 
    970          */ 
    971         private List<IUserSession> getSessions() { 
    972             return sessions; 
    973         } 
    974  
    975         /** 
    976          * @param lastTrie the lastTrie to set 
    977          */ 
    978         private void setLastTrie(TaskInstanceTrie lastTrie) { 
    979             this.lastTrie = lastTrie; 
    980         } 
    981  
    982         /** 
    983          * @return the lastTrie 
    984          */ 
    985         private TaskInstanceTrie getLastTrie() { 
    986             return lastTrie; 
    987         } 
    988  
    989         /** 
    990          * @param trainedSequenceLength the trainedSequenceLength to set 
    991          */ 
    992         private void setTrainedSequenceLength(int trainedSequenceLength) { 
    993             this.trainedSequenceLength = trainedSequenceLength; 
    994         } 
    995  
    996         /** 
    997          * @return the trainedSequenceLength 
    998          */ 
    999         private int getTrainedSequenceLength() { 
    1000             return trainedSequenceLength; 
    1001         } 
    1002  
    1003         /** 
    1004          * @param lastFoundSequences the lastFoundSequences to set 
    1005          */ 
    1006         private void setLastFoundTasks(Tasks lastFoundSequences) { 
    1007             this.lastFoundTasks = lastFoundSequences; 
    1008         } 
    1009  
    1010         /** 
    1011          * @return the lastFoundSequences 
    1012          */ 
    1013         private Tasks getLastFoundTasks() { 
    1014             return lastFoundTasks; 
    1015         } 
    1016  
    1017         /** 
     1042                private RuleApplicationData(List<IUserSession> sessions) { 
     1043                        this.sessions = sessions; 
     1044                } 
     1045 
     1046                /** 
     1047                 * @return the tree 
     1048                 */ 
     1049                private List<IUserSession> getSessions() { 
     1050                        return sessions; 
     1051                } 
     1052 
     1053                /** 
     1054                 * @param lastTrie 
     1055                 *            the lastTrie to set 
     1056                 */ 
     1057                private void setLastTrie(TaskInstanceTrie lastTrie) { 
     1058                        this.lastTrie = lastTrie; 
     1059                } 
     1060 
     1061                /** 
     1062                 * @return the lastTrie 
     1063                 */ 
     1064                private TaskInstanceTrie getLastTrie() { 
     1065                        return lastTrie; 
     1066                } 
     1067 
     1068                /** 
     1069                 * @param trainedSequenceLength 
     1070                 *            the trainedSequenceLength to set 
     1071                 */ 
     1072                private void setTrainedSequenceLength(int trainedSequenceLength) { 
     1073                        this.trainedSequenceLength = trainedSequenceLength; 
     1074                } 
     1075 
     1076                /** 
     1077                 * @return the trainedSequenceLength 
     1078                 */ 
     1079                private int getTrainedSequenceLength() { 
     1080                        return trainedSequenceLength; 
     1081                } 
     1082 
     1083                /** 
     1084                 * @param lastFoundSequences 
     1085                 *            the lastFoundSequences to set 
     1086                 */ 
     1087                private void setLastFoundTasks(Tasks lastFoundSequences) { 
     1088                        this.lastFoundTasks = lastFoundSequences; 
     1089                } 
     1090 
     1091                /** 
     1092                 * @return the lastFoundSequences 
     1093                 */ 
     1094                private Tasks getLastFoundTasks() { 
     1095                        return lastFoundTasks; 
     1096                } 
     1097 
     1098                /** 
    10181099         * 
    10191100         */ 
    1020         private void detectedAndReplacedTasks(boolean detectedAndReplacedTasks) { 
    1021             this.detectedAndReplacedTasks = detectedAndReplacedTasks; 
    1022         } 
    1023  
    1024         /** 
     1101                private void detectedAndReplacedTasks(boolean detectedAndReplacedTasks) { 
     1102                        this.detectedAndReplacedTasks = detectedAndReplacedTasks; 
     1103                } 
     1104 
     1105                /** 
    10251106         * 
    10261107         */ 
    1027         private boolean detectedAndReplacedTasks() { 
    1028             return detectedAndReplacedTasks; 
    1029         } 
    1030          
    1031         /** 
    1032          * @return the result 
    1033          */ 
    1034         private RuleApplicationResult getResult() { 
    1035             return result; 
    1036         } 
    1037  
    1038         /** 
    1039          * @return the stopWatch 
    1040          */ 
    1041         private StopWatch getStopWatch() { 
    1042             return stopWatch; 
    1043         } 
    1044  
    1045     } 
    1046      
    1047  
    1048     /** 
    1049      * @author Patrick Harms 
    1050      */ 
    1051     private static class Tasks implements Iterable<List<ITaskInstance>> { 
    1052          
    1053         /** 
     1108                private boolean detectedAndReplacedTasks() { 
     1109                        return detectedAndReplacedTasks; 
     1110                } 
     1111 
     1112                /** 
     1113                 * @return the result 
     1114                 */ 
     1115                private RuleApplicationResult getResult() { 
     1116                        return result; 
     1117                } 
     1118 
     1119                /** 
     1120                 * @return the stopWatch 
     1121                 */ 
     1122                private StopWatch getStopWatch() { 
     1123                        return stopWatch; 
     1124                } 
     1125 
     1126        } 
     1127 
     1128        /** 
     1129         * @author Patrick Harms 
     1130         */ 
     1131        private static class Tasks implements Iterable<List<ITaskInstance>> { 
     1132 
     1133                /** 
    10541134         *  
    10551135         */ 
    1056         private int occurrenceCount; 
    1057          
    1058         /** 
     1136                private int occurrenceCount; 
     1137 
     1138                /** 
    10591139         *  
    10601140         */ 
    1061         private List<List<ITaskInstance>> sequences; 
    1062  
    1063         /** 
    1064         * @param occurrenceCount 
    1065         * @param sequences 
    1066         */ 
    1067         private Tasks(int occurrenceCount, List<List<ITaskInstance>> sequences) { 
    1068             super(); 
    1069             this.occurrenceCount = occurrenceCount; 
    1070             this.sequences = sequences; 
    1071         } 
    1072  
    1073         /** 
    1074         * @return 
    1075         */ 
    1076         private int getOccurrenceCount() { 
    1077             return occurrenceCount; 
    1078         } 
    1079  
    1080         /** 
    1081         * @return 
    1082         */ 
    1083         private int size() { 
    1084             return this.sequences.size(); 
    1085         } 
    1086  
    1087         /** 
     1141                private List<List<ITaskInstance>> sequences; 
     1142 
     1143                /** 
     1144                * @param occurrenceCount 
     1145                * @param sequences 
     1146                */ 
     1147                private Tasks(int occurrenceCount, List<List<ITaskInstance>> sequences) { 
     1148                        super(); 
     1149                        this.occurrenceCount = occurrenceCount; 
     1150                        this.sequences = sequences; 
     1151                } 
     1152 
     1153                /** 
     1154                * @return 
     1155                */ 
     1156                private int getOccurrenceCount() { 
     1157                        return occurrenceCount; 
     1158                } 
     1159 
     1160                /** 
     1161                * @return 
     1162                */ 
     1163                private int size() { 
     1164                        return this.sequences.size(); 
     1165                } 
     1166 
     1167                /** 
    10881168         *  
    10891169         */ 
    10901170 
    1091         /* (non-Javadoc) 
    1092          * @see java.lang.Iterable#iterator() 
    1093          */ 
    1094         @Override 
    1095         public Iterator<List<ITaskInstance>> iterator() { 
    1096             return this.sequences.iterator(); 
    1097         } 
    1098  
    1099         /* (non-Javadoc) 
    1100          * @see java.lang.Object#toString() 
    1101          */ 
    1102         @Override 
    1103         public String toString() { 
    1104             StringBuffer result = new StringBuffer(); 
    1105             result.append(this.occurrenceCount); 
    1106             result.append(" occurrences:\n"); 
    1107              
    1108             for (List<ITaskInstance> task : sequences) { 
    1109                 result.append(task); 
    1110                 result.append("\n"); 
    1111             } 
    1112              
    1113             return result.toString(); 
    1114         } 
    1115  
    1116     } 
    1117      
    1118     // methods for internal testing 
    1119 //    private void checkMatchingOfSessions(List<List<Event>>  flattenedSessions, 
    1120 //                                         List<IUserSession> sessions, 
    1121 //                                         String             when) 
    1122 //    { 
    1123 //        List<List<Event>> currentFlattenedSessions = flattenSessions(sessions); 
    1124 //        if (flattenedSessions.size() != currentFlattenedSessions.size()) { 
    1125 //            System.out.println("################## number of sessions changed after " + when); 
    1126 //        } 
    1127 //        else { 
    1128 //            for (int i = 0; i < flattenedSessions.size(); i++) { 
    1129 //                List<Event> expected = flattenedSessions.get(i); 
    1130 //                List<Event> current = currentFlattenedSessions.get(i); 
    1131 //             
    1132 //                if (expected.size() != current.size()) { 
    1133 //                    System.out.println 
    1134 //                        ("################## length of session " + i + " changed after " + when); 
    1135 //                } 
    1136 //                else { 
    1137 //                    for (int j = 0; j < expected.size(); j++) { 
    1138 //                        if (!expected.get(j).equals(current.get(j))) { 
    1139 //                            System.out.println("################## event " + j + " of session " + 
    1140 //                                               i + " changed after " + when); 
    1141 //                        } 
    1142 //                    } 
    1143 //                } 
    1144 //            }      
    1145 //        } 
    1146 //    } 
    1147 // 
    1148 //    private List<List<Event>> flattenSessions(List<IUserSession> sessions) { 
    1149 //        List<List<Event>> flattenedSessions = new ArrayList<List<Event>>(); 
    1150 //        for (IUserSession session : sessions) { 
    1151 //            List<Event> flattenedUserSession = new ArrayList<Event>(); 
    1152 //            flatten(session, flattenedUserSession); 
    1153 //            flattenedSessions.add(flattenedUserSession); 
    1154 //        } 
    1155 // 
    1156 //        return flattenedSessions; 
    1157 //    } 
    1158 // 
    1159 //    private void flatten(IUserSession iUserSession, List<Event> flattenedUserSession) { 
    1160 //        for (ITaskInstance instance : iUserSession) { 
    1161 //            flatten(instance, flattenedUserSession); 
    1162 //        } 
    1163 //    } 
    1164 // 
    1165 //    private void flatten(ITaskInstance instance, List<Event> flattenedUserSession) { 
    1166 //        if (instance instanceof ITaskInstanceList) { 
    1167 //            for (ITaskInstance child : (ITaskInstanceList) instance) { 
    1168 //                flatten(child, flattenedUserSession); 
    1169 //            } 
    1170 //        } 
    1171 //        else if (instance instanceof ISelectionInstance) { 
    1172 //            flatten(((ISelectionInstance) instance).getChild(), flattenedUserSession); 
    1173 //        } 
    1174 //        else if (instance instanceof IOptionalInstance) { 
    1175 //            flatten(((IOptionalInstance) instance).getChild(), flattenedUserSession); 
    1176 //        } 
    1177 //        else if (instance instanceof IEventTaskInstance) { 
    1178 //            flattenedUserSession.add(((IEventTaskInstance) instance).getEvent()); 
    1179 //        } 
    1180 //    } 
     1171                /* 
     1172                 * (non-Javadoc) 
     1173                 *  
     1174                 * @see java.lang.Iterable#iterator() 
     1175                 */ 
     1176                @Override 
     1177                public Iterator<List<ITaskInstance>> iterator() { 
     1178                        return this.sequences.iterator(); 
     1179                } 
     1180 
     1181                /* 
     1182                 * (non-Javadoc) 
     1183                 *  
     1184                 * @see java.lang.Object#toString() 
     1185                 */ 
     1186                @Override 
     1187                public String toString() { 
     1188                        StringBuffer result = new StringBuffer(); 
     1189                        result.append(this.occurrenceCount); 
     1190                        result.append(" occurrences:\n"); 
     1191 
     1192                        for (List<ITaskInstance> task : sequences) { 
     1193                                result.append(task); 
     1194                                result.append("\n"); 
     1195                        } 
     1196 
     1197                        return result.toString(); 
     1198                } 
     1199 
     1200        } 
     1201 
     1202        // methods for internal testing 
     1203        // private void checkMatchingOfSessions(List<List<Event>> flattenedSessions, 
     1204        // List<IUserSession> sessions, 
     1205        // String when) 
     1206        // { 
     1207        // List<List<Event>> currentFlattenedSessions = flattenSessions(sessions); 
     1208        // if (flattenedSessions.size() != currentFlattenedSessions.size()) { 
     1209        // System.out.println("################## number of sessions changed after " 
     1210        // + when); 
     1211        // } 
     1212        // else { 
     1213        // for (int i = 0; i < flattenedSessions.size(); i++) { 
     1214        // List<Event> expected = flattenedSessions.get(i); 
     1215        // List<Event> current = currentFlattenedSessions.get(i); 
     1216        // 
     1217        // if (expected.size() != current.size()) { 
     1218        // System.out.println 
     1219        // ("################## length of session " + i + " changed after " + when); 
     1220        // } 
     1221        // else { 
     1222        // for (int j = 0; j < expected.size(); j++) { 
     1223        // if (!expected.get(j).equals(current.get(j))) { 
     1224        // System.out.println("################## event " + j + " of session " + 
     1225        // i + " changed after " + when); 
     1226        // } 
     1227        // } 
     1228        // } 
     1229        // } 
     1230        // } 
     1231        // } 
     1232        // 
     1233        // private List<List<Event>> flattenSessions(List<IUserSession> sessions) { 
     1234        // List<List<Event>> flattenedSessions = new ArrayList<List<Event>>(); 
     1235        // for (IUserSession session : sessions) { 
     1236        // List<Event> flattenedUserSession = new ArrayList<Event>(); 
     1237        // flatten(session, flattenedUserSession); 
     1238        // flattenedSessions.add(flattenedUserSession); 
     1239        // } 
     1240        // 
     1241        // return flattenedSessions; 
     1242        // } 
     1243        // 
     1244        // private void flatten(IUserSession iUserSession, List<Event> 
     1245        // flattenedUserSession) { 
     1246        // for (ITaskInstance instance : iUserSession) { 
     1247        // flatten(instance, flattenedUserSession); 
     1248        // } 
     1249        // } 
     1250        // 
     1251        // private void flatten(ITaskInstance instance, List<Event> 
     1252        // flattenedUserSession) { 
     1253        // if (instance instanceof ITaskInstanceList) { 
     1254        // for (ITaskInstance child : (ITaskInstanceList) instance) { 
     1255        // flatten(child, flattenedUserSession); 
     1256        // } 
     1257        // } 
     1258        // else if (instance instanceof ISelectionInstance) { 
     1259        // flatten(((ISelectionInstance) instance).getChild(), 
     1260        // flattenedUserSession); 
     1261        // } 
     1262        // else if (instance instanceof IOptionalInstance) { 
     1263        // flatten(((IOptionalInstance) instance).getChild(), flattenedUserSession); 
     1264        // } 
     1265        // else if (instance instanceof IEventTaskInstance) { 
     1266        // flattenedUserSession.add(((IEventTaskInstance) instance).getEvent()); 
     1267        // } 
     1268        // } 
    11811269 
    11821270} 
Note: See TracChangeset for help on using the changeset viewer.