Changeset 1733
- Timestamp:
- 09/05/14 19:33:12 (10 years ago)
- Location:
- branches/autoquest-core-tasktrees-alignment
- Files:
-
- 1 added
- 95 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/Alignment.java
r1593 r1733 5 5 public class Alignment { 6 6 ArrayList<NumberSequence> alingment; 7 8 7 9 8 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/AlignmentAlgorithm.java
r1649 r1733 6 6 7 7 public interface AlignmentAlgorithm { 8 8 9 void align(NumberSequence input1, NumberSequence input2, 10 SubstitutionMatrix submat, float threshold); 11 12 public abstract ArrayList<NumberSequence> getAlignment(); 13 9 14 /** 10 15 * Get the alignment score between the two input strings. … … 12 17 public abstract double getAlignmentScore(); 13 18 14 public abstract ArrayList<NumberSequence> getAlignment(); 19 public abstract ArrayList<Match> getMatches(); 20 21 public double getMaxScore(); 22 23 public abstract void printAlignment(); 15 24 16 25 public abstract void printDPMatrix(); 17 26 18 public abstract void printAlignment();19 20 public abstract ArrayList<Match> getMatches();21 22 public double getMaxScore();23 24 void align(NumberSequence input1, NumberSequence input2,25 SubstitutionMatrix submat, float threshold);26 27 27 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/AlignmentAlgorithmFactory.java
r1616 r1733 1 1 package de.ugoe.cs.autoquest.tasktrees.alignment.algorithms; 2 2 3 public class AlignmentAlgorithmFactory { 3 4 4 public class AlignmentAlgorithmFactory {5 6 public static void setDefaultAlgorithm(String algorithmname) {7 //TODO: check for valid algorihm class names here8 algorithmclass = algorithmname;9 }10 11 private static String algorithmclass = "de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.SmithWatermanRepeated";12 13 14 15 5 public static AlignmentAlgorithm create() { 16 6 Class<?> newclass; 17 7 Object object = null; 18 8 try { 19 newclass = Class.forName(algorithmclass); 20 object = newclass.newInstance(); 21 22 } catch (ClassNotFoundException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException e) { 9 newclass = Class.forName(algorithmclass); 10 object = newclass.newInstance(); 11 12 } catch (ClassNotFoundException | SecurityException 13 | InstantiationException | IllegalAccessException 14 | IllegalArgumentException e) { 23 15 e.printStackTrace(); 24 16 } 25 17 return (AlignmentAlgorithm) object; 26 18 } 19 20 public static void setDefaultAlgorithm(String algorithmname) { 21 // TODO: check for valid algorihm class names here 22 algorithmclass = algorithmname; 23 } 24 25 private static String algorithmclass = "de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.SmithWatermanRepeated"; 27 26 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/AlignmentHelpers.java
r1553 r1733 7 7 import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement; 8 8 9 public class AlignmentHelpers extends GUIModel { 9 10 10 public class AlignmentHelpers extends GUIModel { 11 11 public static int distanceBetween(IGUIElement first, IGUIElement second) { 12 12 13 14 /** 15 * 16 */ 17 private static final long serialVersionUID = -2593092958275693133L; 13 int hopcount1 = 0; 14 int hopcount2 = 0; 15 final List<IGUIElement> tmp = new ArrayList<IGUIElement>(); 16 tmp.add(first); 17 tmp.add(second); 18 final IGUIElement commonDenominator = getCommonDenominator(tmp); 19 20 while (!(first.equals(commonDenominator))) { 21 first = first.getParent(); 22 hopcount1++; 23 } 24 25 while (!(second.equals(commonDenominator))) { 26 second = second.getParent(); 27 hopcount2++; 28 } 29 30 return hopcount1 + hopcount2; 31 } 18 32 19 33 /** … … 24 38 * </p> 25 39 */ 26 private static IGUIElement getCommonDenominator(List<IGUIElement> guiElements) { 40 private static IGUIElement getCommonDenominator( 41 List<IGUIElement> guiElements) { 27 42 IGUIElement commonDenominator = null; 28 43 29 44 if (guiElements.size() > 0) { 30 List<IGUIElement> commonDenominatorPath = new ArrayList<IGUIElement>();45 final List<IGUIElement> commonDenominatorPath = new ArrayList<IGUIElement>(); 31 46 32 47 // create a reference list using the first GUI element … … 49 64 // well as it subsequent 50 65 // siblings 51 List<IGUIElement> currentPath = new ArrayList<IGUIElement>();66 final List<IGUIElement> currentPath = new ArrayList<IGUIElement>(); 52 67 for (int i = 1; i < guiElements.size(); i++) { 53 68 currentPath.clear(); … … 55 70 while (guiElement != null) { 56 71 // if (guiElementMatchesConsideredTypes(guiElement)) { 57 72 currentPath.add(0, guiElement); 58 73 // } 59 74 guiElement = guiElement.getParent(); … … 84 99 } 85 100 86 public static int distanceBetween(IGUIElement first, IGUIElement second) { 87 88 int hopcount1 = 0; 89 int hopcount2 = 0; 90 List<IGUIElement> tmp = new ArrayList<IGUIElement>(); 91 tmp.add(first); 92 tmp.add(second); 93 IGUIElement commonDenominator = getCommonDenominator(tmp); 94 95 while(!(first.equals(commonDenominator))) { 96 first = first.getParent(); 97 hopcount1++; 98 } 99 100 while(!(second.equals(commonDenominator))) { 101 second = second.getParent(); 102 hopcount2++; 103 } 104 105 return hopcount1 + hopcount2; 106 } 101 /** 102 * 103 */ 104 private static final long serialVersionUID = -2593092958275693133L; 107 105 108 106 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/Constants.java
r1578 r1733 2 2 3 3 public class Constants { 4 4 5 5 public static final int GAP_SYMBOL = -1; 6 6 public static final int UNMATCHED_SYMBOL = -2; -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/Match.java
r1717 r1733 5 5 import java.util.LinkedList; 6 6 7 8 9 public class Match implements Serializable{ 7 public class Match implements Serializable { 10 8 /** 11 9 * … … 13 11 private static final long serialVersionUID = -3206992723755714741L; 14 12 15 private ArrayList<NumberSequence> matchseqs;13 private final ArrayList<NumberSequence> matchseqs; 16 14 17 15 private LinkedList<MatchOccurence> occurences; … … 24 22 } 25 23 26 public NumberSequence getFirstSequence() {27 return matchseqs.get(0);28 }29 30 public NumberSequence getSecondSequence() {31 return matchseqs.get(1);32 }33 34 public void setFirstSequence(NumberSequence seq) {35 matchseqs.set(0, seq);36 }37 38 public void setSecondSequence(NumberSequence seq) {39 matchseqs.set(1, seq);40 }41 42 24 public void addOccurence(MatchOccurence occurence) { 43 25 occurences.add(occurence); 44 26 } 45 27 46 public int occurenceCount() { 47 return occurences.size(); 48 } 49 50 public int size() { 51 //Both sequences should be equally long 52 return matchseqs.get(0).size(); 28 public void addOccurencesOf(Match m) { 29 occurences.addAll(m.getOccurences()); 53 30 } 54 31 … … 63 40 } 64 41 42 public NumberSequence getFirstSequence() { 43 return matchseqs.get(0); 44 } 45 65 46 public LinkedList<MatchOccurence> getOccurences() { 66 47 return occurences; 48 } 49 50 public NumberSequence getSecondSequence() { 51 return matchseqs.get(1); 52 } 53 54 public int occurenceCount() { 55 return occurences.size(); 56 } 57 58 public void setFirstSequence(NumberSequence seq) { 59 matchseqs.set(0, seq); 67 60 } 68 61 … … 71 64 } 72 65 73 74 public void addOccurencesOf(Match m) { 75 occurences.addAll(m.getOccurences()); 66 public void setSecondSequence(NumberSequence seq) { 67 matchseqs.set(1, seq); 76 68 } 77 78 79 69 70 public int size() { 71 // Both sequences should be equally long 72 return matchseqs.get(0).size(); 73 } 80 74 81 75 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/MatchOccurence.java
r1717 r1733 3 3 import java.io.Serializable; 4 4 5 public class MatchOccurence implements Serializable {5 public class MatchOccurence implements Serializable { 6 6 /** 7 7 * … … 11 11 private int endindex; 12 12 private int sequenceId; 13 13 14 14 public MatchOccurence(int startindex, int endindex, int sequenceId) { 15 15 this.startindex = startindex; … … 17 17 this.sequenceId = sequenceId; 18 18 } 19 19 20 20 public int getEndindex() { 21 21 return endindex; 22 } 23 24 public int getSequenceId() { 25 return sequenceId; 26 } 27 28 public int getStartindex() { 29 return startindex; 22 30 } 23 31 … … 26 34 } 27 35 28 public int getStartindex() {29 return startindex;36 public void setSequenceId(int sequenceId) { 37 this.sequenceId = sequenceId; 30 38 } 39 31 40 public void setStartindex(int startindex) { 32 41 this.startindex = startindex; 33 42 } 34 public int getSequenceId() {35 return sequenceId;36 }37 38 public void setSequenceId(int sequenceId) {39 this.sequenceId = sequenceId;40 }41 43 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/MatrixEntry.java
r1568 r1733 6 6 private int xvalue; 7 7 private int yvalue; 8 9 public MatrixEntry(float score, MatrixEntry previous) { 8 9 public MatrixEntry() { 10 } 11 12 public MatrixEntry(float score, MatrixEntry previous) { 10 13 this.score = score; 11 14 this.previous = previous; 12 15 } 13 14 public MatrixEntry() { 16 17 public MatrixEntry getPrevious() { 18 return previous; 15 19 } 16 20 17 21 public double getScore() { 18 22 return score; 19 }20 public void setScore(double score) {21 this.score = score;22 }23 public MatrixEntry getPrevious() {24 return previous;25 }26 public void setPrevious(MatrixEntry previous) {27 this.previous = previous;28 23 } 29 24 … … 32 27 } 33 28 29 public int getYvalue() { 30 return yvalue; 31 } 32 33 public void setPrevious(MatrixEntry previous) { 34 this.previous = previous; 35 } 36 37 public void setScore(double score) { 38 this.score = score; 39 } 40 34 41 public void setXvalue(int xvalue) { 35 42 this.xvalue = xvalue; 36 }37 38 public int getYvalue() {39 return yvalue;40 43 } 41 44 -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/NeedlemanWunsch.java
r1620 r1733 8 8 import de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.Constants; 9 9 10 11 10 public class NeedlemanWunsch implements AlignmentAlgorithm { 12 11 … … 39 38 private SubstitutionMatrix submat; 40 39 40 @Override 41 public void align(NumberSequence input1, NumberSequence input2, 42 SubstitutionMatrix submat, float threshold) { 43 this.input1 = input1.getSequence(); 44 this.input2 = input2.getSequence(); 45 length1 = input1.size(); 46 length2 = input2.size(); 47 this.submat = submat; 48 49 // System.out.println("Starting SmithWaterman algorithm with a " 50 // + submat.getClass() + " Substitution Matrix: " + 51 // submat.getClass().getCanonicalName()); 52 53 matrix = new MatrixEntry[length1 + 1][length2 + 1]; 54 alignment = new ArrayList<NumberSequence>(); 55 56 for (int i = 0; i < (length1 + 1); i++) { 57 for (int j = 0; j < (length2 + 1); j++) { 58 matrix[i][j] = new MatrixEntry(); 59 } 60 } 61 62 buildMatrix(); 63 traceback(); 64 65 } 66 67 /** 68 * Build the score matrix using dynamic programming. 69 */ 70 private void buildMatrix() { 71 if (submat.getGapPenalty() >= 0) { 72 throw new Error("Indel score must be negative"); 73 } 74 75 // it's a gap 76 matrix[0][0].setScore(0); 77 matrix[0][0].setPrevious(null); // starting point 78 79 // the first column 80 for (int j = 1; j <= length2; j++) { 81 matrix[0][j].setScore(j * submat.getGapPenalty()); 82 matrix[0][j].setPrevious(matrix[0][j - 1]); 83 matrix[0][j].setYvalue(input2[j - 1]); 84 matrix[0][j].setXvalue(Constants.GAP_SYMBOL); 85 } 86 // the first row 87 88 for (int j = 1; j <= length1; j++) { 89 matrix[j][0].setScore(j * submat.getGapPenalty()); 90 matrix[j][0].setPrevious(matrix[j - 1][0]); 91 matrix[j][0].setXvalue(input1[j - 1]); 92 matrix[j][0].setYvalue(Constants.GAP_SYMBOL); 93 } 94 95 for (int i = 1; i <= length1; i++) { 96 97 for (int j = 1; j <= length2; j++) { 98 final double diagScore = matrix[i - 1][j - 1].getScore() 99 + similarity(i, j); 100 final double upScore = matrix[i][j - 1].getScore() 101 + submat.getGapPenalty(); 102 final double leftScore = matrix[i - 1][j].getScore() 103 + submat.getGapPenalty(); 104 105 matrix[i][j].setScore(Math.max(diagScore, 106 Math.max(upScore, leftScore))); 107 108 // find the directions that give the maximum scores. 109 // TODO: Multiple directions are ignored, we choose the first 110 // maximum score 111 // True if we had a match 112 if (diagScore == matrix[i][j].getScore()) { 113 matrix[i][j].setPrevious(matrix[i - 1][j - 1]); 114 matrix[i][j].setXvalue(input1[i - 1]); 115 matrix[i][j].setYvalue(input2[j - 1]); 116 } 117 // true if we took an event from sequence x and not from y 118 if (leftScore == matrix[i][j].getScore()) { 119 matrix[i][j].setXvalue(input1[i - 1]); 120 matrix[i][j].setYvalue(Constants.GAP_SYMBOL); 121 matrix[i][j].setPrevious(matrix[i - 1][j]); 122 } 123 // true if we took an event from sequence y and not from x 124 if (upScore == matrix[i][j].getScore()) { 125 matrix[i][j].setXvalue(Constants.GAP_SYMBOL); 126 matrix[i][j].setYvalue(input2[j - 1]); 127 matrix[i][j].setPrevious(matrix[i][j - 1]); 128 } 129 } 130 } 131 } 132 133 /* 134 * (non-Javadoc) 135 * 136 * @see 137 * de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.AlignmentAlgorithm 138 * #getAlignment() 139 */ 140 @Override 141 public ArrayList<NumberSequence> getAlignment() { 142 return alignment; 143 } 144 145 /* 146 * (non-Javadoc) 147 * 148 * @see 149 * de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.AlignmentAlgorithm 150 * #getAlignmentScore() 151 */ 152 @Override 153 public double getAlignmentScore() { 154 return getMaxScore(); 155 } 156 157 @Override 158 public ArrayList<Match> getMatches() { 159 // TODO Auto-generated method stub 160 return null; 161 } 162 163 /** 164 * Get the maximum value in the score matrix. 165 */ 166 @Override 167 public double getMaxScore() { 168 double maxScore = 0; 169 170 // skip the first row and column 171 for (int i = 1; i <= length1; i++) { 172 for (int j = 1; j <= length2; j++) { 173 if (matrix[i][j].getScore() > maxScore) { 174 maxScore = matrix[i][j].getScore(); 175 } 176 } 177 } 178 179 return maxScore; 180 } 181 182 @Override 183 public void printAlignment() { 184 final int[] tmp1 = alignment.get(0).getSequence(); 185 final int[] tmp2 = alignment.get(1).getSequence(); 186 for (int i = 0; i < tmp1.length; i++) { 187 if (tmp1[i] == Constants.GAP_SYMBOL) { 188 System.out.print(" ___"); 189 } else if (tmp1[i] == Constants.UNMATCHED_SYMBOL) { 190 System.out.print(" ..."); 191 } else { 192 System.out.format("%5d", tmp1[i]); 193 } 194 195 } 196 System.out.println(); 197 for (int i = 0; i < tmp2.length; i++) { 198 if (tmp2[i] == Constants.GAP_SYMBOL) { 199 System.out.print(" ___"); 200 } else if (tmp2[i] == Constants.UNMATCHED_SYMBOL) { 201 System.out.print(" ..."); 202 } else { 203 System.out.format("%5d", tmp2[i]); 204 } 205 206 } 207 System.out.println(); 208 209 } 210 211 /** 212 * print the dynmaic programming matrix 213 */ 214 @Override 215 public void printDPMatrix() { 216 System.out.print(" "); 217 for (int i = 1; i <= length1; i++) { 218 System.out.format("%5d", input1[i - 1]); 219 } 220 System.out.println(); 221 for (int j = 0; j <= length2; j++) { 222 if (j > 0) { 223 System.out.format("%5d ", input2[j - 1]); 224 } else { 225 System.out.print(" "); 226 } 227 for (int i = 0; i <= length1; i++) { 228 System.out.format("%4.1f ", matrix[i][j].getScore()); 229 } 230 System.out.println(); 231 } 232 } 233 234 public void setAlignment(ArrayList<NumberSequence> alignment) { 235 this.alignment = alignment; 236 } 41 237 42 238 /** … … 54 250 } 55 251 56 /**57 * Build the score matrix using dynamic programming.58 */59 private void buildMatrix() {60 if (submat.getGapPenalty() >= 0) {61 throw new Error("Indel score must be negative");62 }63 64 // it's a gap65 matrix[0][0].setScore(0);66 matrix[0][0].setPrevious(null); // starting point67 68 // the first column69 for (int j = 1; j <= length2; j++) {70 matrix[0][j].setScore(j*submat.getGapPenalty());71 matrix[0][j].setPrevious(matrix[0][j - 1]);72 matrix[0][j].setYvalue(input2[j-1]);73 matrix[0][j].setXvalue(Constants.GAP_SYMBOL);74 }75 // the first row76 77 for (int j = 1; j <= length1; j++) {78 matrix[j][0].setScore(j*submat.getGapPenalty());79 matrix[j][0].setPrevious(matrix[j - 1][0]);80 matrix[j][0].setXvalue(input1[j-1]);81 matrix[j][0].setYvalue(Constants.GAP_SYMBOL);82 }83 84 for (int i = 1; i <= length1; i++) {85 86 for (int j = 1; j <= length2; j++) {87 double diagScore = matrix[i - 1][j - 1].getScore()88 + similarity(i, j);89 double upScore = matrix[i][j - 1].getScore()90 + submat.getGapPenalty();91 double leftScore = matrix[i - 1][j].getScore()92 + submat.getGapPenalty();93 94 matrix[i][j].setScore(Math.max(diagScore,95 Math.max(upScore, leftScore)));96 97 // find the directions that give the maximum scores.98 // TODO: Multiple directions are ignored, we choose the first99 // maximum score100 // True if we had a match101 if (diagScore == matrix[i][j].getScore()) {102 matrix[i][j].setPrevious(matrix[i - 1][j - 1]);103 matrix[i][j].setXvalue(input1[i - 1]);104 matrix[i][j].setYvalue(input2[j - 1]);105 }106 // true if we took an event from sequence x and not from y107 if (leftScore == matrix[i][j].getScore()) {108 matrix[i][j].setXvalue(input1[i - 1]);109 matrix[i][j].setYvalue(Constants.GAP_SYMBOL);110 matrix[i][j].setPrevious(matrix[i - 1][j]);111 }112 // true if we took an event from sequence y and not from x113 if (upScore == matrix[i][j].getScore()) {114 matrix[i][j].setXvalue(Constants.GAP_SYMBOL);115 matrix[i][j].setYvalue(input2[j - 1]);116 matrix[i][j].setPrevious(matrix[i][j - 1]);117 }118 }119 }120 }121 122 /**123 * Get the maximum value in the score matrix.124 */125 public double getMaxScore() {126 double maxScore = 0;127 128 // skip the first row and column129 for (int i = 1; i <= length1; i++) {130 for (int j = 1; j <= length2; j++) {131 if (matrix[i][j].getScore() > maxScore) {132 maxScore = matrix[i][j].getScore();133 }134 }135 }136 137 return maxScore;138 }139 140 /*141 * (non-Javadoc)142 *143 * @see144 * de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.AlignmentAlgorithm145 * #getAlignmentScore()146 */147 @Override148 public double getAlignmentScore() {149 return getMaxScore();150 }151 152 252 public void traceback() { 153 253 MatrixEntry tmp = matrix[length1][length2]; 154 LinkedList<Integer> aligned1 = new LinkedList<Integer>();155 LinkedList<Integer> aligned2 = new LinkedList<Integer>();254 final LinkedList<Integer> aligned1 = new LinkedList<Integer>(); 255 final LinkedList<Integer> aligned2 = new LinkedList<Integer>(); 156 256 while (tmp.getPrevious() != null) { 157 257 158 258 aligned1.add(new Integer(tmp.getXvalue())); 159 259 aligned2.add(new Integer(tmp.getYvalue())); 160 260 161 261 tmp = tmp.getPrevious(); 162 } 163 262 } 263 164 264 // reverse order of the alignment 165 int reversed1[] = new int[aligned1.size()];166 int reversed2[] = new int[aligned2.size()];265 final int reversed1[] = new int[aligned1.size()]; 266 final int reversed2[] = new int[aligned2.size()]; 167 267 168 268 int count = 0; 169 for ( Iterator<Integer> it = aligned1.iterator(); it.hasNext();) {269 for (final Iterator<Integer> it = aligned1.iterator(); it.hasNext();) { 170 270 count++; 171 271 reversed1[reversed1.length - count] = it.next(); 172 272 173 273 } 174 274 count = 0; 175 for ( Iterator<Integer> it = aligned2.iterator(); it.hasNext();) {275 for (final Iterator<Integer> it = aligned2.iterator(); it.hasNext();) { 176 276 count++; 177 277 reversed2[reversed2.length - count] = it.next(); 178 278 } 179 279 180 NumberSequence ns1 = new NumberSequence(reversed1.length);181 NumberSequence ns2 = new NumberSequence(reversed2.length);280 final NumberSequence ns1 = new NumberSequence(reversed1.length); 281 final NumberSequence ns2 = new NumberSequence(reversed2.length); 182 282 ns1.setSequence(reversed1); 183 283 ns2.setSequence(reversed2); … … 187 287 } 188 288 189 190 /**191 * print the dynmaic programming matrix192 */193 public void printDPMatrix() {194 System.out.print(" ");195 for (int i = 1; i <= length1; i++)196 System.out.format("%5d", input1[i - 1]);197 System.out.println();198 for (int j = 0; j <= length2; j++) {199 if (j > 0)200 System.out.format("%5d ", input2[j - 1]);201 else {202 System.out.print(" ");203 }204 for (int i = 0; i <= length1; i++) {205 System.out.format("%4.1f ", matrix[i][j].getScore());206 }207 System.out.println();208 }209 }210 211 public void printAlignment() {212 int[] tmp1 = alignment.get(0).getSequence();213 int[] tmp2 = alignment.get(1).getSequence();214 for (int i=0; i< tmp1.length;i++) {215 if(tmp1[i] == Constants.GAP_SYMBOL) {216 System.out.print(" ___");217 }218 else if(tmp1[i] == Constants.UNMATCHED_SYMBOL) {219 System.out.print(" ...");220 }221 else {222 System.out.format("%5d", tmp1[i]);223 }224 225 }226 System.out.println();227 for (int i=0; i< tmp2.length;i++) {228 if(tmp2[i] == Constants.GAP_SYMBOL) {229 System.out.print(" ___");230 }231 else if(tmp2[i] == Constants.UNMATCHED_SYMBOL) {232 System.out.print(" ...");233 }234 else {235 System.out.format("%5d", tmp2[i]);236 }237 238 }239 System.out.println();240 241 242 243 }244 245 /*246 * (non-Javadoc)247 *248 * @see249 * de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.AlignmentAlgorithm250 * #getAlignment()251 */252 @Override253 public ArrayList<NumberSequence> getAlignment() {254 return alignment;255 }256 257 public void setAlignment(ArrayList<NumberSequence> alignment) {258 this.alignment = alignment;259 }260 261 @Override262 public ArrayList<Match> getMatches() {263 // TODO Auto-generated method stub264 return null;265 }266 267 @Override268 public void align(NumberSequence input1, NumberSequence input2, SubstitutionMatrix submat,269 float threshold) {270 this.input1 = input1.getSequence();271 this.input2 = input2.getSequence();272 length1 = input1.size();273 length2 = input2.size();274 this.submat = submat;275 276 // System.out.println("Starting SmithWaterman algorithm with a "277 // + submat.getClass() + " Substitution Matrix: " +278 // submat.getClass().getCanonicalName());279 280 matrix = new MatrixEntry[length1 + 1][length2 + 1];281 alignment = new ArrayList<NumberSequence>();282 283 for (int i = 0; i < length1+1; i++) {284 for (int j = 0; j < length2+1; j++) {285 matrix[i][j] = new MatrixEntry();286 }287 }288 289 buildMatrix();290 traceback();291 292 }293 294 295 296 289 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/NumberSequence.java
r1717 r1733 5 5 import java.util.Random; 6 6 7 public class NumberSequence implements Serializable {7 public class NumberSequence implements Serializable { 8 8 /** 9 9 * … … 18 18 } 19 19 20 public int[] getSequence() { 21 return sequence; 22 } 20 // Searching occurrences of pattern 21 public LinkedList<Integer> containsPattern(Match pattern) { 22 final LinkedList<Integer> result = new LinkedList<Integer>(); 23 int i = 0; 24 final int[] pat1 = pattern.getFirstSequence().getSequence(); 25 final int[] pat2 = pattern.getSecondSequence().getSequence(); 23 26 24 public void setSequence(int[] sequence) { 25 this.sequence = sequence; 26 } 27 28 public void printSequence() { 29 for (int i = 0; i < sequence.length; i++) { 30 System.out.format("%5d", sequence[i]); 31 } 32 System.out.println(); 33 } 34 35 public NumberSequence shuffle() { 36 NumberSequence result = new NumberSequence(sequence.length); 37 result.setId(getId()); 38 result.setSequence(this.sequence); 39 Random rgen = new Random(); 40 41 for (int i = 0; i < result.sequence.length; i++) { 42 int randomPosition = rgen.nextInt(result.sequence.length); 43 int temp = result.sequence[i]; 44 result.sequence[i] = result.sequence[randomPosition]; 45 result.sequence[randomPosition] = temp; 46 } 47 return result; 48 49 } 50 51 //Recursive check if sequence contains pattern at position i 52 private boolean matches(int i, 53 int[] p1, 54 int[] p2 , 55 int ip1, 56 int ip2, 57 boolean jumped1, //True if there was a gap in Sequence 1 of the pattern 58 boolean jumped2, //True if there was a gap in Sequence 2 of the pattern 59 boolean hadSelection, //True if the last match was a selection 60 boolean matchseq1, 61 boolean matchseq2) { 62 63 if(p1.length==ip1) { 64 return true; 65 } 66 if(p2.length==ip2) { 67 return true; 68 } 69 if(i==sequence.length) { 70 return false; 71 } 72 73 boolean foundselection=(!(p1[ip1] == p2[ip2])&&!(p1[ip1]==-1||p2[ip2]==-1)); 74 boolean matchInFirstPattern = (p1[ip1]==sequence[i]); 75 boolean matchInSecondPattern = (p2[ip2]==sequence[i]); 76 77 if(foundselection && hadSelection) { 78 if((matchInFirstPattern && matchseq1) || (matchInSecondPattern && matchseq2)){ 79 if(jumped1) { 80 return matches(i+1,p1,p2,ip1+1,ip2+2,false,false,foundselection,matchInFirstPattern,matchInSecondPattern); 81 } 82 if(jumped2) { 83 return matches(i+1,p1,p2,ip1+2,ip2+1,false,false,foundselection,matchInFirstPattern,matchInSecondPattern); 84 } 85 return matches(i+1,p1,p2,ip1+1,ip2+1,false,false,foundselection,matchInFirstPattern,matchInSecondPattern); 86 } 87 else { 88 return false; 89 } 90 } 91 92 if((matchInFirstPattern||matchInSecondPattern) && jumped1) { 93 return matches(i+1,p1,p2,ip1+1,ip2+2,false,false,foundselection,matchInFirstPattern,matchInSecondPattern); 94 } 95 if((matchInFirstPattern||matchInSecondPattern) && jumped2) { 96 return matches(i+1,p1,p2,ip1+2,ip2+1,false,false,foundselection,matchInFirstPattern,matchInSecondPattern); 97 } 98 if(matchInFirstPattern||matchInSecondPattern) { 99 return matches(i+1,p1,p2,ip1+1,ip2+1,false,false,foundselection,matchInFirstPattern,matchInSecondPattern); 100 } 101 if(p1[ip1]==-1) { 102 return matches(i,p1,p2,ip1+1,ip2,true,false,false,false,false); 103 } 104 if(p2[ip2]==-1) { 105 return matches(i,p1,p2,ip1,ip2+1,false,true,false,false,false); 106 } 107 108 return false; 109 } 110 111 //Searching occurrences of pattern 112 public LinkedList<Integer> containsPattern(Match pattern) { 113 LinkedList<Integer> result = new LinkedList<Integer>(); 114 int i = 0; 115 int[] pat1 = pattern.getFirstSequence().getSequence(); 116 int[] pat2 = pattern.getSecondSequence().getSequence(); 117 118 while (i < sequence.length ) { 119 if(matches(i,pat1,pat2,0,0,false,false,false,false,false)) { 27 while (i < sequence.length) { 28 if (matches(i, pat1, pat2, 0, 0, false, false, false, false, false)) { 120 29 result.add(i); 121 30 } … … 123 32 } 124 33 return result; 34 } 35 36 public boolean equals(NumberSequence n) { 37 final int[] seq = n.getSequence(); 38 if (n.size() != this.size()) { 39 return false; 40 } 41 for (int i = 0; i < n.size(); i++) { 42 if (seq[i] != this.sequence[i]) { 43 return false; 44 } 45 } 46 return true; 125 47 } 126 48 … … 136 58 } 137 59 138 public int size() {139 return sequence.length;60 public int getId() { 61 return id; 140 62 } 141 63 142 public int getId() { 143 return id; 64 public int[] getSequence() { 65 return sequence; 66 } 67 68 // Recursive check if sequence contains pattern at position i 69 private boolean matches(int i, int[] p1, int[] p2, int ip1, int ip2, 70 boolean jumped1, // True if there was a gap in Sequence 1 of the 71 // pattern 72 boolean jumped2, // True if there was a gap in Sequence 2 of the 73 // pattern 74 boolean hadSelection, // True if the last match was a selection 75 boolean matchseq1, boolean matchseq2) { 76 77 if (p1.length == ip1) { 78 return true; 79 } 80 if (p2.length == ip2) { 81 return true; 82 } 83 if (i == sequence.length) { 84 return false; 85 } 86 87 final boolean foundselection = (!(p1[ip1] == p2[ip2]) && !((p1[ip1] == -1) || (p2[ip2] == -1))); 88 final boolean matchInFirstPattern = (p1[ip1] == sequence[i]); 89 final boolean matchInSecondPattern = (p2[ip2] == sequence[i]); 90 91 if (foundselection && hadSelection) { 92 if ((matchInFirstPattern && matchseq1) 93 || (matchInSecondPattern && matchseq2)) { 94 if (jumped1) { 95 return matches(i + 1, p1, p2, ip1 + 1, ip2 + 2, false, 96 false, foundselection, matchInFirstPattern, 97 matchInSecondPattern); 98 } 99 if (jumped2) { 100 return matches(i + 1, p1, p2, ip1 + 2, ip2 + 1, false, 101 false, foundselection, matchInFirstPattern, 102 matchInSecondPattern); 103 } 104 return matches(i + 1, p1, p2, ip1 + 1, ip2 + 1, false, false, 105 foundselection, matchInFirstPattern, 106 matchInSecondPattern); 107 } else { 108 return false; 109 } 110 } 111 112 if ((matchInFirstPattern || matchInSecondPattern) && jumped1) { 113 return matches(i + 1, p1, p2, ip1 + 1, ip2 + 2, false, false, 114 foundselection, matchInFirstPattern, matchInSecondPattern); 115 } 116 if ((matchInFirstPattern || matchInSecondPattern) && jumped2) { 117 return matches(i + 1, p1, p2, ip1 + 2, ip2 + 1, false, false, 118 foundselection, matchInFirstPattern, matchInSecondPattern); 119 } 120 if (matchInFirstPattern || matchInSecondPattern) { 121 return matches(i + 1, p1, p2, ip1 + 1, ip2 + 1, false, false, 122 foundselection, matchInFirstPattern, matchInSecondPattern); 123 } 124 if (p1[ip1] == -1) { 125 return matches(i, p1, p2, ip1 + 1, ip2, true, false, false, false, 126 false); 127 } 128 if (p2[ip2] == -1) { 129 return matches(i, p1, p2, ip1, ip2 + 1, false, true, false, false, 130 false); 131 } 132 133 return false; 134 } 135 136 public void printSequence() { 137 for (int i = 0; i < sequence.length; i++) { 138 System.out.format("%5d", sequence[i]); 139 } 140 System.out.println(); 144 141 } 145 142 … … 148 145 } 149 146 150 public boolean equals(NumberSequence n) { 151 int[] seq = n.getSequence(); 152 if (n.size() != this.size()) { 153 return false; 147 public void setSequence(int[] sequence) { 148 this.sequence = sequence; 149 } 150 151 public NumberSequence shuffle() { 152 final NumberSequence result = new NumberSequence(sequence.length); 153 result.setId(getId()); 154 result.setSequence(this.sequence); 155 final Random rgen = new Random(); 156 157 for (int i = 0; i < result.sequence.length; i++) { 158 final int randomPosition = rgen.nextInt(result.sequence.length); 159 final int temp = result.sequence[i]; 160 result.sequence[i] = result.sequence[randomPosition]; 161 result.sequence[randomPosition] = temp; 154 162 } 155 for (int i = 0; i < n.size(); i++) {156 if (seq[i] != this.sequence[i]) { 157 return false;158 } 159 }160 return true;163 return result; 164 165 } 166 167 public int size() { 168 return sequence.length; 161 169 } 162 170 -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/SmithWaterman.java
r1620 r1733 38 38 private SubstitutionMatrix submat; 39 39 40 @Override 41 public void align(NumberSequence input1, NumberSequence input2, 42 SubstitutionMatrix submat, float threshold) { 43 this.input1 = input1.getSequence(); 44 this.input2 = input2.getSequence(); 45 length1 = input1.size(); 46 length2 = input2.size(); 47 this.submat = submat; 48 49 // System.out.println("Starting SmithWaterman algorithm with a " 50 // + submat.getClass() + " Substitution Matrix: " + 51 // submat.getClass().getCanonicalName()); 52 53 matrix = new MatrixEntry[length1 + 1][length2 + 1]; 54 alignment = new ArrayList<NumberSequence>(); 55 56 for (int i = 0; i < (length1 + 1); i++) { 57 for (int j = 0; j < (length2 + 1); j++) { 58 matrix[i][j] = new MatrixEntry(); 59 } 60 } 61 62 buildMatrix(); 63 traceback(); 64 65 } 66 67 /** 68 * Build the score matrix using dynamic programming. 69 */ 70 private void buildMatrix() { 71 if (submat.getGapPenalty() >= 0) { 72 throw new Error("Indel score must be negative"); 73 } 74 75 // it's a gap 76 matrix[0][0].setScore(0); 77 matrix[0][0].setPrevious(null); // starting point 78 79 // the first column 80 for (int j = 1; j < length2; j++) { 81 matrix[0][j].setScore(0); 82 matrix[0][j].setPrevious(matrix[0][j - 1]); 83 matrix[0][j].setYvalue(input2[j]); 84 matrix[0][j].setXvalue(Constants.GAP_SYMBOL); 85 } 86 // the first row 87 88 for (int j = 1; j < length1; j++) { 89 matrix[j][0].setScore(0); 90 matrix[j][0].setPrevious(matrix[j - 1][0]); 91 matrix[j][0].setXvalue(input1[j]); 92 matrix[j][0].setYvalue(Constants.GAP_SYMBOL); 93 } 94 95 for (int i = 1; i < length1; i++) { 96 97 for (int j = 1; j < length2; j++) { 98 final double diagScore = matrix[i - 1][j - 1].getScore() 99 + similarity(i, j); 100 final double upScore = matrix[i][j - 1].getScore() 101 + submat.getGapPenalty(); 102 final double leftScore = matrix[i - 1][j].getScore() 103 + submat.getGapPenalty(); 104 105 matrix[i][j].setScore(Math.max(diagScore, 106 Math.max(upScore, Math.max(leftScore, 0)))); 107 108 // find the directions that give the maximum scores. 109 // TODO: Multiple directions are ignored, we choose the first 110 // maximum score 111 // True if we had a match 112 if (diagScore == matrix[i][j].getScore()) { 113 matrix[i][j].setPrevious(matrix[i - 1][j - 1]); 114 matrix[i][j].setXvalue(input1[i - 1]); 115 matrix[i][j].setYvalue(input2[j - 1]); 116 } 117 // true if we took an event from sequence x and not from y 118 if (leftScore == matrix[i][j].getScore()) { 119 matrix[i][j].setXvalue(input1[i - 1]); 120 matrix[i][j].setYvalue(Constants.GAP_SYMBOL); 121 matrix[i][j].setPrevious(matrix[i - 1][j]); 122 } 123 // true if we took an event from sequence y and not from x 124 if (upScore == matrix[i][j].getScore()) { 125 matrix[i][j].setXvalue(Constants.GAP_SYMBOL); 126 matrix[i][j].setYvalue(input2[j - 1]); 127 matrix[i][j].setPrevious(matrix[i][j - 1]); 128 } 129 if (0 == matrix[i][j].getScore()) { 130 matrix[i][j].setPrevious(matrix[0][0]); 131 matrix[i][j].setXvalue(-2); 132 matrix[i][j].setYvalue(-2); 133 } 134 } 135 136 // Set the complete score cell 137 138 } 139 } 140 141 /* 142 * (non-Javadoc) 143 * 144 * @see 145 * de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.AlignmentAlgorithm 146 * #getAlignment() 147 */ 148 @Override 149 public ArrayList<NumberSequence> getAlignment() { 150 return alignment; 151 } 152 153 /* 154 * (non-Javadoc) 155 * 156 * @see 157 * de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.AlignmentAlgorithm 158 * #getAlignmentScore() 159 */ 160 @Override 161 public double getAlignmentScore() { 162 return getMaxScore(); 163 } 164 165 @Override 166 public ArrayList<Match> getMatches() { 167 // TODO Auto-generated method stub 168 return null; 169 } 170 171 /** 172 * Get the maximum value in the score matrix. 173 */ 174 @Override 175 public double getMaxScore() { 176 double maxScore = 0; 177 178 // skip the first row and column 179 for (int i = 1; i <= length1; i++) { 180 for (int j = 1; j < length2; j++) { 181 if (matrix[i][j].getScore() > maxScore) { 182 maxScore = matrix[i][j].getScore(); 183 } 184 } 185 } 186 187 return maxScore; 188 } 189 190 @Override 191 public void printAlignment() { 192 MatrixEntry tmp = matrix[length1 + 1][0]; 193 String aligned1 = ""; 194 String aligned2 = ""; 195 int count = 0; 196 do { 197 String append1 = ""; 198 String append2 = ""; 199 200 if (tmp.getXvalue() == Constants.GAP_SYMBOL) { 201 append1 = " ___"; 202 } else { 203 append1 = String.format("%5d", tmp.getXvalue()); 204 } 205 206 if (tmp.getYvalue() == Constants.GAP_SYMBOL) { 207 append2 = " ___"; 208 } else { 209 append2 = String.format("%5d", tmp.getYvalue()); 210 } 211 if (count != 0) { 212 aligned1 = append1 + aligned1; 213 aligned2 = append2 + aligned2; 214 } 215 216 tmp = tmp.getPrevious(); 217 count++; 218 219 } while (tmp != null); 220 System.out.println(aligned1); 221 System.out.println(aligned2); 222 } 223 224 /** 225 * print the dynmaic programming matrix 226 */ 227 @Override 228 public void printDPMatrix() { 229 System.out.print(" "); 230 for (int i = 1; i <= length1; i++) { 231 System.out.format("%5d", input1[i - 1]); 232 } 233 System.out.println(); 234 for (int j = 0; j <= length2; j++) { 235 if (j > 0) { 236 System.out.format("%5d ", input2[j - 1]); 237 } else { 238 System.out.print(" "); 239 } 240 for (int i = 0; i <= length1; i++) { 241 System.out.format("%4.1f ", matrix[i][j].getScore()); 242 } 243 System.out.println(); 244 } 245 } 246 247 public void setAlignment(ArrayList<NumberSequence> alignment) { 248 this.alignment = alignment; 249 } 40 250 41 251 /** … … 53 263 } 54 264 55 /**56 * Build the score matrix using dynamic programming.57 */58 private void buildMatrix() {59 if (submat.getGapPenalty() >= 0) {60 throw new Error("Indel score must be negative");61 }62 63 // it's a gap64 matrix[0][0].setScore(0);65 matrix[0][0].setPrevious(null); // starting point66 67 // the first column68 for (int j = 1; j < length2; j++) {69 matrix[0][j].setScore(0);70 matrix[0][j].setPrevious(matrix[0][j - 1]);71 matrix[0][j].setYvalue(input2[j]);72 matrix[0][j].setXvalue(Constants.GAP_SYMBOL);73 }74 // the first row75 76 for (int j = 1; j < length1; j++) {77 matrix[j][0].setScore(0);78 matrix[j][0].setPrevious(matrix[j - 1][0]);79 matrix[j][0].setXvalue(input1[j]);80 matrix[j][0].setYvalue(Constants.GAP_SYMBOL);81 }82 83 for (int i = 1; i < length1; i++) {84 85 for (int j = 1; j < length2; j++) {86 double diagScore = matrix[i - 1][j - 1].getScore()87 + similarity(i, j);88 double upScore = matrix[i][j - 1].getScore()89 + submat.getGapPenalty();90 double leftScore = matrix[i - 1][j].getScore()91 + submat.getGapPenalty();92 93 matrix[i][j].setScore(Math.max(diagScore,94 Math.max(upScore, Math.max(leftScore, 0))));95 96 // find the directions that give the maximum scores.97 // TODO: Multiple directions are ignored, we choose the first98 // maximum score99 // True if we had a match100 if (diagScore == matrix[i][j].getScore()) {101 matrix[i][j].setPrevious(matrix[i - 1][j - 1]);102 matrix[i][j].setXvalue(input1[i - 1]);103 matrix[i][j].setYvalue(input2[j - 1]);104 }105 // true if we took an event from sequence x and not from y106 if (leftScore == matrix[i][j].getScore()) {107 matrix[i][j].setXvalue(input1[i - 1]);108 matrix[i][j].setYvalue(Constants.GAP_SYMBOL);109 matrix[i][j].setPrevious(matrix[i - 1][j]);110 }111 // true if we took an event from sequence y and not from x112 if (upScore == matrix[i][j].getScore()) {113 matrix[i][j].setXvalue(Constants.GAP_SYMBOL);114 matrix[i][j].setYvalue(input2[j - 1]);115 matrix[i][j].setPrevious(matrix[i][j - 1]);116 }117 if (0 == matrix[i][j].getScore()) {118 matrix[i][j].setPrevious(matrix[0][0]);119 matrix[i][j].setXvalue(-2);120 matrix[i][j].setYvalue(-2);121 }122 }123 124 // Set the complete score cell125 126 }127 }128 129 /**130 * Get the maximum value in the score matrix.131 */132 public double getMaxScore() {133 double maxScore = 0;134 135 // skip the first row and column136 for (int i = 1; i <= length1; i++) {137 for (int j = 1; j < length2; j++) {138 if (matrix[i][j].getScore() > maxScore) {139 maxScore = matrix[i][j].getScore();140 }141 }142 }143 144 return maxScore;145 }146 147 /*148 * (non-Javadoc)149 *150 * @see151 * de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.AlignmentAlgorithm152 * #getAlignmentScore()153 */154 @Override155 public double getAlignmentScore() {156 return getMaxScore();157 }158 159 265 public void traceback() { 160 266 MatrixEntry tmp = matrix[length1][length2]; 161 int aligned1[] = new int[length1 + length2 + 2];162 int aligned2[] = new int[length1 + length2 + 2];267 final int aligned1[] = new int[length1 + length2 + 2]; 268 final int aligned2[] = new int[length1 + length2 + 2]; 163 269 int count = 0; 164 270 do { 165 if ( length1 + length2 + 2== count) {271 if ((length1 + length2 + 2) == count) { 166 272 Console.traceln(Level.WARNING, 167 273 "Traceback longer than both sequences summed up!"); … … 177 283 count--; 178 284 // reverse order of the alignment 179 int reversed1[] = new int[count];180 int reversed2[] = new int[count];285 final int reversed1[] = new int[count]; 286 final int reversed2[] = new int[count]; 181 287 182 288 for (int i = count - 1; i > 0; i--) { … … 185 291 } 186 292 187 NumberSequence ns1 = new NumberSequence(reversed1.length);188 NumberSequence ns2 = new NumberSequence(reversed2.length);293 final NumberSequence ns1 = new NumberSequence(reversed1.length); 294 final NumberSequence ns2 = new NumberSequence(reversed2.length); 189 295 ns1.setSequence(reversed1); 190 296 ns2.setSequence(reversed2); … … 194 300 } 195 301 196 public void printAlignment() {197 MatrixEntry tmp = matrix[length1 + 1][0];198 String aligned1 = "";199 String aligned2 = "";200 int count = 0;201 do {202 String append1 = "";203 String append2 = "";204 205 if (tmp.getXvalue() == Constants.GAP_SYMBOL) {206 append1 = " ___";207 } else {208 append1 = String.format("%5d", tmp.getXvalue());209 }210 211 if (tmp.getYvalue() == Constants.GAP_SYMBOL) {212 append2 = " ___";213 } else {214 append2 = String.format("%5d", tmp.getYvalue());215 }216 if (count != 0) {217 aligned1 = append1 + aligned1;218 aligned2 = append2 + aligned2;219 }220 221 tmp = tmp.getPrevious();222 count++;223 224 } while (tmp != null);225 System.out.println(aligned1);226 System.out.println(aligned2);227 }228 229 /**230 * print the dynmaic programming matrix231 */232 public void printDPMatrix() {233 System.out.print(" ");234 for (int i = 1; i <= length1; i++)235 System.out.format("%5d", input1[i - 1]);236 System.out.println();237 for (int j = 0; j <= length2; j++) {238 if (j > 0)239 System.out.format("%5d ", input2[j - 1]);240 else {241 System.out.print(" ");242 }243 for (int i = 0; i <= length1; i++) {244 System.out.format("%4.1f ", matrix[i][j].getScore());245 }246 System.out.println();247 }248 }249 250 /*251 * (non-Javadoc)252 *253 * @see254 * de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.AlignmentAlgorithm255 * #getAlignment()256 */257 @Override258 public ArrayList<NumberSequence> getAlignment() {259 return alignment;260 }261 262 public void setAlignment(ArrayList<NumberSequence> alignment) {263 this.alignment = alignment;264 }265 266 @Override267 public ArrayList<Match> getMatches() {268 // TODO Auto-generated method stub269 return null;270 }271 272 @Override273 public void align(NumberSequence input1, NumberSequence input2, SubstitutionMatrix submat,274 float threshold) {275 this.input1 = input1.getSequence();276 this.input2 = input2.getSequence();277 length1 = input1.size();278 length2 = input2.size();279 this.submat = submat;280 281 // System.out.println("Starting SmithWaterman algorithm with a "282 // + submat.getClass() + " Substitution Matrix: " +283 // submat.getClass().getCanonicalName());284 285 matrix = new MatrixEntry[length1 + 1][length2 + 1];286 alignment = new ArrayList<NumberSequence>();287 288 for (int i = 0; i < length1+1; i++) {289 for (int j = 0; j < length2+1; j++) {290 matrix[i][j] = new MatrixEntry();291 }292 }293 294 buildMatrix();295 traceback();296 297 }298 299 302 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/SmithWatermanRepeated.java
r1654 r1733 5 5 import java.util.LinkedList; 6 6 7 8 7 import de.ugoe.cs.autoquest.tasktrees.alignment.matrix.SubstitutionMatrix; 9 8 import de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.Constants; 10 9 11 12 10 public class SmithWatermanRepeated implements AlignmentAlgorithm { 13 11 … … 33 31 private MatrixEntry[][] matrix; 34 32 35 36 33 private ArrayList<NumberSequence> alignment; 37 34 38 35 private float scoreThreshold; 39 36 … … 44 41 45 42 public SmithWatermanRepeated() { 46 43 44 } 45 46 @Override 47 public void align(NumberSequence input1, NumberSequence input2, 48 SubstitutionMatrix submat, float threshold) { 49 50 alignment = new ArrayList<NumberSequence>(); 51 alignment.add(input1); 52 alignment.add(input2); 53 54 this.input1 = input1.getSequence(); 55 this.input2 = input2.getSequence(); 56 57 length1 = input1.size(); 58 length2 = input2.size(); 59 this.submat = submat; 60 61 // System.out.println("Starting SmithWaterman algorithm with a " 62 // + submat.getClass() + " Substitution Matrix: " + 63 // submat.getClass().getCanonicalName()); 64 this.scoreThreshold = threshold; 65 66 matrix = new MatrixEntry[length1 + 2][length2 + 1]; 67 68 for (int i = 0; i <= (length1 + 1); i++) { 69 for (int j = 0; j <= length2; j++) { 70 matrix[i][j] = new MatrixEntry(); 71 } 72 } 73 74 // Console.traceln(Level.INFO,"Generating DP Matrix"); 75 buildMatrix(); 76 // Console.traceln(Level.INFO,"Doing traceback"); 77 traceback(); 78 } 79 80 /** 81 * Build the score matrix using dynamic programming. 82 */ 83 private void buildMatrix() { 84 if (submat.getGapPenalty() >= 0) { 85 throw new Error("Indel score must be negative"); 86 } 87 88 // it's a gap 89 matrix[0][0].setScore(0); 90 matrix[0][0].setPrevious(null); // starting point 91 matrix[0][0].setXvalue(Constants.UNMATCHED_SYMBOL); 92 matrix[0][0].setYvalue(Constants.UNMATCHED_SYMBOL); 93 94 // the first column 95 for (int j = 1; j < length2; j++) { 96 matrix[0][j].setScore(0); 97 // We don't need to go back to [0][0] if we reached matrix[0][x], so 98 // just end here 99 // matrix[0][j].setPrevious(matrix[0][j-1]); 100 matrix[0][j].setPrevious(null); 101 } 102 103 for (int i = 1; i < (length1 + 2); i++) { 104 105 // Formula for first row: 106 // F(i,0) = max { F(i-1,0), F(i-1,j)-T j=1,...,m 107 108 final double firstRowLeftScore = matrix[i - 1][0].getScore(); 109 // for sequences of length 1 110 double tempMax; 111 int maxRowIndex; 112 if (length2 == 1) { 113 tempMax = matrix[i - 1][0].getScore(); 114 maxRowIndex = 0; 115 } else { 116 tempMax = matrix[i - 1][1].getScore(); 117 maxRowIndex = 1; 118 // position of the maximal score of the previous row 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 127 } 128 129 tempMax -= scoreThreshold; 130 matrix[i][0].setScore(Math.max(firstRowLeftScore, tempMax)); 131 if (tempMax == matrix[i][0].getScore()) { 132 matrix[i][0].setPrevious(matrix[i - 1][maxRowIndex]); 133 } 134 135 if (firstRowLeftScore == matrix[i][0].getScore()) { 136 matrix[i][0].setPrevious(matrix[i - 1][0]); 137 } 138 139 // The last additional score is not related to a character in the 140 // input sequence, it's the total score. Therefore we don't need to 141 // save something for it 142 // and can end here 143 if (i < (length1 + 1)) { 144 matrix[i][0].setXvalue(input1[i - 1]); 145 matrix[i][0].setYvalue(Constants.UNMATCHED_SYMBOL); 146 } else { 147 return; 148 } 149 150 for (int j = 1; j <= length2; j++) { 151 final double diagScore = matrix[i - 1][j - 1].getScore() 152 + similarity(i, j); 153 final double upScore = matrix[i][j - 1].getScore() 154 + submat.getGapPenalty(); 155 final double leftScore = matrix[i - 1][j].getScore() 156 + submat.getGapPenalty(); 157 158 matrix[i][j].setScore(Math.max( 159 diagScore, 160 Math.max(upScore, 161 Math.max(leftScore, matrix[i][0].getScore())))); 162 163 // find the directions that give the maximum scores. 164 // TODO: Multiple directions are ignored, we choose the first 165 // maximum score 166 // True if we had a match 167 if (diagScore == matrix[i][j].getScore()) { 168 matrix[i][j].setPrevious(matrix[i - 1][j - 1]); 169 matrix[i][j].setXvalue(input1[i - 1]); 170 matrix[i][j].setYvalue(input2[j - 1]); 171 } 172 // true if we took an event from sequence x and not from y 173 if (leftScore == matrix[i][j].getScore()) { 174 matrix[i][j].setXvalue(input1[i - 1]); 175 matrix[i][j].setYvalue(Constants.GAP_SYMBOL); 176 matrix[i][j].setPrevious(matrix[i - 1][j]); 177 } 178 // true if we took an event from sequence y and not from x 179 if (upScore == matrix[i][j].getScore()) { 180 matrix[i][j].setXvalue(Constants.GAP_SYMBOL); 181 matrix[i][j].setYvalue(input2[j - 1]); 182 matrix[i][j].setPrevious(matrix[i][j - 1]); 183 } 184 // true if we ended a matching region 185 if (matrix[i][0].getScore() == matrix[i][j].getScore()) { 186 matrix[i][j].setPrevious(matrix[i][0]); 187 matrix[i][j].setXvalue(input1[i - 1]); 188 matrix[i][j].setYvalue(Constants.UNMATCHED_SYMBOL); 189 } 190 } 191 192 // Set the complete score cell 193 194 } 195 } 196 197 /* 198 * (non-Javadoc) 199 * 200 * @see 201 * de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.AlignmentAlgorithm 202 * #getAlignment() 203 */ 204 @Override 205 public ArrayList<NumberSequence> getAlignment() { 206 return alignment; 207 } 208 209 /* 210 * (non-Javadoc) 211 * 212 * @see 213 * de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.AlignmentAlgorithm 214 * #getAlignmentScore() 215 */ 216 @Override 217 public double getAlignmentScore() { 218 return matrix[length1 + 1][0].getScore(); 219 } 220 221 @Override 222 public ArrayList<Match> getMatches() { 223 final ArrayList<Match> result = new ArrayList<Match>(); 224 225 // both alignment sequences should be equally long 226 int i = 0; 227 final int[] seq1 = alignment.get(0).getSequence(); 228 final int[] seq2 = alignment.get(1).getSequence(); 229 int start = 0; 230 while (i < seq1.length) { 231 if (seq2[i] != Constants.UNMATCHED_SYMBOL) { 232 start = i; 233 int count = 0; 234 while ((i < seq2.length) 235 && (seq2[i] != Constants.UNMATCHED_SYMBOL)) { 236 i++; 237 count++; 238 } 239 // I am really missing memcpy here? How does one do this better 240 // in java? 241 final int[] tmp1 = new int[count]; 242 final int[] tmp2 = new int[count]; 243 for (int j = 0; j < count; j++) { 244 tmp1[j] = seq1[start + j]; 245 tmp2[j] = seq2[start + j]; 246 } 247 final NumberSequence tmpns1 = new NumberSequence(count); 248 final NumberSequence tmpns2 = new NumberSequence(count); 249 tmpns1.setSequence(tmp1); 250 tmpns2.setSequence(tmp2); 251 final Match tmpal = new Match(); 252 tmpal.setFirstSequence(tmpns1); 253 tmpal.setSecondSequence(tmpns2); 254 // tmpal.addOccurence(new 255 // MatchOccurence(start,alignment.get(0).getId())); 256 // tmpal.addOccurence(new 257 // MatchOccurence(start,alignment.get(1).getId())); 258 result.add(tmpal); 259 } 260 i++; 261 } 262 return result; 263 } 264 265 /** 266 * Get the maximum value in the score matrix. 267 */ 268 @Override 269 public double getMaxScore() { 270 double maxScore = 0; 271 272 // skip the first row and column 273 for (int i = 1; i <= length1; i++) { 274 for (int j = 1; j <= length2; j++) { 275 if (matrix[i][j].getScore() > maxScore) { 276 maxScore = matrix[i][j].getScore(); 277 } 278 } 279 } 280 281 return maxScore; 282 } 283 284 @Override 285 public void printAlignment() { 286 final int[] tmp1 = alignment.get(0).getSequence(); 287 final int[] tmp2 = alignment.get(1).getSequence(); 288 for (int i = 0; i < tmp1.length; i++) { 289 if (tmp1[i] == Constants.GAP_SYMBOL) { 290 System.out.print(" ___"); 291 } else if (tmp1[i] == Constants.UNMATCHED_SYMBOL) { 292 System.out.print(" ..."); 293 } else { 294 System.out.format("%5d", tmp1[i]); 295 } 296 297 } 298 System.out.println(); 299 for (int i = 0; i < tmp2.length; i++) { 300 if (tmp2[i] == Constants.GAP_SYMBOL) { 301 System.out.print(" ___"); 302 } else if (tmp2[i] == Constants.UNMATCHED_SYMBOL) { 303 System.out.print(" ..."); 304 } else { 305 System.out.format("%5d", tmp2[i]); 306 } 307 308 } 309 System.out.println(); 310 311 } 312 313 /** 314 * print the dynmaic programming matrix 315 */ 316 @Override 317 public void printDPMatrix() { 318 System.out.print(" "); 319 for (int i = 1; i <= length1; i++) { 320 System.out.format("%5d", input1[i - 1]); 321 } 322 System.out.println(); 323 for (int j = 0; j <= length2; j++) { 324 if (j > 0) { 325 System.out.format("%5d ", input2[j - 1]); 326 } else { 327 System.out.print(" "); 328 } 329 for (int i = 0; i <= (length1 + 1); i++) { 330 if ((i < (length1 + 1)) || ((i == (length1 + 1)) && (j == 0))) { 331 System.out.format("%4.1f ", matrix[i][j].getScore()); 332 } 333 334 } 335 System.out.println(); 336 } 337 } 338 339 public void setAlignment(ArrayList<NumberSequence> alignment) { 340 this.alignment = alignment; 47 341 } 48 342 … … 57 351 * @return Cost of substitution of the character in str1 by the one in str2 58 352 */ 59 private double similarity(int i, int j) { 353 private double similarity(int i, int j) { 60 354 return submat.getScore(input1[i - 1], input2[j - 1]); 61 355 } 62 356 63 /**64 * Build the score matrix using dynamic programming.65 */66 private void buildMatrix() {67 if (submat.getGapPenalty() >= 0) {68 throw new Error("Indel score must be negative");69 }70 71 // it's a gap72 matrix[0][0].setScore(0);73 matrix[0][0].setPrevious(null); // starting point74 matrix[0][0].setXvalue(Constants.UNMATCHED_SYMBOL);75 matrix[0][0].setYvalue(Constants.UNMATCHED_SYMBOL);76 77 // the first column78 for (int j = 1; j < length2; j++) {79 matrix[0][j].setScore(0);80 //We don't need to go back to [0][0] if we reached matrix[0][x], so just end here81 //matrix[0][j].setPrevious(matrix[0][j-1]);82 matrix[0][j].setPrevious(null);83 }84 85 86 87 for (int i = 1; i < length1 + 2; i++) {88 89 // Formula for first row:90 // F(i,0) = max { F(i-1,0), F(i-1,j)-T j=1,...,m91 92 double firstRowLeftScore = matrix[i-1][0].getScore();93 //for sequences of length 194 double tempMax;95 int maxRowIndex;96 if(length2 == 1) {97 tempMax = matrix[i-1][0].getScore();98 maxRowIndex = 0;99 } else {100 tempMax = matrix[i-1][1].getScore();101 maxRowIndex = 1;102 //position of the maximal score of the previous row103 104 for(int j = 2; j <= length2;j++) {105 if(matrix[i-1][j].getScore() > tempMax) {106 tempMax = matrix[i-1][j].getScore();107 maxRowIndex = j;108 }109 }110 111 }112 113 tempMax -= scoreThreshold;114 matrix[i][0].setScore(Math.max(firstRowLeftScore, tempMax));115 if(tempMax == matrix[i][0].getScore()){116 matrix[i][0].setPrevious(matrix[i-1][maxRowIndex]);117 }118 119 if(firstRowLeftScore == matrix[i][0].getScore()) {120 matrix[i][0].setPrevious(matrix[i-1][0]);121 }122 123 //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 it124 //and can end here125 if(i<length1+1) {126 matrix[i][0].setXvalue(input1[i-1]);127 matrix[i][0].setYvalue(Constants.UNMATCHED_SYMBOL);128 }129 else {130 return;131 }132 133 134 135 for (int j = 1; j <= length2; j++) {136 double diagScore = matrix[i - 1][j - 1].getScore() + similarity(i, j);137 double upScore = matrix[i][j - 1].getScore() + submat.getGapPenalty();138 double leftScore = matrix[i - 1][j].getScore() + submat.getGapPenalty();139 140 matrix[i][j].setScore(Math.max(diagScore,Math.max(upScore, Math.max(leftScore,matrix[i][0].getScore()))));141 142 // find the directions that give the maximum scores.143 // TODO: Multiple directions are ignored, we choose the first maximum score144 //True if we had a match145 if (diagScore == matrix[i][j].getScore()) {146 matrix[i][j].setPrevious(matrix[i-1][j-1]);147 matrix[i][j].setXvalue(input1[i-1]);148 matrix[i][j].setYvalue(input2[j-1]);149 }150 //true if we took an event from sequence x and not from y151 if (leftScore == matrix[i][j].getScore()) {152 matrix[i][j].setXvalue(input1[i-1]);153 matrix[i][j].setYvalue(Constants.GAP_SYMBOL);154 matrix[i][j].setPrevious(matrix[i-1][j]);155 }156 //true if we took an event from sequence y and not from x157 if (upScore == matrix[i][j].getScore()) {158 matrix[i][j].setXvalue(Constants.GAP_SYMBOL);159 matrix[i][j].setYvalue(input2[j-1]);160 matrix[i][j].setPrevious(matrix[i][j-1]);161 }162 //true if we ended a matching region163 if (matrix[i][0].getScore() == matrix[i][j].getScore()) {164 matrix[i][j].setPrevious(matrix[i][0]);165 matrix[i][j].setXvalue(input1[i-1]);166 matrix[i][j].setYvalue(Constants.UNMATCHED_SYMBOL);167 }168 }169 170 //Set the complete score cell171 172 }173 }174 175 /**176 * Get the maximum value in the score matrix.177 */178 public double getMaxScore() {179 double maxScore = 0;180 181 // skip the first row and column182 for (int i = 1; i <= length1; i++) {183 for (int j = 1; j <= length2; j++) {184 if (matrix[i][j].getScore() > maxScore) {185 maxScore = matrix[i][j].getScore();186 }187 }188 }189 190 return maxScore;191 }192 193 /* (non-Javadoc)194 * @see de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.AlignmentAlgorithm#getAlignmentScore()195 */196 @Override197 public double getAlignmentScore() {198 return matrix[length1+1][0].getScore();199 }200 201 357 public void traceback() { 202 MatrixEntry tmp = matrix[length1 +1][0].getPrevious();203 LinkedList<Integer> aligned1 = new LinkedList<Integer>();204 LinkedList<Integer> aligned2 = new LinkedList<Integer>();358 MatrixEntry tmp = matrix[length1 + 1][0].getPrevious(); 359 final LinkedList<Integer> aligned1 = new LinkedList<Integer>(); 360 final LinkedList<Integer> aligned2 = new LinkedList<Integer>(); 205 361 while (tmp.getPrevious() != null) { 206 362 207 363 aligned1.add(new Integer(tmp.getXvalue())); 208 364 aligned2.add(new Integer(tmp.getYvalue())); 209 365 210 366 tmp = tmp.getPrevious(); 211 } 212 367 } 368 213 369 // reverse order of the alignment 214 int reversed1[] = new int[aligned1.size()];215 int reversed2[] = new int[aligned2.size()];370 final int reversed1[] = new int[aligned1.size()]; 371 final int reversed2[] = new int[aligned2.size()]; 216 372 217 373 int count = 0; 218 for ( Iterator<Integer> it = aligned1.iterator(); it.hasNext();) {374 for (final Iterator<Integer> it = aligned1.iterator(); it.hasNext();) { 219 375 count++; 220 376 reversed1[reversed1.length - count] = it.next(); 221 377 222 378 } 223 379 count = 0; 224 for ( Iterator<Integer> it = aligned2.iterator(); it.hasNext();) {380 for (final Iterator<Integer> it = aligned2.iterator(); it.hasNext();) { 225 381 count++; 226 382 reversed2[reversed2.length - count] = it.next(); 227 383 } 228 384 229 230 NumberSequence ns1 = new NumberSequence(reversed1.length); 231 NumberSequence ns2 = new NumberSequence(reversed2.length); 385 final NumberSequence ns1 = new NumberSequence(reversed1.length); 386 final NumberSequence ns2 = new NumberSequence(reversed2.length); 232 387 ns1.setSequence(reversed1); 233 388 ns2.setSequence(reversed2); 234 389 ns1.setId(alignment.get(0).getId()); 235 390 ns2.setId(alignment.get(1).getId()); 236 391 237 392 alignment.set(0, ns1); 238 393 alignment.set(1, ns2); 239 394 } 240 241 242 243 public void printAlignment() {244 int[] tmp1 = alignment.get(0).getSequence();245 int[] tmp2 = alignment.get(1).getSequence();246 for (int i=0; i< tmp1.length;i++) {247 if(tmp1[i] == Constants.GAP_SYMBOL) {248 System.out.print(" ___");249 }250 else if(tmp1[i] == Constants.UNMATCHED_SYMBOL) {251 System.out.print(" ...");252 }253 else {254 System.out.format("%5d", tmp1[i]);255 }256 257 }258 System.out.println();259 for (int i=0; i< tmp2.length;i++) {260 if(tmp2[i] == Constants.GAP_SYMBOL) {261 System.out.print(" ___");262 }263 else if(tmp2[i] == Constants.UNMATCHED_SYMBOL) {264 System.out.print(" ...");265 }266 else {267 System.out.format("%5d", tmp2[i]);268 }269 270 }271 System.out.println();272 273 274 275 }276 277 public ArrayList<Match> getMatches() {278 ArrayList<Match> result = new ArrayList<Match>();279 280 //both alignment sequences should be equally long281 int i = 0;282 int[] seq1 = alignment.get(0).getSequence();283 int[] seq2 = alignment.get(1).getSequence();284 int start = 0;285 while (i < seq1.length){286 if(seq2[i] != Constants.UNMATCHED_SYMBOL) {287 start = i;288 int count = 0;289 while(i < seq2.length && seq2[i] != Constants.UNMATCHED_SYMBOL) {290 i++;291 count++;292 }293 //I am really missing memcpy here? How does one do this better in java?294 int[] tmp1 = new int[count];295 int[] tmp2 = new int[count];296 for (int j = 0; j<count;j++) {297 tmp1[j] = seq1[start+j];298 tmp2[j] = seq2[start+j];299 }300 NumberSequence tmpns1 = new NumberSequence(count);301 NumberSequence tmpns2 = new NumberSequence(count);302 tmpns1.setSequence(tmp1);303 tmpns2.setSequence(tmp2);304 Match tmpal = new Match();305 tmpal.setFirstSequence(tmpns1);306 tmpal.setSecondSequence(tmpns2);307 //tmpal.addOccurence(new MatchOccurence(start,alignment.get(0).getId()));308 //tmpal.addOccurence(new MatchOccurence(start,alignment.get(1).getId()));309 result.add(tmpal);310 }311 i++;312 }313 return result;314 }315 316 /**317 * print the dynmaic programming matrix318 */319 public void printDPMatrix() {320 System.out.print(" ");321 for (int i = 1; i <= length1; i++)322 System.out.format("%5d", input1[i - 1]);323 System.out.println();324 for (int j = 0; j <= length2; j++) {325 if (j > 0)326 System.out.format("%5d ",input2[j - 1]);327 else{328 System.out.print(" ");329 }330 for (int i = 0; i <= length1 + 1; i++) {331 if((i<length1+1) || (i==length1+1 && j==0)) {332 System.out.format("%4.1f ",matrix[i][j].getScore());333 }334 335 }336 System.out.println();337 }338 }339 340 341 /* (non-Javadoc)342 * @see de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.AlignmentAlgorithm#getAlignment()343 */344 @Override345 public ArrayList<NumberSequence> getAlignment() {346 return alignment;347 }348 349 public void setAlignment(ArrayList<NumberSequence> alignment) {350 this.alignment = alignment;351 }352 353 @Override354 public void align(NumberSequence input1, NumberSequence input2, SubstitutionMatrix submat,355 float threshold) {356 357 alignment = new ArrayList<NumberSequence>();358 alignment.add(input1);359 alignment.add(input2);360 361 this.input1=input1.getSequence();362 this.input2=input2.getSequence();363 364 length1 = input1.size();365 length2 = input2.size();366 this.submat = submat;367 368 //System.out.println("Starting SmithWaterman algorithm with a "369 // + submat.getClass() + " Substitution Matrix: " + submat.getClass().getCanonicalName());370 this.scoreThreshold = threshold;371 372 matrix = new MatrixEntry[length1+2][length2+1];373 374 375 for (int i = 0; i <= length1+1; i++) {376 for(int j = 0; j<= length2; j++) {377 matrix[i][j] = new MatrixEntry();378 }379 }380 381 //Console.traceln(Level.INFO,"Generating DP Matrix");382 buildMatrix();383 //Console.traceln(Level.INFO,"Doing traceback");384 traceback();385 }386 395 387 396 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/matrix/DifferenceSubstitutionMatrix.java
r1702 r1733 9 9 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask; 10 10 11 12 11 /** 13 12 * @author Ralph Krimmel … … 16 15 public class DifferenceSubstitutionMatrix implements SubstitutionMatrix { 17 16 18 private int[] input1;19 private int[] input2;20 private int maxValue;21 22 public DifferenceSubstitutionMatrix(int[] input1, int[] input2) {17 private final int[] input1; 18 private final int[] input2; 19 private final int maxValue; 20 21 public DifferenceSubstitutionMatrix(int[] input1, int[] input2) { 23 22 this.input1 = input1; 24 23 this.input2 = input2; 25 24 this.maxValue = getMaxValue(); 26 25 } 27 28 /* (non-Javadoc) 29 * @see de.ugoe.cs.autoquest.plugin.alignment.SubstitutionMatrix#getDistance(int, int) 30 */ 31 public float getScore(int pos1, int pos2) { 32 return maxValue - (input1[pos1] - input2[pos2]); 33 } 34 35 private int getMaxValue() { 36 int max = input1[0]; 37 for (int i=0; i < input1.length; i++) { 38 if(input1[i] > max) { 39 max = input1[i]; 40 } 41 } 42 for (int j=0; j < input2.length; j++) { 43 if(input2[j] > max) { 44 max = input2[j]; 45 } 46 } 47 return max; 26 27 @Override 28 public void generate(HashSet<ITask> uniqueTasks) { 48 29 } 49 30 … … 53 34 } 54 35 36 private int getMaxValue() { 37 int max = input1[0]; 38 for (int i = 0; i < input1.length; i++) { 39 if (input1[i] > max) { 40 max = input1[i]; 41 } 42 } 43 for (int j = 0; j < input2.length; j++) { 44 if (input2[j] > max) { 45 max = input2[j]; 46 } 47 } 48 return max; 49 } 55 50 51 /* 52 * (non-Javadoc) 53 * 54 * @see 55 * de.ugoe.cs.autoquest.plugin.alignment.SubstitutionMatrix#getDistance(int, 56 * int) 57 */ 56 58 @Override 57 public void generate(HashSet<ITask> uniqueTasks) { 59 public float getScore(int pos1, int pos2) { 60 return maxValue - (input1[pos1] - input2[pos2]); 58 61 } 59 62 -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/matrix/DummySubstitutionMatrix.java
r1702 r1733 9 9 10 10 @Override 11 public float getScore(int pos1, int pos2) { 12 if(pos1==pos2) { 13 return 1; 14 } 15 else { 16 return 0; 17 } 11 public void generate(HashSet<ITask> uniqueTasks) { 18 12 } 19 13 … … 24 18 25 19 @Override 26 public void generate(HashSet<ITask> uniqueTasks) { 20 public float getScore(int pos1, int pos2) { 21 if (pos1 == pos2) { 22 return 1; 23 } else { 24 return 0; 25 } 27 26 } 28 27 … … 30 29 public void update(LinkedList<ITask> newlyGeneratedTasks) { 31 30 // TODO Auto-generated method stub 32 31 33 32 } 34 35 33 36 34 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/matrix/DynamicTriangleMatrix.java
r1702 r1733 5 5 //Must be initialized! 6 6 public class DynamicTriangleMatrix implements ITriangleMatrix { 7 8 private ArrayList<Float> matrix;7 8 private final ArrayList<Float> matrix; 9 9 protected int size; 10 10 private float initalizationValue; 11 12 13 14 //Increases the size 15 /* (non-Javadoc) 16 * @see de.ugoe.cs.autoquest.tasktrees.alignment.matrix.ITriangleMatrix#increaseSize(int) 11 12 public DynamicTriangleMatrix(int size) { 13 this.size = size; 14 matrix = new ArrayList<Float>(); 15 matrix.ensureCapacity(size * (size + (1 / 2))); 16 } 17 18 /* 19 * (non-Javadoc) 20 * 21 * @see 22 * de.ugoe.cs.autoquest.tasktrees.alignment.matrix.ITriangleMatrix#get(int, 23 * int) 24 */ 25 @Override 26 public float get(int first, int second) { 27 final int row = Math.min(first, second); 28 final int col = Math.max(first, second); 29 return matrix.get((row * size) 30 - (((row * (row + 1)) / 2) - (size - col))); 31 32 } 33 34 // Increases the size 35 /* 36 * (non-Javadoc) 37 * 38 * @see 39 * de.ugoe.cs.autoquest.tasktrees.alignment.matrix.ITriangleMatrix#increaseSize 40 * (int) 17 41 */ 18 42 @Override 19 43 public void increaseSize(int count) { 20 int oldsize = size;44 final int oldsize = size; 21 45 this.size += count; 22 matrix.ensureCapacity(size *(size+1/2));23 for (int i=0;i<(oldsize*count)+(count*(count+1)/2);i++) {46 matrix.ensureCapacity(size * (size + (1 / 2))); 47 for (int i = 0; i < ((oldsize * count) + ((count * (count + 1)) / 2)); i++) { 24 48 matrix.add(this.initalizationValue); 25 49 } 26 50 } 27 51 28 29 public DynamicTriangleMatrix(int size) { 30 this.size = size; 31 matrix = new ArrayList<Float>(); 32 matrix.ensureCapacity(size*(size+1/2)); 33 } 34 35 36 /* (non-Javadoc) 37 * @see de.ugoe.cs.autoquest.tasktrees.alignment.matrix.ITriangleMatrix#get(int, int) 38 */ 39 @Override 40 public float get(int first, int second) { 41 int row = Math.min(first, second); 42 int col = Math.max(first, second); 43 return matrix.get(row*size-(row*(row+1)/2 - (size-col))); 44 45 } 46 47 /* (non-Javadoc) 48 * @see de.ugoe.cs.autoquest.tasktrees.alignment.matrix.ITriangleMatrix#set(int, int, float) 49 */ 50 @Override 51 public void set(int first, int second, float value) { 52 int row = Math.min(first, second); 53 int col = Math.max(first, second); 54 matrix.set(row*size-(row*(row+1)/2 - (size-col)),value); 55 } 56 57 /* (non-Javadoc) 58 * @see de.ugoe.cs.autoquest.tasktrees.alignment.matrix.ITriangleMatrix#initialize(float) 52 /* 53 * (non-Javadoc) 54 * 55 * @see 56 * de.ugoe.cs.autoquest.tasktrees.alignment.matrix.ITriangleMatrix#initialize 57 * (float) 59 58 */ 60 59 @Override … … 62 61 this.initalizationValue = value; 63 62 matrix.clear(); 64 for (int i =0; i < this.size*(this.size+1)/2; i++) {63 for (int i = 0; i < ((this.size * (this.size + 1)) / 2); i++) { 65 64 matrix.add(value); 66 65 } 67 66 } 68 69 70 /* (non-Javadoc) 71 * @see de.ugoe.cs.autoquest.tasktrees.alignment.matrix.ITriangleMatrix#toString() 67 68 /* 69 * (non-Javadoc) 70 * 71 * @see 72 * de.ugoe.cs.autoquest.tasktrees.alignment.matrix.ITriangleMatrix#set(int, 73 * int, float) 74 */ 75 @Override 76 public void set(int first, int second, float value) { 77 final int row = Math.min(first, second); 78 final int col = Math.max(first, second); 79 matrix.set((row * size) - (((row * (row + 1)) / 2) - (size - col)), 80 value); 81 } 82 83 @Override 84 public int size() { 85 return size; 86 } 87 88 /* 89 * (non-Javadoc) 90 * 91 * @see 92 * de.ugoe.cs.autoquest.tasktrees.alignment.matrix.ITriangleMatrix#toString 93 * () 72 94 */ 73 95 @Override … … 75 97 String result = ""; 76 98 for (int i = 0; i < size; i++) { 77 for (int j = 0; j< size; j++) {78 if (i<j) {79 if (Float.isInfinite(this.get(i,j))) {99 for (int j = 0; j < size; j++) { 100 if (i < j) { 101 if (Float.isInfinite(this.get(i, j))) { 80 102 result = result + " -------"; 103 } else { 104 result = result 105 + String.format("%+8.2f", this.get(i, j)); 81 106 } 82 else { 83 result = result + String.format("%+8.2f",this.get(i,j)); 84 } 85 } 86 else { 107 } else { 87 108 result = result + (" "); 88 109 } … … 92 113 return result; 93 114 } 94 95 96 @Override97 public int size() {98 return size;99 }100 115 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/matrix/EventTaskInstancesListGenerator.java
r1695 r1733 7 7 import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance; 8 8 9 public class EventTaskInstancesListGenerator extends DefaultTaskTraversingVisitor { 10 11 private LinkedList<IEventTaskInstance> eventlist; 12 13 public LinkedList<IEventTaskInstance> getEventlist() { 14 return eventlist; 9 public class EventTaskInstancesListGenerator extends 10 DefaultTaskTraversingVisitor { 11 12 private LinkedList<IEventTaskInstance> eventlist; 13 14 public EventTaskInstancesListGenerator() { 15 eventlist = new LinkedList<IEventTaskInstance>(); 16 } 17 18 public LinkedList<IEventTaskInstance> getEventlist() { 19 return eventlist; 20 } 21 22 public void setEventlist(LinkedList<IEventTaskInstance> eventlist) { 23 this.eventlist = eventlist; 24 } 25 26 @Override 27 public void visit(IEventTask eventTask) { 28 if (eventTask.getInstances().size() > 0) { 29 final IEventTaskInstance eti = (IEventTaskInstance) eventTask 30 .getInstances().iterator().next(); 31 // System.out.println("Adding eventtaskinstance to list: " + eti); 32 eventlist.add(eti); 15 33 } 34 } 16 35 17 public void setEventlist(LinkedList<IEventTaskInstance> eventlist) {18 this.eventlist = eventlist;19 }20 21 @Override22 public void visit(IEventTask eventTask) {23 if(eventTask.getInstances().size() > 0) {24 IEventTaskInstance eti = (IEventTaskInstance) eventTask.getInstances().iterator().next();25 //System.out.println("Adding eventtaskinstance to list: " + eti);26 eventlist.add(eti);27 }28 }29 30 public EventTaskInstancesListGenerator() {31 eventlist = new LinkedList<IEventTaskInstance>();32 }33 34 36 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/matrix/ITriangleMatrix.java
r1702 r1733 3 3 public interface ITriangleMatrix { 4 4 5 //Increases the size 5 public abstract float get(int first, int second); 6 7 // Increases the size 6 8 public abstract void increaseSize(int count) throws Exception; 7 9 8 public abstract float get(int first, int second);10 public abstract void initialize(float value); 9 11 10 12 public abstract void set(int first, int second, float value); 11 13 12 public abstract void initialize(float value);14 public abstract int size(); 13 15 16 @Override 14 17 public abstract String toString(); 15 18 16 public abstract int size();17 18 19 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/matrix/NearbySubstitutionMatrix.java
r1702 r1733 15 15 public class NearbySubstitutionMatrix implements SubstitutionMatrix { 16 16 17 private int[] input1;18 private int[] input2;19 private int range;20 21 public NearbySubstitutionMatrix(int[] input1, int[] input2, int range) {17 private final int[] input1; 18 private final int[] input2; 19 private final int range; 20 21 public NearbySubstitutionMatrix(int[] input1, int[] input2, int range) { 22 22 this.input1 = input1; 23 23 this.input2 = input2; 24 24 this.range = range; 25 25 } 26 27 /* (non-Javadoc)28 * @see de.ugoe.cs.autoquest.plugin.alignment.SubstitutionMatrix#getDistance(int, int)29 */30 public float getScore(int pos1, int pos2) {31 int difference = Math.abs(input1[pos1]-input2[pos2]);32 if(difference < range) {33 return range-difference;34 }35 else {36 return -range;37 }38 }39 40 41 @Override42 public float getGapPenalty() {43 return -range-1;44 }45 46 47 26 48 27 @Override … … 51 30 52 31 @Override 32 public float getGapPenalty() { 33 return -range - 1; 34 } 35 36 /* 37 * (non-Javadoc) 38 * 39 * @see 40 * de.ugoe.cs.autoquest.plugin.alignment.SubstitutionMatrix#getDistance(int, 41 * int) 42 */ 43 @Override 44 public float getScore(int pos1, int pos2) { 45 final int difference = Math.abs(input1[pos1] - input2[pos2]); 46 if (difference < range) { 47 return range - difference; 48 } else { 49 return -range; 50 } 51 } 52 53 @Override 53 54 public void update(LinkedList<ITask> newlyGeneratedTasks) { 54 55 } 55 56 56 57 58 57 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/matrix/ObjectDistanceSubstitionMatrix.java
r1711 r1733 17 17 import de.ugoe.cs.util.console.Console; 18 18 19 20 21 public class ObjectDistanceSubstitionMatrix implements SubstitutionMatrix,Serializable { 19 public class ObjectDistanceSubstitionMatrix implements SubstitutionMatrix, 20 Serializable { 22 21 23 22 /** … … 25 24 */ 26 25 private static final long serialVersionUID = -4253258274617754083L; 27 private HashMap<Integer, Integer> idmapping;26 private final HashMap<Integer, Integer> idmapping; 28 27 private ITriangleMatrix matrix; 29 28 private HashSet<ITask> uniqueTasks; 30 29 private float gapPenalty; 31 30 private int index = 0; 32 private HashMap<Integer, LinkedList<IEventTaskInstance>> etisOfTasks;31 private final HashMap<Integer, LinkedList<IEventTaskInstance>> etisOfTasks; 33 32 private boolean calculateNonTaskInstances = true; 34 33 private int firstRoundMaxIndex = 0; 35 34 36 private double positiveThreshold; 37 38 public ObjectDistanceSubstitionMatrix( 39 float positiveThreshold, int gapPenalty, 40 boolean calculateNonTaskInstances) { 35 private final double positiveThreshold; 36 37 public ObjectDistanceSubstitionMatrix(float positiveThreshold, 38 int gapPenalty, boolean calculateNonTaskInstances) { 41 39 this.positiveThreshold = positiveThreshold; 42 40 idmapping = new HashMap<Integer, Integer>(); … … 45 43 this.calculateNonTaskInstances = calculateNonTaskInstances; 46 44 47 }48 49 public float getGapPenalty() {50 return gapPenalty;51 }52 53 public void setGapPenalty(float gapPenalty) {54 this.gapPenalty = gapPenalty;55 }56 57 //TODO: Merge this with updateEventTaskInstances58 private void searchEventTaskInstances() {59 for (Iterator<ITask> it = uniqueTasks.iterator(); it.hasNext();) {60 ITask task = it.next();61 if (!(task instanceof IEventTask)) {62 EventTaskInstancesListGenerator etlg = new EventTaskInstancesListGenerator();63 task.accept(etlg);64 LinkedList<IEventTaskInstance> eventTaskInstances = etlg65 .getEventlist();66 etisOfTasks.put(task.getId(), eventTaskInstances);67 }68 }69 }70 71 public void updateEventTaskInstances(LinkedList<ITask> newTasks){72 for (Iterator<ITask> it = newTasks.iterator();it.hasNext();) {73 ITask task = it.next();74 if (!(task instanceof IEventTask)) {75 EventTaskInstancesListGenerator etlg = new EventTaskInstancesListGenerator();76 task.accept(etlg);77 LinkedList<IEventTaskInstance> eventTaskInstances = etlg78 .getEventlist();79 etisOfTasks.put(task.getId(), eventTaskInstances);80 }81 }82 }83 84 //Just Calculate the distance between the new tasks and the matrix.85 public void update(LinkedList<ITask> newTasks) {86 87 if (this.calculateNonTaskInstances) {88 try {89 matrix.increaseSize(newTasks.size());90 System.out.println("Subsitution matrix size is now " + matrix.size()*(matrix.size()+1)/2);91 Console.traceln(Level.INFO, "searching EventTasks in Tasks");92 } catch (Exception e) {93 Console.logException(e);94 }95 this.updateEventTaskInstances(newTasks);96 for(Iterator<ITask> it = newTasks.iterator();it.hasNext();) {97 ITask task1 = it.next();98 for (Iterator<ITask> jt = uniqueTasks.iterator(); jt.hasNext();) {99 ITask task2 = jt.next();100 computeDistance(task1,task2);101 }102 }103 }104 45 } 105 46 … … 112 53 // We just need to the first instance here 113 54 if (task1.getInstances().size() > 0) { 114 ti1 = (ITaskInstance) task1.getInstances().iterator() 115 .next(); 55 ti1 = task1.getInstances().iterator().next(); 116 56 } 117 57 if (task2.getInstances().size() > 0) { 118 ti2 = (ITaskInstance) task2.getInstances().iterator() 119 .next(); 58 ti2 = task2.getInstances().iterator().next(); 120 59 } 121 60 IEventTaskInstance eti1 = null; 122 61 IEventTaskInstance eti2 = null; 123 62 124 if ( ti1 instanceof IEventTaskInstance125 && ti2 instanceof IEventTaskInstance) {63 if ((ti1 instanceof IEventTaskInstance) 64 && (ti2 instanceof IEventTaskInstance)) { 126 65 eti1 = (IEventTaskInstance) ti1; 127 66 index1 = getIndex(eti1); … … 129 68 index2 = getIndex(eti2); 130 69 distance = distanceBetweenInstances(eti1, eti2); 131 } else if ( ti1 instanceof IEventTaskInstance70 } else if ((ti1 instanceof IEventTaskInstance) 132 71 && !(ti2 instanceof IEventTaskInstance)) { 133 task1 = ((ITaskInstance) ti1).getTask();72 task1 = ti1.getTask(); 134 73 index2 = getIndex(task2); 135 74 eti1 = (IEventTaskInstance) ti1; … … 137 76 distance = distanceBetweenTaskAndInstance(task2, eti1); 138 77 } else if (!(ti1 instanceof IEventTaskInstance) 139 && ti2 instanceof IEventTaskInstance) {78 && (ti2 instanceof IEventTaskInstance)) { 140 79 index1 = getIndex(task1); 141 80 eti2 = (IEventTaskInstance) ti2; … … 152 91 matrix.set(index1, index2, distance); 153 92 } 154 155 93 94 private float distanceBetweenInstances(IEventTaskInstance eti1, 95 IEventTaskInstance eti2) { 96 final IGUIElement first = (IGUIElement) eti1.getEvent().getTarget(); 97 final IGUIElement second = (IGUIElement) eti2.getEvent().getTarget(); 98 float distance = -1 * AlignmentHelpers.distanceBetween(first, second); 99 distance += positiveThreshold; 100 return distance; 101 } 102 103 private float distanceBetweenTaskAndInstance(ITask task1, 104 IEventTaskInstance eti1) { 105 if (this.calculateNonTaskInstances) { 106 float tmpDistance = 0; 107 // System.out.println(etisOfTasks); 108 final LinkedList<IEventTaskInstance> eventTaskInstances = etisOfTasks 109 .get(task1.getId()); 110 for (final Iterator<IEventTaskInstance> it = eventTaskInstances 111 .iterator(); it.hasNext();) { 112 final IEventTaskInstance eti2 = it.next(); 113 // int taskId1 = eti1.getTask().getId(); 114 // int taskId2 = eti2.getTask().getId(); 115 // if (scoreExists(taskId1, taskId2)) { 116 // tmpDistance += getScore(taskId1, taskId2); 117 // } else { 118 final float dist = distanceBetweenInstances(eti1, eti2); 119 matrix.set(getIndex(eti1), getIndex(eti2), dist); 120 tmpDistance += dist; 121 // } 122 } 123 return tmpDistance / eventTaskInstances.size(); 124 } else { 125 return 0; 126 } 127 } 128 129 private float distanceBetweenTasks(ITask task1, ITask task2) { 130 if (this.calculateNonTaskInstances) { 131 final LinkedList<IEventTaskInstance> eventTaskInstances = etisOfTasks 132 .get(task1.getId()); 133 float tmpDistance = 0; 134 for (final Iterator<IEventTaskInstance> it = eventTaskInstances 135 .iterator(); it.hasNext();) { 136 final IEventTaskInstance eti1 = it.next(); 137 tmpDistance += distanceBetweenTaskAndInstance(task2, eti1); 138 } 139 140 return tmpDistance / eventTaskInstances.size(); 141 } else { 142 return 0; 143 } 144 } 145 146 @Override 156 147 public void generate(HashSet<ITask> uniqueTasks) { 157 148 this.uniqueTasks = uniqueTasks; … … 160 151 Console.traceln(Level.INFO, "searching EventTasks in Tasks"); 161 152 searchEventTaskInstances(); 162 } 163 else{ 164 matrix = new StaticTriangleMatrix(uniqueTasks.size()+1); 153 } else { 154 matrix = new StaticTriangleMatrix(uniqueTasks.size() + 1); 165 155 } 166 156 matrix.initialize(0); 167 168 int count =0;169 int size=uniqueTasks.size();170 for ( Iterator<ITask> it = uniqueTasks.iterator(); it.hasNext();) {171 ITask task1 = it.next();157 158 int count = 0; 159 final int size = uniqueTasks.size(); 160 for (final Iterator<ITask> it = uniqueTasks.iterator(); it.hasNext();) { 161 final ITask task1 = it.next(); 172 162 count++; 173 if((count%(size/100)==0)) { 174 Console.traceln(Level.INFO,(Math.round((float) count/size*100))+ "%"); 175 } 176 for (Iterator<ITask> jt = uniqueTasks.iterator(); jt.hasNext();) { 177 ITask task2 = jt.next(); 178 computeDistance(task1,task2); 179 } 180 } 181 this.firstRoundMaxIndex=index; 182 } 183 184 185 186 187 188 189 private float distanceBetweenTaskAndInstance(ITask task1, 190 IEventTaskInstance eti1) { 191 if (this.calculateNonTaskInstances) { 192 float tmpDistance = 0; 193 //System.out.println(etisOfTasks); 194 LinkedList<IEventTaskInstance> eventTaskInstances = etisOfTasks 195 .get(task1.getId()); 196 for (Iterator<IEventTaskInstance> it = eventTaskInstances 197 .iterator(); it.hasNext();) { 198 IEventTaskInstance eti2 = it.next(); 199 //int taskId1 = eti1.getTask().getId(); 200 //int taskId2 = eti2.getTask().getId(); 201 //if (scoreExists(taskId1, taskId2)) { 202 // tmpDistance += getScore(taskId1, taskId2); 203 //} else { 204 float dist = distanceBetweenInstances(eti1, eti2); 205 matrix.set(getIndex(eti1), getIndex(eti2), dist); 206 tmpDistance += dist; 207 //} 208 } 209 return tmpDistance / eventTaskInstances.size(); 210 } else { 211 return 0; 212 } 213 } 214 215 //public boolean scoreExists(int id, int id2) { 216 //return idmapping.containsKey(id) && idmapping.containsKey(id2); 217 // return false; 218 //} 219 220 private float distanceBetweenTasks(ITask task1, ITask task2) { 221 if (this.calculateNonTaskInstances) { 222 LinkedList<IEventTaskInstance> eventTaskInstances = etisOfTasks 223 .get(task1.getId()); 224 float tmpDistance = 0; 225 for (Iterator<IEventTaskInstance> it = eventTaskInstances 226 .iterator(); it.hasNext();) { 227 IEventTaskInstance eti1 = it.next(); 228 tmpDistance += distanceBetweenTaskAndInstance(task2, eti1); 229 } 230 231 return tmpDistance / eventTaskInstances.size(); 232 } else { 233 return 0; 234 } 235 } 236 237 synchronized private int getIndex(ITask task) { 238 int tempindex = -1; 239 240 if (!idmapping.containsKey(task.getId())) { 241 242 idmapping.put(task.getId(), index); 243 tempindex = index; 244 index++; 245 } else { 246 tempindex = idmapping.get(task.getId()); 247 } 248 249 return tempindex; 163 if (((count % (size / 100)) == 0)) { 164 Console.traceln(Level.INFO, 165 (Math.round(((float) count / size) * 100)) + "%"); 166 } 167 for (final Iterator<ITask> jt = uniqueTasks.iterator(); jt 168 .hasNext();) { 169 final ITask task2 = jt.next(); 170 computeDistance(task1, task2); 171 } 172 } 173 this.firstRoundMaxIndex = index; 174 } 175 176 @Override 177 public float getGapPenalty() { 178 return gapPenalty; 250 179 } 251 180 … … 260 189 } 261 190 return tempindex; 191 } 192 193 synchronized private int getIndex(ITask task) { 194 int tempindex = -1; 195 196 if (!idmapping.containsKey(task.getId())) { 197 198 idmapping.put(task.getId(), index); 199 tempindex = index; 200 index++; 201 } else { 202 tempindex = idmapping.get(task.getId()); 203 } 204 205 return tempindex; 206 } 207 208 // public boolean scoreExists(int id, int id2) { 209 // return idmapping.containsKey(id) && idmapping.containsKey(id2); 210 // return false; 211 // } 212 213 @Override 214 public float getScore(int taskId1, int taskId2) { 215 if ((taskId1 == Constants.GAP_SYMBOL) 216 || (taskId1 == Constants.UNMATCHED_SYMBOL) 217 || (taskId2 == Constants.GAP_SYMBOL) 218 || (taskId2 == Constants.UNMATCHED_SYMBOL)) { 219 return 0; 220 } else if ((this.calculateNonTaskInstances == false) 221 && ((taskId1 > this.firstRoundMaxIndex) || (taskId2 > this.firstRoundMaxIndex))) { 222 return 0; 223 } else { 224 final Integer first = idmapping.get(taskId1); 225 final Integer second = idmapping.get(taskId2); 226 return matrix.get(first, second); 227 } 228 229 } 230 231 // TODO: Merge this with updateEventTaskInstances 232 private void searchEventTaskInstances() { 233 for (final Iterator<ITask> it = uniqueTasks.iterator(); it.hasNext();) { 234 final ITask task = it.next(); 235 if (!(task instanceof IEventTask)) { 236 final EventTaskInstancesListGenerator etlg = new EventTaskInstancesListGenerator(); 237 task.accept(etlg); 238 final LinkedList<IEventTaskInstance> eventTaskInstances = etlg 239 .getEventlist(); 240 etisOfTasks.put(task.getId(), eventTaskInstances); 241 } 242 } 243 } 244 245 public void setGapPenalty(float gapPenalty) { 246 this.gapPenalty = gapPenalty; 262 247 }; 263 248 264 private float distanceBetweenInstances(IEventTaskInstance eti1, 265 IEventTaskInstance eti2) { 266 IGUIElement first = (IGUIElement) eti1.getEvent().getTarget(); 267 IGUIElement second = (IGUIElement) eti2.getEvent().getTarget(); 268 float distance = -1 * AlignmentHelpers.distanceBetween(first, second); 269 distance += positiveThreshold; 270 return distance; 271 } 272 249 @Override 273 250 public String toString() { 274 251 return matrix.toString(); 275 252 } 276 253 277 public float getScore(int taskId1, int taskId2) { 278 if (taskId1 == Constants.GAP_SYMBOL 279 || taskId1 == Constants.UNMATCHED_SYMBOL 280 || taskId2 == Constants.GAP_SYMBOL 281 || taskId2 == Constants.UNMATCHED_SYMBOL) { 282 return 0; 283 } else if(this.calculateNonTaskInstances==false && 284 (taskId1>this.firstRoundMaxIndex 285 || taskId2>this.firstRoundMaxIndex)) { 286 return 0; 287 } else { 288 Integer first = idmapping.get(taskId1); 289 Integer second = idmapping.get(taskId2); 290 return matrix.get(first, second); 291 } 292 254 // Just Calculate the distance between the new tasks and the matrix. 255 @Override 256 public void update(LinkedList<ITask> newTasks) { 257 258 if (this.calculateNonTaskInstances) { 259 try { 260 matrix.increaseSize(newTasks.size()); 261 System.out.println("Subsitution matrix size is now " 262 + ((matrix.size() * (matrix.size() + 1)) / 2)); 263 Console.traceln(Level.INFO, "searching EventTasks in Tasks"); 264 } catch (final Exception e) { 265 Console.logException(e); 266 } 267 this.updateEventTaskInstances(newTasks); 268 for (final Iterator<ITask> it = newTasks.iterator(); it.hasNext();) { 269 final ITask task1 = it.next(); 270 for (final Iterator<ITask> jt = uniqueTasks.iterator(); jt 271 .hasNext();) { 272 final ITask task2 = jt.next(); 273 computeDistance(task1, task2); 274 } 275 } 276 } 277 } 278 279 public void updateEventTaskInstances(LinkedList<ITask> newTasks) { 280 for (final Iterator<ITask> it = newTasks.iterator(); it.hasNext();) { 281 final ITask task = it.next(); 282 if (!(task instanceof IEventTask)) { 283 final EventTaskInstancesListGenerator etlg = new EventTaskInstancesListGenerator(); 284 task.accept(etlg); 285 final LinkedList<IEventTaskInstance> eventTaskInstances = etlg 286 .getEventlist(); 287 etisOfTasks.put(task.getId(), eventTaskInstances); 288 } 289 } 293 290 } 294 291 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/matrix/StaticTriangleMatrix.java
r1707 r1733 3 3 import java.io.Serializable; 4 4 5 public class StaticTriangleMatrix implements ITriangleMatrix, Serializable {6 5 public class StaticTriangleMatrix implements ITriangleMatrix, Serializable { 6 7 7 /** 8 8 * 9 9 */ 10 10 private static final long serialVersionUID = 7599542322424894866L; 11 private f loat[] matrix;11 private final float[] matrix; 12 12 protected int size; 13 14 13 15 14 public StaticTriangleMatrix(int size) { 16 15 this.size = size; 17 matrix = new float [size*(size+1)/2]; 18 } 19 20 public float get(int first, int second) { 21 int row = Math.min(first, second); 22 int col = Math.max(first, second); 23 return matrix[row*size-(row*(row+1)/2 - (size-col))]; 24 25 } 26 27 public void set(int first, int second, float value) { 28 int row = Math.min(first, second); 29 int col = Math.max(first, second); 30 matrix[row*size-(row*(row+1)/2 - (size-col))] = value; 16 matrix = new float[(size * (size + 1)) / 2]; 31 17 } 32 18 19 @Override 20 public float get(int first, int second) { 21 final int row = Math.min(first, second); 22 final int col = Math.max(first, second); 23 return matrix[(row * size) - (((row * (row + 1)) / 2) - (size - col))]; 24 25 } 26 27 @Override 28 public void increaseSize(int count) throws Exception { 29 throw new Exception( 30 "Cannot call this function on this implementation of ITriangle Matrix"); 31 32 } 33 34 @Override 33 35 public void initialize(float value) { 34 for (int i =0; i < matrix.length; i++) {36 for (int i = 0; i < matrix.length; i++) { 35 37 matrix[i] = value; 36 38 } 37 39 } 38 39 40 40 41 @Override 42 public void set(int first, int second, float value) { 43 final int row = Math.min(first, second); 44 final int col = Math.max(first, second); 45 matrix[(row * size) - (((row * (row + 1)) / 2) - (size - col))] = value; 46 } 47 48 @Override 49 public int size() { 50 return size; 51 } 52 53 @Override 41 54 public String toString() { 42 55 String result = ""; 43 56 for (int i = 0; i < size; i++) { 44 for (int j = 0; j< size; j++) {45 if (i<j) {46 if (Float.isInfinite(this.get(i,j))) {57 for (int j = 0; j < size; j++) { 58 if (i < j) { 59 if (Float.isInfinite(this.get(i, j))) { 47 60 result = result + " -------"; 61 } else { 62 result = result 63 + String.format("%+8.2f", this.get(i, j)); 48 64 } 49 else { 50 result = result + String.format("%+8.2f",this.get(i,j)); 51 } 52 } 53 else { 65 } else { 54 66 result = result + (" "); 55 67 } … … 59 71 return result; 60 72 } 61 62 @Override63 public void increaseSize(int count) throws Exception {64 throw new Exception("Cannot call this function on this implementation of ITriangle Matrix");65 66 }67 68 @Override69 public int size() {70 return size;71 }72 73 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/matrix/SubstitutionMatrix.java
r1702 r1733 6 6 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask; 7 7 8 public interface SubstitutionMatrix { 8 9 10 public void generate(HashSet<ITask> uniqueTasks); 9 11 10 public interface SubstitutionMatrix { 11 12 public float getGapPenalty(); 12 13 13 14 public float getScore(int pos1, int pos2); 14 15 15 public float getGapPenalty();16 17 public void generate(HashSet<ITask> uniqueTasks);18 19 16 public void update(LinkedList<ITask> newlyGeneratedTasks); 20 17 21 22 18 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/matrix/UPGMAMatrix.java
r1702 r1733 1 1 package de.ugoe.cs.autoquest.tasktrees.alignment.matrix; 2 3 4 2 5 3 public class UPGMAMatrix extends StaticTriangleMatrix { … … 9 7 } 10 8 9 @Override 11 10 public int size() { 12 11 return size; 13 12 } 14 13 14 @Override 15 15 public String toString() { 16 16 String result = ""; … … 19 19 } 20 20 result += "\n"; 21 21 22 22 for (int i = 0; i < size; i++) { 23 for (int j = 0; j< size; j++) {24 if (i<j) {25 if (Double.isInfinite(this.get(i,j))) {23 for (int j = 0; j < size; j++) { 24 if (i < j) { 25 if (Double.isInfinite(this.get(i, j))) { 26 26 result = result + " -------"; 27 } else { 28 result = result 29 + String.format("%+8.2f", this.get(i, j)); 27 30 } 28 else { 29 result = result + String.format("%+8.2f",this.get(i,j)); 30 } 31 } 32 else { 31 } else { 33 32 result = result + (" "); 34 33 } … … 39 38 } 40 39 41 42 43 40 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/manager/ComponentManager.java
r1189 r1733 23 23 /** 24 24 * <p> 25 * The component manager is the central reference for the distinct submodules required for 26 * task tree generation. Such include the temporal relationship rule manager, the task equality 27 * rule manager, the default task builder, as well as the default task factory. 25 * The component manager is the central reference for the distinct submodules 26 * required for task tree generation. Such include the temporal relationship 27 * rule manager, the task equality rule manager, the default task builder, as 28 * well as the default task factory. 28 29 * </p> 29 30 * … … 32 33 */ 33 34 public class ComponentManager { 34 35 /**36 * <p>37 * singleton instance of this class38 * </p>39 */40 private static ComponentManager instance;41 35 42 /** 43 * <p> 44 * the default temporal relationship rule manager 45 * </p> 46 */ 47 private TemporalRelationshipRuleManager temporalRelationshipRuleManager; 36 /** 37 * <p> 38 * clears the singleton instance. Needed for test purposes to ensure 39 * statelessness between tests. 40 * </p> 41 */ 42 public static synchronized void clearInstance() { 43 instance = null; 44 } 48 45 49 /** 50 * <p> 51 * the default task builder 52 * </p> 53 */ 54 private ITaskBuilder taskBuilder; 46 /** 47 * <p> 48 * returns the default task builder 49 * </p> 50 * 51 * @return as described 52 */ 53 public static ITaskBuilder getDefaultTaskBuilder() { 54 return getInstance().taskBuilder; 55 } 55 56 56 /** 57 * <p> 58 * the default task factory 59 * </p> 60 */ 61 private ITaskFactory taskFactory; 57 /** 58 * <p> 59 * returns the default task factory 60 * </p> 61 * 62 * @return as described 63 */ 64 public static ITaskFactory getDefaultTaskFactory() { 65 return getInstance().taskFactory; 66 } 62 67 63 /** 64 * <p> 65 * returns the default temporal relationship rule manager 66 * </p> 67 * 68 * @return as described 69 */ 70 public static TemporalRelationshipRuleManager getTemporalRelationshipRuleManager() { 71 return getInstance().temporalRelationshipRuleManager; 72 } 68 /** 69 * <p> 70 * returns the singleton instance of this class 71 * </p> 72 * 73 * @return as described 74 */ 75 private static synchronized ComponentManager getInstance() { 76 if (instance == null) { 77 instance = new ComponentManager(); 78 instance.init(); 79 } 80 return instance; 81 } 73 82 74 75 76 * returns the default task builder77 78 79 80 81 public static ITaskBuilder getDefaultTaskBuilder() {82 return getInstance().taskBuilder;83 83 /** 84 * <p> 85 * returns the default temporal relationship rule manager 86 * </p> 87 * 88 * @return as described 89 */ 90 public static TemporalRelationshipRuleManager getTemporalRelationshipRuleManager() { 91 return getInstance().temporalRelationshipRuleManager; 92 } 84 93 85 /** 86 * <p> 87 * returns the default task factory 88 * </p> 89 * 90 * @return as described 91 */ 92 public static ITaskFactory getDefaultTaskFactory() { 93 return getInstance().taskFactory; 94 } 94 /** 95 * <p> 96 * singleton instance of this class 97 * </p> 98 */ 99 private static ComponentManager instance; 95 100 96 /** 97 * <p> 98 * clears the singleton instance. Needed for test purposes to ensure statelessness between 99 * tests. 100 * </p> 101 */ 102 public static synchronized void clearInstance() { 103 instance = null; 104 } 101 /** 102 * <p> 103 * the default temporal relationship rule manager 104 * </p> 105 */ 106 private TemporalRelationshipRuleManager temporalRelationshipRuleManager; 105 107 106 /** 107 * <p> 108 * returns the singleton instance of this class 109 * </p> 110 * 111 * @return as described 112 */ 113 private static synchronized ComponentManager getInstance() { 114 if (instance == null) { 115 instance = new ComponentManager(); 116 instance.init(); 117 } 118 return instance; 119 } 108 /** 109 * <p> 110 * the default task builder 111 * </p> 112 */ 113 private ITaskBuilder taskBuilder; 120 114 121 /** 122 * <p> 123 * initialized the component manager with all it default components which are the temporal 124 * relationship rule manager, the task equality rule manager, the default task builder, as 125 * well as the default task factory. 126 * </p> 127 */ 128 private void init() { 129 taskBuilder = new TaskBuilder(); 130 taskFactory = new TaskFactory(); 115 /** 116 * <p> 117 * the default task factory 118 * </p> 119 */ 120 private ITaskFactory taskFactory; 131 121 132 temporalRelationshipRuleManager = 133 new TemporalRelationshipRuleManager(taskFactory, taskBuilder); 134 temporalRelationshipRuleManager.init(); 135 } 122 /** 123 * <p> 124 * initialized the component manager with all it default components which 125 * are the temporal relationship rule manager, the task equality rule 126 * manager, the default task builder, as well as the default task factory. 127 * </p> 128 */ 129 private void init() { 130 taskBuilder = new TaskBuilder(); 131 taskFactory = new TaskFactory(); 132 133 temporalRelationshipRuleManager = new TemporalRelationshipRuleManager( 134 taskFactory, taskBuilder); 135 temporalRelationshipRuleManager.init(); 136 } 136 137 137 138 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/manager/TaskTreeManager.java
r1397 r1733 30 30 /** 31 31 * <p> 32 * The task tree manager is responsible for transforming one or more user sessions into a task 33 * model. It can be called by providing a collection of user sessions where the result 34 * will be a task model. Furthermore, it can be used by providing single events in their respective 35 * order including notifications about where a user session ends. The result is a task model, 36 * as well. 32 * The task tree manager is responsible for transforming one or more user 33 * sessions into a task model. It can be called by providing a collection of 34 * user sessions where the result will be a task model. Furthermore, it can be 35 * used by providing single events in their respective order including 36 * notifications about where a user session ends. The result is a task model, as 37 * well. 37 38 * </p> 38 39 * … … 41 42 */ 42 43 public class TaskTreeManager { 43 44 /**45 * <p>46 * the internally used task builder47 * </p>48 */49 private ITaskBuilder taskBuilder = ComponentManager.getDefaultTaskBuilder();50 44 51 /** 52 * <p> 53 * the internally used task factory 54 * </p> 55 */ 56 private ITaskFactory taskFactory = ComponentManager.getDefaultTaskFactory(); 45 /** 46 * <p> 47 * the internally used task builder 48 * </p> 49 */ 50 private final ITaskBuilder taskBuilder = ComponentManager 51 .getDefaultTaskBuilder(); 57 52 58 /** 59 * <p> 60 * if single events are provided, the user sessions collected so far 61 * </p> 62 */ 63 private List<IUserSession> sessions = null; 53 /** 54 * <p> 55 * the internally used task factory 56 * </p> 57 */ 58 private final ITaskFactory taskFactory = ComponentManager 59 .getDefaultTaskFactory(); 64 60 65 66 67 * if single events are provided, the currently collected user session 68 69 70 private IUserSession currentSession= null;61 /** 62 * <p> 63 * if single events are provided, the user sessions collected so far 64 * </p> 65 */ 66 private List<IUserSession> sessions = null; 71 67 72 /** 73 * <p> 74 * initializes the task tree manager 75 * </p> 76 */ 77 public TaskTreeManager() { 78 sessions = new LinkedList<IUserSession>(); 79 } 68 /** 69 * <p> 70 * if single events are provided, the currently collected user session 71 * </p> 72 */ 73 private IUserSession currentSession = null; 80 74 81 /** 82 * <p> 83 * creates a task model based on the provided user sessions. Yet, the user sessions are 84 * list of events. Such will be transformed in into task instances of event tasks assigned 85 * to {@link IUserSession}s. The {@link IUserSession}s will then be restructured using 86 * the temporal relationship rule manager to detect tasks and respective instances. The 87 * results of this transformation is stored in a task model which is the return value of 88 * this method. 89 * </p> 90 * 91 * @param newSessions the user sessions of which the task model shall be created 92 * 93 * @return the task model created from the user sessions 94 * 95 * @throws IllegalStateException if the task manager is already used by providing it with 96 * single events 97 */ 98 public synchronized ITaskModel createTaskModel(Collection<List<Event>> newSessions) { 99 if ((currentSession != null) || (sessions.size() > 0)) { 100 throw new IllegalStateException("do not mix calls to this method with calls to the " + 101 "other methods for handling tasks. Use only one " + 102 "variant instead."); 103 } 104 105 for (List<Event> newSession : newSessions) { 106 if (newSession.size() > 0) { 107 for (Event event : newSession) { 108 handleNewEvent(event); 109 } 110 finishSession(); 111 } 112 } 113 114 return getTaskModel(); 115 } 75 /** 76 * <p> 77 * initializes the task tree manager 78 * </p> 79 */ 80 public TaskTreeManager() { 81 sessions = new LinkedList<IUserSession>(); 82 } 116 83 117 /** 118 * <p> 119 * handles a single event that occurred in a user session. 120 * </p> 121 * 122 * @param event the event to handle 123 */ 124 public void handleNewEvent(Event event) { 125 assertSessionSequence(); 126 String description = event.getType().getName() + " \u21D2 " + event.getTarget(); 127 IEventTask eventTask = taskFactory.createNewEventTask(description); 128 taskBuilder.addExecutedTask 129 (currentSession, taskFactory.createNewTaskInstance(eventTask, event)); 130 } 84 /** 85 * <p> 86 * internally asserts that there is a current session to add new events to 87 * </p> 88 */ 89 private void assertSessionSequence() { 90 if (currentSession == null) { 91 currentSession = taskFactory.createUserSession(); 92 } 93 } 131 94 132 /** 133 * <p> 134 * used to denote, that all previously added events using {@link #handleNewEvent(Event)} 135 * belong to the same session and that this session is now complete. All further events 136 * will be added to a new session which may be ended using this method, as well. 137 * </p> 138 */ 139 public void finishSession() { 140 if ((currentSession != null) && (currentSession.size() > 0)) { 141 sessions.add(currentSession); 142 currentSession = null; 143 } 144 } 95 /** 96 * <p> 97 * creates a task model based on the provided user sessions. Yet, the user 98 * sessions are list of events. Such will be transformed in into task 99 * instances of event tasks assigned to {@link IUserSession}s. The 100 * {@link IUserSession}s will then be restructured using the temporal 101 * relationship rule manager to detect tasks and respective instances. The 102 * results of this transformation is stored in a task model which is the 103 * return value of this method. 104 * </p> 105 * 106 * @param newSessions 107 * the user sessions of which the task model shall be created 108 * 109 * @return the task model created from the user sessions 110 * 111 * @throws IllegalStateException 112 * if the task manager is already used by providing it with 113 * single events 114 */ 115 public synchronized ITaskModel createTaskModel( 116 Collection<List<Event>> newSessions) { 117 if ((currentSession != null) || (sessions.size() > 0)) { 118 throw new IllegalStateException( 119 "do not mix calls to this method with calls to the " 120 + "other methods for handling tasks. Use only one " 121 + "variant instead."); 122 } 145 123 146 /** 147 * <p> 148 * returns the task model, that belongs to the events in the user sessions collected so far. 149 * </p> 150 * 151 * @return the task model 152 */ 153 public synchronized ITaskModel getTaskModel() { 154 finishSession(); 155 156 Console.traceln(Level.INFO, "applying temporal relationship generation rules"); 157 158 ComponentManager.getTemporalRelationshipRuleManager().applyRules(sessions); 124 for (final List<Event> newSession : newSessions) { 125 if (newSession.size() > 0) { 126 for (final Event event : newSession) { 127 handleNewEvent(event); 128 } 129 finishSession(); 130 } 131 } 159 132 160 return taskFactory.createTaskModel(sessions);161 133 return getTaskModel(); 134 } 162 135 163 /** 164 * <p> 165 * internally asserts that there is a current session to add new events to 166 * </p> 167 */ 168 private void assertSessionSequence() { 169 if (currentSession == null) { 170 currentSession = taskFactory.createUserSession(); 171 } 172 } 136 /** 137 * <p> 138 * used to denote, that all previously added events using 139 * {@link #handleNewEvent(Event)} belong to the same session and that this 140 * session is now complete. All further events will be added to a new 141 * session which may be ended using this method, as well. 142 * </p> 143 */ 144 public void finishSession() { 145 if ((currentSession != null) && (currentSession.size() > 0)) { 146 sessions.add(currentSession); 147 currentSession = null; 148 } 149 } 150 151 /** 152 * <p> 153 * returns the task model, that belongs to the events in the user sessions 154 * collected so far. 155 * </p> 156 * 157 * @return the task model 158 */ 159 public synchronized ITaskModel getTaskModel() { 160 finishSession(); 161 162 Console.traceln(Level.INFO, 163 "applying temporal relationship generation rules"); 164 165 ComponentManager.getTemporalRelationshipRuleManager().applyRules( 166 sessions); 167 168 return taskFactory.createTaskModel(sessions); 169 } 170 171 /** 172 * <p> 173 * handles a single event that occurred in a user session. 174 * </p> 175 * 176 * @param event 177 * the event to handle 178 */ 179 public void handleNewEvent(Event event) { 180 assertSessionSequence(); 181 final String description = event.getType().getName() + " \u21D2 " 182 + event.getTarget(); 183 final IEventTask eventTask = taskFactory 184 .createNewEventTask(description); 185 taskBuilder.addExecutedTask(currentSession, 186 taskFactory.createNewTaskInstance(eventTask, event)); 187 } 173 188 174 189 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/EventTaskComparisonRule.java
r1294 r1733 24 24 /** 25 25 * <p> 26 * This rule identifies two tasks as lexically equal, if they are both event tasks and27 * if their respective event types and targets equal.26 * This rule identifies two tasks as lexically equal, if they are both event 27 * tasks and if their respective event types and targets equal. 28 28 * </p> 29 29 * … … 31 31 */ 32 32 public class EventTaskComparisonRule implements TaskComparisonRule { 33 34 /* (non-Javadoc)35 * @see TaskComparisonRule#isApplicable(ITask, ITask)36 */37 @Override38 public boolean isApplicable(ITask task1, ITask task2) {39 return (task1 instanceof IEventTask) && (task2 instanceof IEventTask);40 }41 33 42 /* (non-Javadoc) 43 * @see TaskComparisonRule#areLexicallyEqual(ITask, ITask) 44 */ 45 @Override 46 public boolean areLexicallyEqual(ITask task1, ITask task2) { 47 Collection<ITaskInstance> taskInstances1 = task1.getInstances(); 48 Collection<ITaskInstance> taskInstances2 = task2.getInstances(); 49 50 for (ITaskInstance instance1 : taskInstances1) { 51 boolean found = false; 52 53 for (ITaskInstance instance2 : taskInstances2) { 54 if (areLexicallyEqual(instance1, instance2)) { 55 found = true; 56 break; 57 } 58 } 59 60 if (!found) { 61 return false; 62 } 63 } 64 65 return true; 66 } 34 /* 35 * (non-Javadoc) 36 * 37 * @see TaskComparisonRule#areLexicallyEqual(ITask, ITask) 38 */ 39 @Override 40 public boolean areLexicallyEqual(ITask task1, ITask task2) { 41 final Collection<ITaskInstance> taskInstances1 = task1.getInstances(); 42 final Collection<ITaskInstance> taskInstances2 = task2.getInstances(); 67 43 68 /* (non-Javadoc) 69 * @see TaskComparisonRule#areSyntacticallyEqual(ITask, ITask) 70 */ 71 @Override 72 public boolean areSyntacticallyEqual(ITask task1, ITask task2) { 73 return areLexicallyEqual(task1, task2); 74 } 44 for (final ITaskInstance instance1 : taskInstances1) { 45 boolean found = false; 75 46 76 /* (non-Javadoc) 77 * @see TaskComparisonRule#areSemanticallyEqual(ITask, ITask) 78 */ 79 @Override 80 public boolean areSemanticallyEqual(ITask task1, ITask task2) { 81 return areLexicallyEqual(task1, task2); 82 } 47 for (final ITaskInstance instance2 : taskInstances2) { 48 if (areLexicallyEqual(instance1, instance2)) { 49 found = true; 50 break; 51 } 52 } 83 53 84 /* (non-Javadoc) 85 * @see TaskComparisonRule#compare(ITask, ITask) 86 */ 87 @Override 88 public TaskEquality compare(ITask task1, ITask task2) { 89 if (areLexicallyEqual(task1, task2)) { 90 return TaskEquality.LEXICALLY_EQUAL; 91 } 92 else { 93 return TaskEquality.UNEQUAL; 94 } 95 } 54 if (!found) { 55 return false; 56 } 57 } 96 58 97 98 /* (non-Javadoc) 99 * @see TaskComparisonRule#isApplicable(ITaskInstance, ITaskInstance) 100 */ 101 @Override 102 public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2) { 103 return 104 (instance1 instanceof IEventTaskInstance) && (instance2 instanceof IEventTaskInstance); 105 } 59 return true; 60 } 106 61 107 /* (non-Javadoc) 108 * @see TaskComparisonRule#areLexicallyEqual(ITaskInstance, ITaskInstance) 109 */ 110 @Override 111 public boolean areLexicallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 112 IEventTaskInstance eventTask1 = (IEventTaskInstance) instance1; 113 IEventTaskInstance eventTask2 = (IEventTaskInstance) instance2; 114 115 return (eventTask1.getEvent().getType().equals(eventTask2.getEvent().getType()) && 116 eventTask1.getEvent().getTarget().equals(eventTask2.getEvent().getTarget())); 117 } 62 /* 63 * (non-Javadoc) 64 * 65 * @see TaskComparisonRule#areLexicallyEqual(ITaskInstance, ITaskInstance) 66 */ 67 @Override 68 public boolean areLexicallyEqual(ITaskInstance instance1, 69 ITaskInstance instance2) { 70 final IEventTaskInstance eventTask1 = (IEventTaskInstance) instance1; 71 final IEventTaskInstance eventTask2 = (IEventTaskInstance) instance2; 118 72 119 /* (non-Javadoc) 120 * @see TaskComparisonRule#areSyntacticallyEqual(ITaskInstance, ITaskInstance) 121 */ 122 @Override 123 public boolean areSyntacticallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 124 return areLexicallyEqual(instance1, instance2); 125 } 73 return (eventTask1.getEvent().getType() 74 .equals(eventTask2.getEvent().getType()) && eventTask1 75 .getEvent().getTarget() 76 .equals(eventTask2.getEvent().getTarget())); 77 } 126 78 127 /* (non-Javadoc) 128 * @see TaskComparisonRule#areSemanticallyEqual(ITaskInstance, ITaskInstance) 129 */ 130 @Override 131 public boolean areSemanticallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 132 return areLexicallyEqual(instance1, instance2); 133 } 79 /* 80 * (non-Javadoc) 81 * 82 * @see TaskComparisonRule#areSemanticallyEqual(ITask, ITask) 83 */ 84 @Override 85 public boolean areSemanticallyEqual(ITask task1, ITask task2) { 86 return areLexicallyEqual(task1, task2); 87 } 134 88 135 /* (non-Javadoc) 136 * @see TaskComparisonRule#compare(ITaskInstance, ITaskInstance) 137 */ 138 @Override 139 public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) { 140 if (areLexicallyEqual(instance1, instance2)) { 141 return TaskEquality.LEXICALLY_EQUAL; 142 } 143 else { 144 return TaskEquality.UNEQUAL; 145 } 146 } 89 /* 90 * (non-Javadoc) 91 * 92 * @see TaskComparisonRule#areSemanticallyEqual(ITaskInstance, 93 * ITaskInstance) 94 */ 95 @Override 96 public boolean areSemanticallyEqual(ITaskInstance instance1, 97 ITaskInstance instance2) { 98 return areLexicallyEqual(instance1, instance2); 99 } 100 101 /* 102 * (non-Javadoc) 103 * 104 * @see TaskComparisonRule#areSyntacticallyEqual(ITask, ITask) 105 */ 106 @Override 107 public boolean areSyntacticallyEqual(ITask task1, ITask task2) { 108 return areLexicallyEqual(task1, task2); 109 } 110 111 /* 112 * (non-Javadoc) 113 * 114 * @see TaskComparisonRule#areSyntacticallyEqual(ITaskInstance, 115 * ITaskInstance) 116 */ 117 @Override 118 public boolean areSyntacticallyEqual(ITaskInstance instance1, 119 ITaskInstance instance2) { 120 return areLexicallyEqual(instance1, instance2); 121 } 122 123 /* 124 * (non-Javadoc) 125 * 126 * @see TaskComparisonRule#compare(ITask, ITask) 127 */ 128 @Override 129 public TaskEquality compare(ITask task1, ITask task2) { 130 if (areLexicallyEqual(task1, task2)) { 131 return TaskEquality.LEXICALLY_EQUAL; 132 } else { 133 return TaskEquality.UNEQUAL; 134 } 135 } 136 137 /* 138 * (non-Javadoc) 139 * 140 * @see TaskComparisonRule#compare(ITaskInstance, ITaskInstance) 141 */ 142 @Override 143 public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) { 144 if (areLexicallyEqual(instance1, instance2)) { 145 return TaskEquality.LEXICALLY_EQUAL; 146 } else { 147 return TaskEquality.UNEQUAL; 148 } 149 } 150 151 /* 152 * (non-Javadoc) 153 * 154 * @see TaskComparisonRule#isApplicable(ITask, ITask) 155 */ 156 @Override 157 public boolean isApplicable(ITask task1, ITask task2) { 158 return (task1 instanceof IEventTask) && (task2 instanceof IEventTask); 159 } 160 161 /* 162 * (non-Javadoc) 163 * 164 * @see TaskComparisonRule#isApplicable(ITaskInstance, ITaskInstance) 165 */ 166 @Override 167 public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2) { 168 return (instance1 instanceof IEventTaskInstance) 169 && (instance2 instanceof IEventTaskInstance); 170 } 147 171 148 172 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/GUIEventTaskComparisonRule.java
r1294 r1733 50 50 * <p> 51 51 * This rule compares GUI event tasks (i.e. it is more concrete, than the 52 * {@link EventTaskComparisonRule}). Two GUI event tasks are only equal if their event type and 53 * target are equal. The returned equality is even more fine-grained for events whose type is 54 * {@link TextInput} and {@link ValueSelection}. For text inputs, lexical equality is returned if 55 * the same text is entered using the same key interactions. Syntactical equality is returned if 56 * the same text is entered using different key interactions. Semantical equality is returned if 57 * different text is entered, but into the same event target. Value selections are syntactically 58 * equal, if the same value is selected. Otherwise they are semantically equal. 52 * {@link EventTaskComparisonRule}). Two GUI event tasks are only equal if their 53 * event type and target are equal. The returned equality is even more 54 * fine-grained for events whose type is {@link TextInput} and 55 * {@link ValueSelection}. For text inputs, lexical equality is returned if the 56 * same text is entered using the same key interactions. Syntactical equality is 57 * returned if the same text is entered using different key interactions. 58 * Semantical equality is returned if different text is entered, but into the 59 * same event target. Value selections are syntactically equal, if the same 60 * value is selected. Otherwise they are semantically equal. 59 61 * </p> 60 62 * … … 62 64 */ 63 65 public class GUIEventTaskComparisonRule implements TaskComparisonRule { 64 65 /* (non-Javadoc) 66 * @see TaskComparisonRule#isApplicable(ITask, ITask) 67 */ 68 @Override 69 public boolean isApplicable(ITask task1, ITask task2) { 70 for (ITaskInstance instance : task1.getInstances()) { 71 if ((!(instance instanceof IEventTaskInstance)) || 72 (!(((IEventTaskInstance) instance).getEvent().getType() instanceof IInteraction))) 73 { 74 return false; 75 } 76 } 77 78 for (ITaskInstance instance : task2.getInstances()) { 79 if ((!(instance instanceof IEventTaskInstance)) || 80 (!(((IEventTaskInstance) instance).getEvent().getType() instanceof IInteraction))) 81 { 82 return false; 83 } 84 } 85 86 return true; 87 } 88 89 /* (non-Javadoc) 90 * @see TaskComparisonRule#areLexicallyEqual(ITask, ITask) 91 */ 92 @Override 93 public boolean areLexicallyEqual(ITask task1, ITask task2) { 94 TaskEquality equality = getEquality(task1, task2, TaskEquality.LEXICALLY_EQUAL); 95 return (equality != null) && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL)); 96 } 97 98 /* (non-Javadoc) 99 * @see TaskComparisonRule#areSyntacticallyEqual(ITask, ITask) 100 */ 101 @Override 102 public boolean areSyntacticallyEqual(ITask task1, ITask task2) { 103 TaskEquality equality = getEquality(task1, task2, TaskEquality.SYNTACTICALLY_EQUAL); 104 return (equality != null) && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)); 105 } 106 107 /* (non-Javadoc) 108 * @see TaskComparisonRule#areSemanticallyEqual(ITask, ITask) 109 */ 110 @Override 111 public boolean areSemanticallyEqual(ITask task1, ITask task2) { 112 TaskEquality equality = getEquality(task1, task2, TaskEquality.SEMANTICALLY_EQUAL); 113 return (equality != null) && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL)); 114 } 115 116 /* (non-Javadoc) 117 * @see TaskComparisonRule#compare(ITask, ITask) 118 */ 119 @Override 120 public TaskEquality compare(ITask task1, ITask task2) { 121 return getEquality(task1, task2, null); 122 } 123 124 /* (non-Javadoc) 125 * @see de.ugoe.cs.autoquest.tasktrees.taskequality.TaskComparisonRule#isApplicable(de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance, de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance) 126 */ 127 @Override 128 public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2) { 129 return 130 (instance1 instanceof IEventTaskInstance) && 131 (instance2 instanceof IEventTaskInstance) && 132 (((IEventTaskInstance) instance1).getEvent().getType() instanceof IInteraction) && 133 (((IEventTaskInstance) instance1).getEvent().getType() instanceof IInteraction); 134 } 135 136 /* (non-Javadoc) 137 * @see de.ugoe.cs.autoquest.tasktrees.taskequality.TaskComparisonRule#areLexicallyEqual(de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance, de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance) 138 */ 139 @Override 140 public boolean areLexicallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 141 TaskEquality equality = getEquality(instance1, instance2, TaskEquality.LEXICALLY_EQUAL); 142 return (equality != null) && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL)); 143 } 144 145 /* (non-Javadoc) 146 * @see de.ugoe.cs.autoquest.tasktrees.taskequality.TaskComparisonRule#areSyntacticallyEqual(de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance, de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance) 147 */ 148 @Override 149 public boolean areSyntacticallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 150 TaskEquality equality = getEquality(instance1, instance2, TaskEquality.SYNTACTICALLY_EQUAL); 151 return (equality != null) && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)); 152 } 153 154 /* (non-Javadoc) 155 * @see de.ugoe.cs.autoquest.tasktrees.taskequality.TaskComparisonRule#areSemanticallyEqual(de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance, de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance) 156 */ 157 @Override 158 public boolean areSemanticallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 159 TaskEquality equality = getEquality(instance1, instance2, TaskEquality.SEMANTICALLY_EQUAL); 160 return (equality != null) && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL)); 161 } 162 163 /* (non-Javadoc) 164 * @see de.ugoe.cs.autoquest.tasktrees.taskequality.TaskComparisonRule#compare(de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance, de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance) 165 */ 166 @Override 167 public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) { 168 return getEquality(instance1, instance2, null); 169 } 170 171 /** 172 * 173 */ 174 private TaskEquality getEquality(ITask task1, 175 ITask task2, 176 TaskEquality requiredEqualityLevel) 177 { 178 Collection<ITaskInstance> taskInstances1 = task1.getInstances(); 179 Collection<ITaskInstance> taskInstances2 = task2.getInstances(); 180 181 TaskEquality checkedEquality = 182 requiredEqualityLevel != null ? requiredEqualityLevel : TaskEquality.SEMANTICALLY_EQUAL; 183 184 TaskEquality commonDenominator = TaskEquality.LEXICALLY_EQUAL; 185 186 for (ITaskInstance instance1 : taskInstances1) { 187 TaskEquality mostConcreteEquality = null; 188 189 for (ITaskInstance instance2 : taskInstances2) { 190 TaskEquality equality = getEquality(instance1, instance2, requiredEqualityLevel); 191 192 if ((equality != null) && ((mostConcreteEquality == null) || 193 (equality.isAtLeast(mostConcreteEquality)))) 194 { 195 mostConcreteEquality = equality; 196 197 if (((requiredEqualityLevel != null) && 198 (mostConcreteEquality.isAtLeast(requiredEqualityLevel))) || 199 (mostConcreteEquality.isAtLeast(TaskEquality.LEXICALLY_EQUAL))) 200 { 201 break; 202 } 203 } 204 } 205 206 commonDenominator = commonDenominator.getCommonDenominator(mostConcreteEquality); 207 208 if (!commonDenominator.isAtLeast(checkedEquality)) { 209 return TaskEquality.UNEQUAL; 210 } 211 } 212 213 return commonDenominator; 214 } 215 216 /** 217 * 218 */ 219 private TaskEquality getEquality(ITaskInstance instance1, 220 ITaskInstance instance2, 221 TaskEquality requiredEqualityLevel) 222 { 223 IEventTaskInstance eventTask1 = (IEventTaskInstance) instance1; 224 IEventTaskInstance eventTask2 = (IEventTaskInstance) instance2; 225 226 if (!eventTask1.getEvent().getTarget().equals(eventTask2.getEvent().getTarget())) { 227 return TaskEquality.UNEQUAL; 228 } 229 230 IInteraction interaction1 = (IInteraction) eventTask1.getEvent().getType(); 231 IInteraction interaction2 = (IInteraction) eventTask2.getEvent().getType(); 232 233 return compareInteractions 234 (interaction1, interaction2, eventTask1.getEvent().getTarget(), requiredEqualityLevel); 235 } 236 237 /** 238 * <p> 239 * compares two interactions. The method delegates to other, more specific compare method, e.g., 240 * {@link #compareTextInputs(TextInput, TextInput)} and 241 * {@link #compareValueSelections(ValueSelection, ValueSelection)}, if any exist for the 242 * concrete interaction types. Otherwise it uses the equals method of the interactions for 243 * comparison. In this case, if the interactions equals method returns true, this method 244 * returns lexical equality. 245 * </p> 246 * <p> 247 * The provided equality level can be used to restrict the quality check to the given level. 248 * This is done for optimization purposes. The returned equality level can be at most as 249 * concrete as the provided one. If the provided one is null, it is expected to be lexical 250 * equality. 251 * </p> 252 * 253 * @param interaction1 the first interaction to compare 254 * @param interaction2 the second interaction to compare 255 * @param eventTarget the event target on which the interactions happened (used within 256 * special comparisons like mouse clicks on buttons, where the coordinates 257 * can be ignored) 258 * @param equalityLevel the equality level to be checked for 259 * 260 * @return as described 261 */ 262 private TaskEquality compareInteractions(IInteraction interaction1, 263 IInteraction interaction2, 264 IEventTarget eventTarget, 265 TaskEquality equalityLevel) 266 { 267 TaskEquality level = equalityLevel; 268 269 if (level == null) { 270 level = TaskEquality.LEXICALLY_EQUAL; 271 } 272 273 if (interaction1 == interaction2) { 274 return TaskEquality.LEXICALLY_EQUAL; 275 } 276 else if ((interaction1 instanceof KeyInteraction) && 277 (interaction2 instanceof KeyInteraction)) 278 { 279 return compareKeyInteractions 280 ((KeyInteraction) interaction1, (KeyInteraction) interaction2, level); 281 } 282 else if ((interaction1 instanceof MouseButtonInteraction) && 283 (interaction2 instanceof MouseButtonInteraction)) 284 { 285 return compareMouseButtonInteractions 286 ((MouseButtonInteraction) interaction1, (MouseButtonInteraction) interaction2, 287 eventTarget, level); 288 } 289 else if ((interaction1 instanceof Scroll) && (interaction2 instanceof Scroll)) { 290 return compareScrolls((Scroll) interaction1, (Scroll) interaction2, level); 291 } 292 else if ((interaction1 instanceof TextInput) && (interaction2 instanceof TextInput)) { 293 return compareTextInputs 294 ((TextInput) interaction1, (TextInput) interaction2, level); 295 } 296 else if ((interaction1 instanceof ValueSelection) && 297 (interaction2 instanceof ValueSelection)) 298 { 299 return compareValueSelections 300 ((ValueSelection<?>) interaction1, (ValueSelection<?>) interaction2, level); 301 } 302 else if (interaction1.equals(interaction2)) { 303 return TaskEquality.LEXICALLY_EQUAL; 304 } 305 else { 306 return TaskEquality.UNEQUAL; 307 } 308 } 309 310 /** 311 * <p> 312 * compares two key interactions. If both are of the same type and if both have the 313 * same key, they are lexically equal. If both are only of the same type, they are 314 * semantically equal. Otherwise, they are unequal. 315 * </p> 316 * <p> 317 * The provided equality level can be used to restrict the quality check to the given level. 318 * This is done for optimization purposes. The returned equality level is as concrete as 319 * the provided one. It may be more concrete if there is no difference regarding the 320 * comparison on the levels. 321 * </p> 322 * 323 * @param interaction1 the first key interaction 324 * @param interaction2 the second key interaction 325 * @param equalityLevel the equality level to be checked for 326 * 327 * @return as described 328 */ 329 private TaskEquality compareKeyInteractions(KeyInteraction interaction1, 330 KeyInteraction interaction2, 331 TaskEquality equalityLevel) 332 { 333 if (((interaction1 instanceof KeyPressed) && (interaction2 instanceof KeyPressed)) || 334 ((interaction1 instanceof KeyReleased) && (interaction2 instanceof KeyReleased)) || 335 ((interaction1 instanceof KeyTyped) && (interaction2 instanceof KeyTyped))) 336 { 337 if ((equalityLevel.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)) && 338 (interaction1.getKey() == interaction2.getKey())) 339 { 340 return TaskEquality.LEXICALLY_EQUAL; 341 } 342 else { 343 return TaskEquality.SEMANTICALLY_EQUAL; 344 } 345 } 346 347 return TaskEquality.UNEQUAL; 348 } 349 350 /** 351 * <p> 352 * compares two mouse drag and drops. If both drag and drops have the same start and end 353 * coordinates, they are lexically equal. Otherwise, they are semantically equal. 354 * </p> 355 * <p> 356 * The provided equality level can be used to restrict the quality check to the given level. 357 * This is done for optimization purposes. The returned equality level is as concrete as 358 * the provided one. It may be more concrete if there is no difference regarding the 359 * comparison on the levels. 360 * </p> 361 * 362 * @param interaction1 the first mouse drag and drop to compare 363 * @param interaction2 the second mouse drag and drop to compare 364 * @param equalityLevel the equality level to be checked for 365 * 366 * @return as described 367 */ 368 private TaskEquality compareMouseDragAndDrops(MouseDragAndDrop interaction1, 369 MouseDragAndDrop interaction2, 370 TaskEquality equalityLevel) 371 { 372 if (interaction1.getButton() != interaction2.getButton()) { 373 return TaskEquality.UNEQUAL; 374 } 375 376 if (equalityLevel.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)) { 377 int x1 = interaction1.getX(); 378 int x1Start = interaction1.getXStart(); 379 int x2 = interaction2.getX(); 380 int x2Start = interaction2.getXStart(); 381 int y1 = interaction1.getY(); 382 int y1Start = interaction1.getYStart(); 383 int y2 = interaction2.getY(); 384 int y2Start = interaction2.getYStart(); 385 386 if ((x1Start == x2Start) && (x1 == x2) && (y1Start == y2Start) && (y1 == y2)) { 387 return TaskEquality.LEXICALLY_EQUAL; 388 } 389 } 390 391 return TaskEquality.SEMANTICALLY_EQUAL; 392 } 393 394 /** 395 * <p> 396 * compares two mouse button interactions such as clicks, mouse button down, or double clicks. 397 * If both interactions have the same coordinates, they are lexically equal. Otherwise, they 398 * are semantically equal. Mouse clicks for which the coordinates make no lexical difference 399 * (see {@link #clickCoordinatesMakeLexicalDifference(IEventTarget)}) are treated as 400 * lexically equal. 401 * </p> 402 * <p> 403 * The provided equality level can be used to restrict the quality check to the given level. 404 * This is done for optimization purposes. The returned equality level is as concrete as 405 * the provided one. It may be more concrete if there is no difference regarding the 406 * comparison on the levels. 407 * </p> 408 * 409 * @param interaction1 the first mouse button interaction to compare 410 * @param interaction2 the second mouse button interaction to compare 411 * @param eventTarget the event target on which the interactions happened (used within 412 * special comparisons like mouse clicks on buttons, where the coordinates 413 * can be ignored) 414 * @param equalityLevel the equality level to be checked for 415 * 416 * @return as described 417 */ 418 private TaskEquality compareMouseButtonInteractions(MouseButtonInteraction interaction1, 419 MouseButtonInteraction interaction2, 420 IEventTarget eventTarget, 421 TaskEquality equalityLevel) 422 { 423 boolean coordinatesMatch = true; 424 425 if ((interaction1 instanceof MouseDragAndDrop) && 426 (interaction2 instanceof MouseDragAndDrop)) 427 { 428 return compareMouseDragAndDrops 429 ((MouseDragAndDrop) interaction1, (MouseDragAndDrop) interaction2, equalityLevel); 430 } 431 else if (interaction1.getButton() != interaction2.getButton()) { 432 return TaskEquality.UNEQUAL; 433 } 434 else if (equalityLevel.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL) && 435 clickCoordinatesMakeLexicalDifference(eventTarget)) 436 { 437 int x1 = interaction1.getX(); 438 int x2 = interaction2.getX(); 439 int y1 = interaction1.getY(); 440 int y2 = interaction2.getY(); 441 442 if ((x1 != x2) || (y1 != y2)) { 443 coordinatesMatch = false; 444 } 445 } 446 447 // up to now, they can be equal. Now check the types. Do it as last action as these 448 // checks take the most time and should, therefore, only be done latest 449 if (((interaction1 instanceof MouseClick) && (interaction2 instanceof MouseClick)) || 450 ((interaction1 instanceof MouseDoubleClick) && 451 (interaction2 instanceof MouseDoubleClick)) || 452 ((interaction1 instanceof MouseButtonDown) && 453 (interaction2 instanceof MouseButtonDown)) || 454 ((interaction1 instanceof MouseButtonUp) && 455 (interaction2 instanceof MouseButtonUp))) 456 { 457 if (coordinatesMatch) { 458 return TaskEquality.LEXICALLY_EQUAL; 459 } 460 else { 461 return TaskEquality.SEMANTICALLY_EQUAL; 462 } 463 } 464 465 return TaskEquality.UNEQUAL; 466 } 467 468 /** 469 * <p> 470 * compares two mouse button interactions such as clicks, mouse button down, or double clicks. 471 * If both interactions have the same coordinates, they are lexically equal. Otherwise, they 472 * are semantically equal. Mouse clicks for which the coordinates make no lexical difference 473 * (see {@link #clickCoordinatesMakeLexicalDifference(IEventTarget)}) are treated as 474 * lexically equal. 475 * </p> 476 * <p> 477 * The provided equality level can be used to restrict the quality check to the given level. 478 * This is done for optimization purposes. The returned equality level is as concrete as 479 * the provided one. It may be more concrete if there is no difference regarding the 480 * comparison on the levels. 481 * </p> 482 * 483 * @param interaction1 the first mouse button interaction to compare 484 * @param interaction2 the second mouse button interaction to compare 485 * @param eventTarget the event target on which the interactions happened (used within 486 * special comparisons like mouse clicks on buttons, where the coordinates 487 * can be ignored) 488 * @param equalityLevel the equality level to be checked for 489 * 490 * @return as described 491 */ 492 private TaskEquality compareScrolls(Scroll interaction1, 493 Scroll interaction2, 494 TaskEquality equalityLevel) 495 { 496 if (equalityLevel.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)) { 497 int x1 = interaction1.getXPosition(); 498 int x2 = interaction2.getXPosition(); 499 int y1 = interaction1.getYPosition(); 500 int y2 = interaction2.getYPosition(); 501 502 if ((x1 == x2) && (y1 == y2)) { 503 return TaskEquality.LEXICALLY_EQUAL; 504 } 505 } 506 507 return TaskEquality.SEMANTICALLY_EQUAL; 508 } 509 510 /** 511 * <p> 512 * compares two text inputs. If both text inputs have the same entered text and text input 513 * events, they are lexically equal. If they only have the same entered text, they are 514 * syntactically equal. If they are only both text inputs, they are semantically equal. 515 * (the equality of the event targets is checked beforehand). 516 * </p> 517 * <p> 518 * The provided equality level can be used to restrict the quality check to the given level. 519 * This is done for optimization purposes. The returned equality level is as concrete as 520 * the provided one. It may be more concrete if there is no difference regarding the 521 * comparison on the levels. 522 * </p> 523 * 524 * @param interaction1 the first text input to compare 525 * @param interaction2 the second text input to compare 526 * @param equalityLevel the equality level to be checked for 527 * 528 * @return as described 529 */ 530 private TaskEquality compareTextInputs(TextInput interaction1, 531 TextInput interaction2, 532 TaskEquality equalityLevel) 533 { 534 switch (equalityLevel) { 535 case LEXICALLY_EQUAL: 536 if (interaction1.getTextInputEvents().equals(interaction2.getTextInputEvents())) { 537 return TaskEquality.LEXICALLY_EQUAL; 538 } 539 // fall through 540 case SYNTACTICALLY_EQUAL: 541 if (interaction1.getEnteredText().equals(interaction2.getEnteredText())) { 542 return TaskEquality.SYNTACTICALLY_EQUAL; 543 } 544 // fall through 545 case SEMANTICALLY_EQUAL: 546 return TaskEquality.SEMANTICALLY_EQUAL; 547 default: 548 return TaskEquality.UNEQUAL; 549 } 550 } 551 552 /** 553 * <p> 554 * compares two value selections. If both value selections have the same selected value, they 555 * are syntactically equal, otherwise they are semantically equal. 556 * (the equality of the event targets is checked beforehand). 557 * </p> 558 * <p> 559 * The provided equality level can be used to restrict the quality check to the given level. 560 * This is done for optimization purposes. The returned equality level is as concrete as 561 * the provided one. It may be more concrete if there is no difference regarding the 562 * comparison on the levels. 563 * </p> 564 * 565 * @param interaction1 the first value selection to compare 566 * @param interaction2 the second value selection to compare 567 * @param equalityLevel the equality level to be checked for 568 * 569 * @return as described 570 */ 571 private TaskEquality compareValueSelections(ValueSelection<?> interaction1, 572 ValueSelection<?> interaction2, 573 TaskEquality equalityLevel) 574 { 575 if (equalityLevel.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)) { 576 Object value1 = interaction1.getSelectedValue(); 577 Object value2 = interaction2.getSelectedValue(); 578 579 if ((value1 == value2) || ((value1 != null) && (value1.equals(value2)))) { 580 return TaskEquality.LEXICALLY_EQUAL; 581 } 582 } 583 584 return TaskEquality.SEMANTICALLY_EQUAL; 585 } 586 587 /** 588 * <p> 589 * Checks, if the coordinates of a click or double click on the provided event target makes 590 * a lexical difference. Mouse clicks and double clicks on buttons, check boxes, 591 * combo boxes, images, list boxes, menu buttons, radio buttons, shapes, uneditable text, 592 * and tool tips have no lexical difference as long as they happen on the same event target. 593 * The concrete coordinates are not relevant. 594 * </p> 595 * 596 * @param eventTarget the event target on which the interaction occurred 597 * 598 * @return if the coordinates are important to be considered for clicks and double clicks, 599 * false else 600 */ 601 private boolean clickCoordinatesMakeLexicalDifference(IEventTarget eventTarget) { 602 if ((eventTarget instanceof IButton) || 603 (eventTarget instanceof ICheckBox) || 604 (eventTarget instanceof IComboBox) || 605 (eventTarget instanceof IImage) || 606 (eventTarget instanceof IListBox) || 607 (eventTarget instanceof IMenu) || 608 (eventTarget instanceof IMenuButton) || 609 (eventTarget instanceof IRadioButton) || 610 (eventTarget instanceof IShape) || 611 (eventTarget instanceof IText) || 612 (eventTarget instanceof IToolTip)) 613 { 614 return false; 615 } 616 else { 617 return true; 618 } 619 } 66 67 /* 68 * (non-Javadoc) 69 * 70 * @see TaskComparisonRule#areLexicallyEqual(ITask, ITask) 71 */ 72 @Override 73 public boolean areLexicallyEqual(ITask task1, ITask task2) { 74 final TaskEquality equality = getEquality(task1, task2, 75 TaskEquality.LEXICALLY_EQUAL); 76 return (equality != null) 77 && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL)); 78 } 79 80 /* 81 * (non-Javadoc) 82 * 83 * @see de.ugoe.cs.autoquest.tasktrees.taskequality.TaskComparisonRule# 84 * areLexicallyEqual(de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance, 85 * de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance) 86 */ 87 @Override 88 public boolean areLexicallyEqual(ITaskInstance instance1, 89 ITaskInstance instance2) { 90 final TaskEquality equality = getEquality(instance1, instance2, 91 TaskEquality.LEXICALLY_EQUAL); 92 return (equality != null) 93 && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL)); 94 } 95 96 /* 97 * (non-Javadoc) 98 * 99 * @see TaskComparisonRule#areSemanticallyEqual(ITask, ITask) 100 */ 101 @Override 102 public boolean areSemanticallyEqual(ITask task1, ITask task2) { 103 final TaskEquality equality = getEquality(task1, task2, 104 TaskEquality.SEMANTICALLY_EQUAL); 105 return (equality != null) 106 && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL)); 107 } 108 109 /* 110 * (non-Javadoc) 111 * 112 * @see de.ugoe.cs.autoquest.tasktrees.taskequality.TaskComparisonRule# 113 * areSemanticallyEqual 114 * (de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance, 115 * de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance) 116 */ 117 @Override 118 public boolean areSemanticallyEqual(ITaskInstance instance1, 119 ITaskInstance instance2) { 120 final TaskEquality equality = getEquality(instance1, instance2, 121 TaskEquality.SEMANTICALLY_EQUAL); 122 return (equality != null) 123 && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL)); 124 } 125 126 /* 127 * (non-Javadoc) 128 * 129 * @see TaskComparisonRule#areSyntacticallyEqual(ITask, ITask) 130 */ 131 @Override 132 public boolean areSyntacticallyEqual(ITask task1, ITask task2) { 133 final TaskEquality equality = getEquality(task1, task2, 134 TaskEquality.SYNTACTICALLY_EQUAL); 135 return (equality != null) 136 && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)); 137 } 138 139 /* 140 * (non-Javadoc) 141 * 142 * @see de.ugoe.cs.autoquest.tasktrees.taskequality.TaskComparisonRule# 143 * areSyntacticallyEqual 144 * (de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance, 145 * de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance) 146 */ 147 @Override 148 public boolean areSyntacticallyEqual(ITaskInstance instance1, 149 ITaskInstance instance2) { 150 final TaskEquality equality = getEquality(instance1, instance2, 151 TaskEquality.SYNTACTICALLY_EQUAL); 152 return (equality != null) 153 && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)); 154 } 155 156 /** 157 * <p> 158 * Checks, if the coordinates of a click or double click on the provided 159 * event target makes a lexical difference. Mouse clicks and double clicks 160 * on buttons, check boxes, combo boxes, images, list boxes, menu buttons, 161 * radio buttons, shapes, uneditable text, and tool tips have no lexical 162 * difference as long as they happen on the same event target. The concrete 163 * coordinates are not relevant. 164 * </p> 165 * 166 * @param eventTarget 167 * the event target on which the interaction occurred 168 * 169 * @return if the coordinates are important to be considered for clicks and 170 * double clicks, false else 171 */ 172 private boolean clickCoordinatesMakeLexicalDifference( 173 IEventTarget eventTarget) { 174 if ((eventTarget instanceof IButton) 175 || (eventTarget instanceof ICheckBox) 176 || (eventTarget instanceof IComboBox) 177 || (eventTarget instanceof IImage) 178 || (eventTarget instanceof IListBox) 179 || (eventTarget instanceof IMenu) 180 || (eventTarget instanceof IMenuButton) 181 || (eventTarget instanceof IRadioButton) 182 || (eventTarget instanceof IShape) 183 || (eventTarget instanceof IText) 184 || (eventTarget instanceof IToolTip)) { 185 return false; 186 } else { 187 return true; 188 } 189 } 190 191 /* 192 * (non-Javadoc) 193 * 194 * @see TaskComparisonRule#compare(ITask, ITask) 195 */ 196 @Override 197 public TaskEquality compare(ITask task1, ITask task2) { 198 return getEquality(task1, task2, null); 199 } 200 201 /* 202 * (non-Javadoc) 203 * 204 * @see 205 * de.ugoe.cs.autoquest.tasktrees.taskequality.TaskComparisonRule#compare 206 * (de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance, 207 * de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance) 208 */ 209 @Override 210 public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) { 211 return getEquality(instance1, instance2, null); 212 } 213 214 /** 215 * <p> 216 * compares two interactions. The method delegates to other, more specific 217 * compare method, e.g., {@link #compareTextInputs(TextInput, TextInput)} 218 * and {@link #compareValueSelections(ValueSelection, ValueSelection)}, if 219 * any exist for the concrete interaction types. Otherwise it uses the 220 * equals method of the interactions for comparison. In this case, if the 221 * interactions equals method returns true, this method returns lexical 222 * equality. 223 * </p> 224 * <p> 225 * The provided equality level can be used to restrict the quality check to 226 * the given level. This is done for optimization purposes. The returned 227 * equality level can be at most as concrete as the provided one. If the 228 * provided one is null, it is expected to be lexical equality. 229 * </p> 230 * 231 * @param interaction1 232 * the first interaction to compare 233 * @param interaction2 234 * the second interaction to compare 235 * @param eventTarget 236 * the event target on which the interactions happened (used 237 * within special comparisons like mouse clicks on buttons, where 238 * the coordinates can be ignored) 239 * @param equalityLevel 240 * the equality level to be checked for 241 * 242 * @return as described 243 */ 244 private TaskEquality compareInteractions(IInteraction interaction1, 245 IInteraction interaction2, IEventTarget eventTarget, 246 TaskEquality equalityLevel) { 247 TaskEquality level = equalityLevel; 248 249 if (level == null) { 250 level = TaskEquality.LEXICALLY_EQUAL; 251 } 252 253 if (interaction1 == interaction2) { 254 return TaskEquality.LEXICALLY_EQUAL; 255 } else if ((interaction1 instanceof KeyInteraction) 256 && (interaction2 instanceof KeyInteraction)) { 257 return compareKeyInteractions((KeyInteraction) interaction1, 258 (KeyInteraction) interaction2, level); 259 } else if ((interaction1 instanceof MouseButtonInteraction) 260 && (interaction2 instanceof MouseButtonInteraction)) { 261 return compareMouseButtonInteractions( 262 (MouseButtonInteraction) interaction1, 263 (MouseButtonInteraction) interaction2, eventTarget, level); 264 } else if ((interaction1 instanceof Scroll) 265 && (interaction2 instanceof Scroll)) { 266 return compareScrolls((Scroll) interaction1, (Scroll) interaction2, 267 level); 268 } else if ((interaction1 instanceof TextInput) 269 && (interaction2 instanceof TextInput)) { 270 return compareTextInputs((TextInput) interaction1, 271 (TextInput) interaction2, level); 272 } else if ((interaction1 instanceof ValueSelection) 273 && (interaction2 instanceof ValueSelection)) { 274 return compareValueSelections((ValueSelection<?>) interaction1, 275 (ValueSelection<?>) interaction2, level); 276 } else if (interaction1.equals(interaction2)) { 277 return TaskEquality.LEXICALLY_EQUAL; 278 } else { 279 return TaskEquality.UNEQUAL; 280 } 281 } 282 283 /** 284 * <p> 285 * compares two key interactions. If both are of the same type and if both 286 * have the same key, they are lexically equal. If both are only of the same 287 * type, they are semantically equal. Otherwise, they are unequal. 288 * </p> 289 * <p> 290 * The provided equality level can be used to restrict the quality check to 291 * the given level. This is done for optimization purposes. The returned 292 * equality level is as concrete as the provided one. It may be more 293 * concrete if there is no difference regarding the comparison on the 294 * levels. 295 * </p> 296 * 297 * @param interaction1 298 * the first key interaction 299 * @param interaction2 300 * the second key interaction 301 * @param equalityLevel 302 * the equality level to be checked for 303 * 304 * @return as described 305 */ 306 private TaskEquality compareKeyInteractions(KeyInteraction interaction1, 307 KeyInteraction interaction2, TaskEquality equalityLevel) { 308 if (((interaction1 instanceof KeyPressed) && (interaction2 instanceof KeyPressed)) 309 || ((interaction1 instanceof KeyReleased) && (interaction2 instanceof KeyReleased)) 310 || ((interaction1 instanceof KeyTyped) && (interaction2 instanceof KeyTyped))) { 311 if ((equalityLevel.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)) 312 && (interaction1.getKey() == interaction2.getKey())) { 313 return TaskEquality.LEXICALLY_EQUAL; 314 } else { 315 return TaskEquality.SEMANTICALLY_EQUAL; 316 } 317 } 318 319 return TaskEquality.UNEQUAL; 320 } 321 322 /** 323 * <p> 324 * compares two mouse button interactions such as clicks, mouse button down, 325 * or double clicks. If both interactions have the same coordinates, they 326 * are lexically equal. Otherwise, they are semantically equal. Mouse clicks 327 * for which the coordinates make no lexical difference (see 328 * {@link #clickCoordinatesMakeLexicalDifference(IEventTarget)}) are treated 329 * as lexically equal. 330 * </p> 331 * <p> 332 * The provided equality level can be used to restrict the quality check to 333 * the given level. This is done for optimization purposes. The returned 334 * equality level is as concrete as the provided one. It may be more 335 * concrete if there is no difference regarding the comparison on the 336 * levels. 337 * </p> 338 * 339 * @param interaction1 340 * the first mouse button interaction to compare 341 * @param interaction2 342 * the second mouse button interaction to compare 343 * @param eventTarget 344 * the event target on which the interactions happened (used 345 * within special comparisons like mouse clicks on buttons, where 346 * the coordinates can be ignored) 347 * @param equalityLevel 348 * the equality level to be checked for 349 * 350 * @return as described 351 */ 352 private TaskEquality compareMouseButtonInteractions( 353 MouseButtonInteraction interaction1, 354 MouseButtonInteraction interaction2, IEventTarget eventTarget, 355 TaskEquality equalityLevel) { 356 boolean coordinatesMatch = true; 357 358 if ((interaction1 instanceof MouseDragAndDrop) 359 && (interaction2 instanceof MouseDragAndDrop)) { 360 return compareMouseDragAndDrops((MouseDragAndDrop) interaction1, 361 (MouseDragAndDrop) interaction2, equalityLevel); 362 } else if (interaction1.getButton() != interaction2.getButton()) { 363 return TaskEquality.UNEQUAL; 364 } else if (equalityLevel.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL) 365 && clickCoordinatesMakeLexicalDifference(eventTarget)) { 366 final int x1 = interaction1.getX(); 367 final int x2 = interaction2.getX(); 368 final int y1 = interaction1.getY(); 369 final int y2 = interaction2.getY(); 370 371 if ((x1 != x2) || (y1 != y2)) { 372 coordinatesMatch = false; 373 } 374 } 375 376 // up to now, they can be equal. Now check the types. Do it as last 377 // action as these 378 // checks take the most time and should, therefore, only be done latest 379 if (((interaction1 instanceof MouseClick) && (interaction2 instanceof MouseClick)) 380 || ((interaction1 instanceof MouseDoubleClick) && (interaction2 instanceof MouseDoubleClick)) 381 || ((interaction1 instanceof MouseButtonDown) && (interaction2 instanceof MouseButtonDown)) 382 || ((interaction1 instanceof MouseButtonUp) && (interaction2 instanceof MouseButtonUp))) { 383 if (coordinatesMatch) { 384 return TaskEquality.LEXICALLY_EQUAL; 385 } else { 386 return TaskEquality.SEMANTICALLY_EQUAL; 387 } 388 } 389 390 return TaskEquality.UNEQUAL; 391 } 392 393 /** 394 * <p> 395 * compares two mouse drag and drops. If both drag and drops have the same 396 * start and end coordinates, they are lexically equal. Otherwise, they are 397 * semantically equal. 398 * </p> 399 * <p> 400 * The provided equality level can be used to restrict the quality check to 401 * the given level. This is done for optimization purposes. The returned 402 * equality level is as concrete as the provided one. It may be more 403 * concrete if there is no difference regarding the comparison on the 404 * levels. 405 * </p> 406 * 407 * @param interaction1 408 * the first mouse drag and drop to compare 409 * @param interaction2 410 * the second mouse drag and drop to compare 411 * @param equalityLevel 412 * the equality level to be checked for 413 * 414 * @return as described 415 */ 416 private TaskEquality compareMouseDragAndDrops( 417 MouseDragAndDrop interaction1, MouseDragAndDrop interaction2, 418 TaskEquality equalityLevel) { 419 if (interaction1.getButton() != interaction2.getButton()) { 420 return TaskEquality.UNEQUAL; 421 } 422 423 if (equalityLevel.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)) { 424 final int x1 = interaction1.getX(); 425 final int x1Start = interaction1.getXStart(); 426 final int x2 = interaction2.getX(); 427 final int x2Start = interaction2.getXStart(); 428 final int y1 = interaction1.getY(); 429 final int y1Start = interaction1.getYStart(); 430 final int y2 = interaction2.getY(); 431 final int y2Start = interaction2.getYStart(); 432 433 if ((x1Start == x2Start) && (x1 == x2) && (y1Start == y2Start) 434 && (y1 == y2)) { 435 return TaskEquality.LEXICALLY_EQUAL; 436 } 437 } 438 439 return TaskEquality.SEMANTICALLY_EQUAL; 440 } 441 442 /** 443 * <p> 444 * compares two mouse button interactions such as clicks, mouse button down, 445 * or double clicks. If both interactions have the same coordinates, they 446 * are lexically equal. Otherwise, they are semantically equal. Mouse clicks 447 * for which the coordinates make no lexical difference (see 448 * {@link #clickCoordinatesMakeLexicalDifference(IEventTarget)}) are treated 449 * as lexically equal. 450 * </p> 451 * <p> 452 * The provided equality level can be used to restrict the quality check to 453 * the given level. This is done for optimization purposes. The returned 454 * equality level is as concrete as the provided one. It may be more 455 * concrete if there is no difference regarding the comparison on the 456 * levels. 457 * </p> 458 * 459 * @param interaction1 460 * the first mouse button interaction to compare 461 * @param interaction2 462 * the second mouse button interaction to compare 463 * @param eventTarget 464 * the event target on which the interactions happened (used 465 * within special comparisons like mouse clicks on buttons, where 466 * the coordinates can be ignored) 467 * @param equalityLevel 468 * the equality level to be checked for 469 * 470 * @return as described 471 */ 472 private TaskEquality compareScrolls(Scroll interaction1, 473 Scroll interaction2, TaskEquality equalityLevel) { 474 if (equalityLevel.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)) { 475 final int x1 = interaction1.getXPosition(); 476 final int x2 = interaction2.getXPosition(); 477 final int y1 = interaction1.getYPosition(); 478 final int y2 = interaction2.getYPosition(); 479 480 if ((x1 == x2) && (y1 == y2)) { 481 return TaskEquality.LEXICALLY_EQUAL; 482 } 483 } 484 485 return TaskEquality.SEMANTICALLY_EQUAL; 486 } 487 488 /** 489 * <p> 490 * compares two text inputs. If both text inputs have the same entered text 491 * and text input events, they are lexically equal. If they only have the 492 * same entered text, they are syntactically equal. If they are only both 493 * text inputs, they are semantically equal. (the equality of the event 494 * targets is checked beforehand). 495 * </p> 496 * <p> 497 * The provided equality level can be used to restrict the quality check to 498 * the given level. This is done for optimization purposes. The returned 499 * equality level is as concrete as the provided one. It may be more 500 * concrete if there is no difference regarding the comparison on the 501 * levels. 502 * </p> 503 * 504 * @param interaction1 505 * the first text input to compare 506 * @param interaction2 507 * the second text input to compare 508 * @param equalityLevel 509 * the equality level to be checked for 510 * 511 * @return as described 512 */ 513 private TaskEquality compareTextInputs(TextInput interaction1, 514 TextInput interaction2, TaskEquality equalityLevel) { 515 switch (equalityLevel) { 516 case LEXICALLY_EQUAL: 517 if (interaction1.getTextInputEvents().equals( 518 interaction2.getTextInputEvents())) { 519 return TaskEquality.LEXICALLY_EQUAL; 520 } 521 // fall through 522 case SYNTACTICALLY_EQUAL: 523 if (interaction1.getEnteredText().equals( 524 interaction2.getEnteredText())) { 525 return TaskEquality.SYNTACTICALLY_EQUAL; 526 } 527 // fall through 528 case SEMANTICALLY_EQUAL: 529 return TaskEquality.SEMANTICALLY_EQUAL; 530 default: 531 return TaskEquality.UNEQUAL; 532 } 533 } 534 535 /** 536 * <p> 537 * compares two value selections. If both value selections have the same 538 * selected value, they are syntactically equal, otherwise they are 539 * semantically equal. (the equality of the event targets is checked 540 * beforehand). 541 * </p> 542 * <p> 543 * The provided equality level can be used to restrict the quality check to 544 * the given level. This is done for optimization purposes. The returned 545 * equality level is as concrete as the provided one. It may be more 546 * concrete if there is no difference regarding the comparison on the 547 * levels. 548 * </p> 549 * 550 * @param interaction1 551 * the first value selection to compare 552 * @param interaction2 553 * the second value selection to compare 554 * @param equalityLevel 555 * the equality level to be checked for 556 * 557 * @return as described 558 */ 559 private TaskEquality compareValueSelections(ValueSelection<?> interaction1, 560 ValueSelection<?> interaction2, TaskEquality equalityLevel) { 561 if (equalityLevel.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)) { 562 final Object value1 = interaction1.getSelectedValue(); 563 final Object value2 = interaction2.getSelectedValue(); 564 565 if ((value1 == value2) 566 || ((value1 != null) && (value1.equals(value2)))) { 567 return TaskEquality.LEXICALLY_EQUAL; 568 } 569 } 570 571 return TaskEquality.SEMANTICALLY_EQUAL; 572 } 573 574 /** 575 * 576 */ 577 private TaskEquality getEquality(ITask task1, ITask task2, 578 TaskEquality requiredEqualityLevel) { 579 final Collection<ITaskInstance> taskInstances1 = task1.getInstances(); 580 final Collection<ITaskInstance> taskInstances2 = task2.getInstances(); 581 582 final TaskEquality checkedEquality = requiredEqualityLevel != null ? requiredEqualityLevel 583 : TaskEquality.SEMANTICALLY_EQUAL; 584 585 TaskEquality commonDenominator = TaskEquality.LEXICALLY_EQUAL; 586 587 for (final ITaskInstance instance1 : taskInstances1) { 588 TaskEquality mostConcreteEquality = null; 589 590 for (final ITaskInstance instance2 : taskInstances2) { 591 final TaskEquality equality = getEquality(instance1, instance2, 592 requiredEqualityLevel); 593 594 if ((equality != null) 595 && ((mostConcreteEquality == null) || (equality 596 .isAtLeast(mostConcreteEquality)))) { 597 mostConcreteEquality = equality; 598 599 if (((requiredEqualityLevel != null) && (mostConcreteEquality 600 .isAtLeast(requiredEqualityLevel))) 601 || (mostConcreteEquality 602 .isAtLeast(TaskEquality.LEXICALLY_EQUAL))) { 603 break; 604 } 605 } 606 } 607 608 commonDenominator = commonDenominator 609 .getCommonDenominator(mostConcreteEquality); 610 611 if (!commonDenominator.isAtLeast(checkedEquality)) { 612 return TaskEquality.UNEQUAL; 613 } 614 } 615 616 return commonDenominator; 617 } 618 619 /** 620 * 621 */ 622 private TaskEquality getEquality(ITaskInstance instance1, 623 ITaskInstance instance2, TaskEquality requiredEqualityLevel) { 624 final IEventTaskInstance eventTask1 = (IEventTaskInstance) instance1; 625 final IEventTaskInstance eventTask2 = (IEventTaskInstance) instance2; 626 627 if (!eventTask1.getEvent().getTarget() 628 .equals(eventTask2.getEvent().getTarget())) { 629 return TaskEquality.UNEQUAL; 630 } 631 632 final IInteraction interaction1 = (IInteraction) eventTask1.getEvent() 633 .getType(); 634 final IInteraction interaction2 = (IInteraction) eventTask2.getEvent() 635 .getType(); 636 637 return compareInteractions(interaction1, interaction2, eventTask1 638 .getEvent().getTarget(), requiredEqualityLevel); 639 } 640 641 /* 642 * (non-Javadoc) 643 * 644 * @see TaskComparisonRule#isApplicable(ITask, ITask) 645 */ 646 @Override 647 public boolean isApplicable(ITask task1, ITask task2) { 648 for (final ITaskInstance instance : task1.getInstances()) { 649 if ((!(instance instanceof IEventTaskInstance)) 650 || (!(((IEventTaskInstance) instance).getEvent().getType() instanceof IInteraction))) { 651 return false; 652 } 653 } 654 655 for (final ITaskInstance instance : task2.getInstances()) { 656 if ((!(instance instanceof IEventTaskInstance)) 657 || (!(((IEventTaskInstance) instance).getEvent().getType() instanceof IInteraction))) { 658 return false; 659 } 660 } 661 662 return true; 663 } 664 665 /* 666 * (non-Javadoc) 667 * 668 * @see 669 * de.ugoe.cs.autoquest.tasktrees.taskequality.TaskComparisonRule#isApplicable 670 * (de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance, 671 * de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance) 672 */ 673 @Override 674 public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2) { 675 return (instance1 instanceof IEventTaskInstance) 676 && (instance2 instanceof IEventTaskInstance) 677 && (((IEventTaskInstance) instance1).getEvent().getType() instanceof IInteraction) 678 && (((IEventTaskInstance) instance1).getEvent().getType() instanceof IInteraction); 679 } 620 680 621 681 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/IterationComparisonRule.java
r1294 r1733 23 23 /** 24 24 * <p> 25 * This class is capable of comparing Iterations. Iterations equal at distinct levels 26 * in distinct situations. The following table shows the results of the comparison for the 27 * specific situations (the parameters are commutative). In any other situation, the comparison 28 * returns <code>NodeEquality.UNEQUAL</code>: 25 * This class is capable of comparing Iterations. Iterations equal at distinct 26 * levels in distinct situations. The following table shows the results of the 27 * comparison for the specific situations (the parameters are commutative). In 28 * any other situation, the comparison returns <code>NodeEquality.UNEQUAL</code> 29 * : 29 30 * </p> 30 31 * 31 32 * <table border="1"> 32 * <tr> 33 * <th>iteration 1</th> 34 * <th>iteration 2</th> 35 * <th>comparison result</th> 36 * </tr> 37 * <tr> 38 * <td>any iteration</td> 39 * <td>any iteration with a child that is lexically equal to the child of iteration 1</td> 40 * <td><code>NodeEquality.LEXICALLY_EQUAL</code></td> 41 * </tr> 42 * <tr> 43 * <td>any iteration</td> 44 * <td>any iteration with a child that is syntactically equal to the child of iteration 1</td> 45 * <td><code>NodeEquality.SYNTACTICALLY_EQUAL</code></td> 46 * </tr> 47 * <tr> 48 * <td>any iteration</td> 49 * <td>any iteration with a child that is semantically equal to the child of iteration 1</td> 50 * <td><code>NodeEquality.SEMANTICALLY_EQUAL</code></td> 51 * </tr> 52 * <tr> 53 * <td>an iteration with a selection of syntactically equal children</td> 54 * <td>an iteration with a child that is syntactically equal to the children of the child 55 * selection of iteration 1</td> 56 * <td><code>NodeEquality.SYNTACTICALLY_EQUAL</code></td> 57 * </tr> 58 * <tr> 59 * <td>an iteration with a selection of syntactically equal children</td> 60 * <td>an iteration with a selection of syntactically equal children that are all syntactically 61 * equal to the selection of children of iteration 1</td> 62 * <td><code>NodeEquality.SYNTACTICALLY_EQUAL</code></td> 63 * </tr> 64 * <tr> 65 * <td>an iteration with a selection of semantically equal children</td> 66 * <td>an iteration with a child that is semantically equal to the children of the child 67 * selection of iteration 1</td> 68 * <td><code>NodeEquality.SEMANTICALLY_EQUAL</code></td> 69 * </tr> 70 * <tr> 71 * <td>an iteration with a selection of semantically equal children</td> 72 * <td>an iteration with a selection of semantically equal children that are all semantically 73 * equal to the selection of children of iteration 1</td> 74 * <td><code>NodeEquality.SEMANTICALLY_EQUAL</code></td> 75 * </tr> 33 * <tr> 34 * <th>iteration 1</th> 35 * <th>iteration 2</th> 36 * <th>comparison result</th> 37 * </tr> 38 * <tr> 39 * <td>any iteration</td> 40 * <td>any iteration with a child that is lexically equal to the child of 41 * iteration 1</td> 42 * <td><code>NodeEquality.LEXICALLY_EQUAL</code></td> 43 * </tr> 44 * <tr> 45 * <td>any iteration</td> 46 * <td>any iteration with a child that is syntactically equal to the child of 47 * iteration 1</td> 48 * <td><code>NodeEquality.SYNTACTICALLY_EQUAL</code></td> 49 * </tr> 50 * <tr> 51 * <td>any iteration</td> 52 * <td>any iteration with a child that is semantically equal to the child of 53 * iteration 1</td> 54 * <td><code>NodeEquality.SEMANTICALLY_EQUAL</code></td> 55 * </tr> 56 * <tr> 57 * <td>an iteration with a selection of syntactically equal children</td> 58 * <td>an iteration with a child that is syntactically equal to the children of 59 * the child selection of iteration 1</td> 60 * <td><code>NodeEquality.SYNTACTICALLY_EQUAL</code></td> 61 * </tr> 62 * <tr> 63 * <td>an iteration with a selection of syntactically equal children</td> 64 * <td>an iteration with a selection of syntactically equal children that are 65 * all syntactically equal to the selection of children of iteration 1</td> 66 * <td><code>NodeEquality.SYNTACTICALLY_EQUAL</code></td> 67 * </tr> 68 * <tr> 69 * <td>an iteration with a selection of semantically equal children</td> 70 * <td>an iteration with a child that is semantically equal to the children of 71 * the child selection of iteration 1</td> 72 * <td><code>NodeEquality.SEMANTICALLY_EQUAL</code></td> 73 * </tr> 74 * <tr> 75 * <td>an iteration with a selection of semantically equal children</td> 76 * <td>an iteration with a selection of semantically equal children that are all 77 * semantically equal to the selection of children of iteration 1</td> 78 * <td><code>NodeEquality.SEMANTICALLY_EQUAL</code></td> 79 * </tr> 76 80 * </table> 77 81 * … … 80 84 */ 81 85 public class IterationComparisonRule implements TaskComparisonRule { 82 83 /* (non-Javadoc) 84 * @see TaskComparisonRule#isApplicable(ITask, ITask) 85 */ 86 @Override 87 public boolean isApplicable(ITask task1, ITask task2) { 88 return (task1 instanceof IIteration) && (task2 instanceof IIteration); 89 } 90 91 /* (non-Javadoc) 92 * @see TaskComparisonRule#areLexicallyEqual(ITask, ITask) 93 */ 94 @Override 95 public boolean areLexicallyEqual(ITask task1, ITask task2) { 96 ITask child1 = ((IIteration) task1).getMarkedTask(); 97 ITask child2 = ((IIteration) task2).getMarkedTask(); 98 99 if (child1 != null) { 100 if (child2 == null) { 101 return false; 102 } 103 else { 104 // iterations may have 3 different structures. 105 // 1. they have one child, which is the iterated one 106 // 2. they have a sequence of children, which is iterated 107 // 3. they have a selection of different iterated variants (usually the variants 108 // are semantically equal) 109 // ignore the type of the children but check them for equality. 110 111 return getNodeEquality(child1, child2).isAtLeast(TaskEquality.LEXICALLY_EQUAL); 112 } 113 } 114 else if (child2 == null) { 115 return true; 116 } 117 118 return false; 119 } 120 121 /* (non-Javadoc) 122 * @see TaskComparisonRule#areSyntacticallyEqual(ITask, ITask) 123 */ 124 @Override 125 public boolean areSyntacticallyEqual(ITask task1, ITask task2) { 126 return areLexicallyEqual(task1, task2); 127 } 128 129 /* (non-Javadoc) 130 * @see TaskComparisonRule#areSemanticallyEqual(ITask, ITask) 131 */ 132 @Override 133 public boolean areSemanticallyEqual(ITask task1, ITask task2) { 134 return compare(task1, task2).isAtLeast(TaskEquality.SEMANTICALLY_EQUAL); 135 } 136 137 /* (non-Javadoc) 138 * @see TaskComparisonRule#compare(ITask, ITask) 139 */ 140 @Override 141 public TaskEquality compare(ITask task1, ITask task2) { 142 ITask child1 = ((IIteration) task1).getMarkedTask(); 143 ITask child2 = ((IIteration) task2).getMarkedTask(); 144 145 // if both iterations do not have children, they are equal although this doesn't make sense 146 if ((child1 == null) && (child2 == null)) { 147 return TaskEquality.LEXICALLY_EQUAL; 148 } 149 else if ((child1 == null) || (child2 == null)) { 150 return TaskEquality.UNEQUAL; 151 } 152 153 // iterations may have 3 different structures. 154 // 1. they have one child, which is the iterated one 155 // 2. they have a sequence of children, which is iterated 156 // 3. they have a selection of different iterated variants (usually the variants are 157 // semantically equal) 158 // 159 // the permutations of the three variants in combination must be checked 160 161 // check if both tasks are the same variants of iterations and if their children are equal. 162 // This condition matches, if both iterations are the same variants of iteration. I.e. three 163 // combinations of the permutation are handled herewith. 164 TaskEquality taskEquality = getNodeEquality(child1, child2); 165 166 if (taskEquality != null) { 167 return taskEquality; 168 } 169 170 // compare one iteration with a single task as a child and another one with a selection of 171 // semantically equal tasks 172 return selectionChildrenSemanticallyEqualNode(child1, child2); 173 174 // all other combinations (i.e. sequence with single child and sequence with selection) 175 // can not match 176 } 177 178 /* (non-Javadoc) 179 * @see TaskComparisonRule#isApplicable(ITaskInstance, ITaskInstance) 180 */ 181 @Override 182 public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2) { 183 return isApplicable(instance1.getTask(), instance2.getTask()); 184 } 185 186 /* (non-Javadoc) 187 * @see TaskComparisonRule#areLexicallyEqual(ITaskInstance, ITaskInstance) 188 */ 189 @Override 190 public boolean areLexicallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 191 IIterationInstance iteration1 = (IIterationInstance) instance1; 192 IIterationInstance iteration2 = (IIterationInstance) instance2; 193 194 // if both sequences do not have children, they are equal although this doesn't make sense 195 if ((iteration1.size() == 0) && (iteration2.size() == 0)) { 196 return true; 197 } 198 199 if (iteration1.size() != iteration2.size()) { 200 return false; 201 } 202 203 for (int i = 0; i < iteration1.size(); i++) { 204 ITaskInstance child1 = iteration1.get(i); 205 ITaskInstance child2 = iteration2.get(i); 206 207 TaskEquality taskEquality = 208 callRuleManager(child1, child2, TaskEquality.LEXICALLY_EQUAL); 209 210 if ((taskEquality == null) || (taskEquality == TaskEquality.UNEQUAL)) { 211 return false; 212 } 213 } 214 215 return true; 216 } 217 218 /* (non-Javadoc) 219 * @see TaskComparisonRule#areSyntacticallyEqual(ITaskInstance, ITaskInstance) 220 */ 221 @Override 222 public boolean areSyntacticallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 223 return areLexicallyEqual(instance1, instance2); 224 } 225 226 /* (non-Javadoc) 227 * @see TaskComparisonRule#areSemanticallyEqual(ITaskInstance, ITaskInstance) 228 */ 229 @Override 230 public boolean areSemanticallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 231 return areLexicallyEqual(instance1, instance2); 232 } 233 234 /* (non-Javadoc) 235 * @see TaskComparisonRule#compare(ITaskInstance, ITaskInstance) 236 */ 237 @Override 238 public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) { 239 if (areLexicallyEqual(instance1, instance2)) { 240 return TaskEquality.LEXICALLY_EQUAL; 241 } 242 else { 243 return TaskEquality.UNEQUAL; 244 } 245 } 246 247 /** 248 * <p> 249 * compares two tasks with each other by calling the rule manager. If the rule manager returns 250 * identity, then the returned equality is set to lexically equal. The reason is, that 251 * the children of the iterations are compared and that therefore the distinct iterations 252 * can be at most lexically equal. 253 * </p> 254 * 255 * @param child1 the first task to be compared 256 * @param child2 the second task to be compared 257 * 258 * @return the determined equality being at most lexical equality. 259 */ 260 private TaskEquality getNodeEquality(ITask child1, ITask child2) { 261 TaskEquality taskEquality = callRuleManager(child1, child2, null); 262 263 if (taskEquality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL)) { 264 // prevent, that identical is returned, because the iterations itself are not identical 265 // although the iterated tasks are 266 if (taskEquality == TaskEquality.IDENTICAL) { 267 return TaskEquality.LEXICALLY_EQUAL; 268 } 269 else { 270 return taskEquality; 271 } 272 } 273 274 return TaskEquality.UNEQUAL; 275 } 276 277 /** 278 * <p> 279 * compares two tasks. One of them must be a selection, the other one can be any task. 280 * The method returns a task equality that is not <code>NodeEquality.UNEQUAL</code> 281 * if the other task is at least semantically equal to the children of the selection. It 282 * returns more concrete equalities, if the equality between the other task and the children 283 * of the selection is more concrete. 284 * </p> 285 * 286 * @param task1 the first task to compare 287 * @param task2 the second task to compare 288 * 289 * @return as described 290 */ 291 private TaskEquality selectionChildrenSemanticallyEqualNode(ITask task1, ITask task2) { 292 ISelection selection = null; 293 ITask task = null; 294 if (task1 instanceof ISelection) { 295 selection = (ISelection) task1; 296 task = task2; 297 } 298 else if (task2 instanceof ISelection) { 299 selection = (ISelection) task2; 300 task = task1; 301 } 302 else { 303 return TaskEquality.UNEQUAL; 304 } 305 306 // Iterations, where one has a selection and the other one not can at most be syntactically 307 // equal but not identical 308 TaskEquality commonDenominatorForAllComparisons = TaskEquality.SYNTACTICALLY_EQUAL; 309 310 for (ITask child : selection.getChildren()) { 311 TaskEquality taskEquality = 312 callRuleManager(task, child, commonDenominatorForAllComparisons); 313 314 if ((taskEquality == null) || (taskEquality == TaskEquality.UNEQUAL)) { 315 return TaskEquality.UNEQUAL; 316 } 317 318 commonDenominatorForAllComparisons = 319 commonDenominatorForAllComparisons.getCommonDenominator(taskEquality); 320 } 321 322 return commonDenominatorForAllComparisons; 323 } 324 325 /** 326 * <p> 327 * used to to call the task equality rule manager for the comparison of the two provided 328 * children. If no required equality level is provided, than the most concrete equality is 329 * returned. Otherwise, the required equality is returned as long as the children are equal 330 * on that level. 331 * </p> 332 * 333 * @param child1 the first task to be compared 334 * @param child2 the second task to be compared 335 * @param requiredEqualityLevel the equality level to be checked for 336 * 337 * @return the determined equality 338 */ 339 private TaskEquality callRuleManager(ITask child1, 340 ITask child2, 341 TaskEquality requiredEqualityLevel) 342 { 343 if (requiredEqualityLevel == null) { 344 return TaskEqualityRuleManager.getInstance().compare(child1, child2); 345 } 346 else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual 347 (child1, child2, requiredEqualityLevel)) 348 { 349 return requiredEqualityLevel; 350 } 351 else { 352 return TaskEquality.UNEQUAL; 353 } 354 } 355 356 /** 357 * <p> 358 * used to to call the task equality rule manager for the comparison of the two provided 359 * children. If no required equality level is provided, than the most concrete equality is 360 * returned. Otherwise, the required equality is returned as long as the children are equal 361 * on that level. 362 * </p> 363 * 364 * @param taskInstance1 the first task instance to be compared 365 * @param taskInstance2 the second task instance to be compared 366 * @param requiredEqualityLevel the equality level to be checked for 367 * 368 * @return the determined equality 369 */ 370 private TaskEquality callRuleManager(ITaskInstance taskInstance1, 371 ITaskInstance taskInstance2, 372 TaskEquality requiredEqualityLevel) 373 { 374 if (requiredEqualityLevel == null) { 375 return TaskEqualityRuleManager.getInstance().compare(taskInstance1, taskInstance2); 376 } 377 else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual 378 (taskInstance1, taskInstance2, requiredEqualityLevel)) 379 { 380 return requiredEqualityLevel; 381 } 382 else { 383 return TaskEquality.UNEQUAL; 384 } 385 } 86 87 /* 88 * (non-Javadoc) 89 * 90 * @see TaskComparisonRule#areLexicallyEqual(ITask, ITask) 91 */ 92 @Override 93 public boolean areLexicallyEqual(ITask task1, ITask task2) { 94 final ITask child1 = ((IIteration) task1).getMarkedTask(); 95 final ITask child2 = ((IIteration) task2).getMarkedTask(); 96 97 if (child1 != null) { 98 if (child2 == null) { 99 return false; 100 } else { 101 // iterations may have 3 different structures. 102 // 1. they have one child, which is the iterated one 103 // 2. they have a sequence of children, which is iterated 104 // 3. they have a selection of different iterated variants 105 // (usually the variants 106 // are semantically equal) 107 // ignore the type of the children but check them for equality. 108 109 return getNodeEquality(child1, child2).isAtLeast( 110 TaskEquality.LEXICALLY_EQUAL); 111 } 112 } else if (child2 == null) { 113 return true; 114 } 115 116 return false; 117 } 118 119 /* 120 * (non-Javadoc) 121 * 122 * @see TaskComparisonRule#areLexicallyEqual(ITaskInstance, ITaskInstance) 123 */ 124 @Override 125 public boolean areLexicallyEqual(ITaskInstance instance1, 126 ITaskInstance instance2) { 127 final IIterationInstance iteration1 = (IIterationInstance) instance1; 128 final IIterationInstance iteration2 = (IIterationInstance) instance2; 129 130 // if both sequences do not have children, they are equal although this 131 // doesn't make sense 132 if ((iteration1.size() == 0) && (iteration2.size() == 0)) { 133 return true; 134 } 135 136 if (iteration1.size() != iteration2.size()) { 137 return false; 138 } 139 140 for (int i = 0; i < iteration1.size(); i++) { 141 final ITaskInstance child1 = iteration1.get(i); 142 final ITaskInstance child2 = iteration2.get(i); 143 144 final TaskEquality taskEquality = callRuleManager(child1, child2, 145 TaskEquality.LEXICALLY_EQUAL); 146 147 if ((taskEquality == null) 148 || (taskEquality == TaskEquality.UNEQUAL)) { 149 return false; 150 } 151 } 152 153 return true; 154 } 155 156 /* 157 * (non-Javadoc) 158 * 159 * @see TaskComparisonRule#areSemanticallyEqual(ITask, ITask) 160 */ 161 @Override 162 public boolean areSemanticallyEqual(ITask task1, ITask task2) { 163 return compare(task1, task2).isAtLeast(TaskEquality.SEMANTICALLY_EQUAL); 164 } 165 166 /* 167 * (non-Javadoc) 168 * 169 * @see TaskComparisonRule#areSemanticallyEqual(ITaskInstance, 170 * ITaskInstance) 171 */ 172 @Override 173 public boolean areSemanticallyEqual(ITaskInstance instance1, 174 ITaskInstance instance2) { 175 return areLexicallyEqual(instance1, instance2); 176 } 177 178 /* 179 * (non-Javadoc) 180 * 181 * @see TaskComparisonRule#areSyntacticallyEqual(ITask, ITask) 182 */ 183 @Override 184 public boolean areSyntacticallyEqual(ITask task1, ITask task2) { 185 return areLexicallyEqual(task1, task2); 186 } 187 188 /* 189 * (non-Javadoc) 190 * 191 * @see TaskComparisonRule#areSyntacticallyEqual(ITaskInstance, 192 * ITaskInstance) 193 */ 194 @Override 195 public boolean areSyntacticallyEqual(ITaskInstance instance1, 196 ITaskInstance instance2) { 197 return areLexicallyEqual(instance1, instance2); 198 } 199 200 /** 201 * <p> 202 * used to to call the task equality rule manager for the comparison of the 203 * two provided children. If no required equality level is provided, than 204 * the most concrete equality is returned. Otherwise, the required equality 205 * is returned as long as the children are equal on that level. 206 * </p> 207 * 208 * @param child1 209 * the first task to be compared 210 * @param child2 211 * the second task to be compared 212 * @param requiredEqualityLevel 213 * the equality level to be checked for 214 * 215 * @return the determined equality 216 */ 217 private TaskEquality callRuleManager(ITask child1, ITask child2, 218 TaskEquality requiredEqualityLevel) { 219 if (requiredEqualityLevel == null) { 220 return TaskEqualityRuleManager.getInstance() 221 .compare(child1, child2); 222 } else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual( 223 child1, child2, requiredEqualityLevel)) { 224 return requiredEqualityLevel; 225 } else { 226 return TaskEquality.UNEQUAL; 227 } 228 } 229 230 /** 231 * <p> 232 * used to to call the task equality rule manager for the comparison of the 233 * two provided children. If no required equality level is provided, than 234 * the most concrete equality is returned. Otherwise, the required equality 235 * is returned as long as the children are equal on that level. 236 * </p> 237 * 238 * @param taskInstance1 239 * the first task instance to be compared 240 * @param taskInstance2 241 * the second task instance to be compared 242 * @param requiredEqualityLevel 243 * the equality level to be checked for 244 * 245 * @return the determined equality 246 */ 247 private TaskEquality callRuleManager(ITaskInstance taskInstance1, 248 ITaskInstance taskInstance2, TaskEquality requiredEqualityLevel) { 249 if (requiredEqualityLevel == null) { 250 return TaskEqualityRuleManager.getInstance().compare(taskInstance1, 251 taskInstance2); 252 } else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual( 253 taskInstance1, taskInstance2, requiredEqualityLevel)) { 254 return requiredEqualityLevel; 255 } else { 256 return TaskEquality.UNEQUAL; 257 } 258 } 259 260 /* 261 * (non-Javadoc) 262 * 263 * @see TaskComparisonRule#compare(ITask, ITask) 264 */ 265 @Override 266 public TaskEquality compare(ITask task1, ITask task2) { 267 final ITask child1 = ((IIteration) task1).getMarkedTask(); 268 final ITask child2 = ((IIteration) task2).getMarkedTask(); 269 270 // if both iterations do not have children, they are equal although this 271 // doesn't make sense 272 if ((child1 == null) && (child2 == null)) { 273 return TaskEquality.LEXICALLY_EQUAL; 274 } else if ((child1 == null) || (child2 == null)) { 275 return TaskEquality.UNEQUAL; 276 } 277 278 // iterations may have 3 different structures. 279 // 1. they have one child, which is the iterated one 280 // 2. they have a sequence of children, which is iterated 281 // 3. they have a selection of different iterated variants (usually the 282 // variants are 283 // semantically equal) 284 // 285 // the permutations of the three variants in combination must be checked 286 287 // check if both tasks are the same variants of iterations and if their 288 // children are equal. 289 // This condition matches, if both iterations are the same variants of 290 // iteration. I.e. three 291 // combinations of the permutation are handled herewith. 292 final TaskEquality taskEquality = getNodeEquality(child1, child2); 293 294 if (taskEquality != null) { 295 return taskEquality; 296 } 297 298 // compare one iteration with a single task as a child and another one 299 // with a selection of 300 // semantically equal tasks 301 return selectionChildrenSemanticallyEqualNode(child1, child2); 302 303 // all other combinations (i.e. sequence with single child and sequence 304 // with selection) 305 // can not match 306 } 307 308 /* 309 * (non-Javadoc) 310 * 311 * @see TaskComparisonRule#compare(ITaskInstance, ITaskInstance) 312 */ 313 @Override 314 public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) { 315 if (areLexicallyEqual(instance1, instance2)) { 316 return TaskEquality.LEXICALLY_EQUAL; 317 } else { 318 return TaskEquality.UNEQUAL; 319 } 320 } 321 322 /** 323 * <p> 324 * compares two tasks with each other by calling the rule manager. If the 325 * rule manager returns identity, then the returned equality is set to 326 * lexically equal. The reason is, that the children of the iterations are 327 * compared and that therefore the distinct iterations can be at most 328 * lexically equal. 329 * </p> 330 * 331 * @param child1 332 * the first task to be compared 333 * @param child2 334 * the second task to be compared 335 * 336 * @return the determined equality being at most lexical equality. 337 */ 338 private TaskEquality getNodeEquality(ITask child1, ITask child2) { 339 final TaskEquality taskEquality = callRuleManager(child1, child2, null); 340 341 if (taskEquality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL)) { 342 // prevent, that identical is returned, because the iterations 343 // itself are not identical 344 // although the iterated tasks are 345 if (taskEquality == TaskEquality.IDENTICAL) { 346 return TaskEquality.LEXICALLY_EQUAL; 347 } else { 348 return taskEquality; 349 } 350 } 351 352 return TaskEquality.UNEQUAL; 353 } 354 355 /* 356 * (non-Javadoc) 357 * 358 * @see TaskComparisonRule#isApplicable(ITask, ITask) 359 */ 360 @Override 361 public boolean isApplicable(ITask task1, ITask task2) { 362 return (task1 instanceof IIteration) && (task2 instanceof IIteration); 363 } 364 365 /* 366 * (non-Javadoc) 367 * 368 * @see TaskComparisonRule#isApplicable(ITaskInstance, ITaskInstance) 369 */ 370 @Override 371 public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2) { 372 return isApplicable(instance1.getTask(), instance2.getTask()); 373 } 374 375 /** 376 * <p> 377 * compares two tasks. One of them must be a selection, the other one can be 378 * any task. The method returns a task equality that is not 379 * <code>NodeEquality.UNEQUAL</code> if the other task is at least 380 * semantically equal to the children of the selection. It returns more 381 * concrete equalities, if the equality between the other task and the 382 * children of the selection is more concrete. 383 * </p> 384 * 385 * @param task1 386 * the first task to compare 387 * @param task2 388 * the second task to compare 389 * 390 * @return as described 391 */ 392 private TaskEquality selectionChildrenSemanticallyEqualNode(ITask task1, 393 ITask task2) { 394 ISelection selection = null; 395 ITask task = null; 396 if (task1 instanceof ISelection) { 397 selection = (ISelection) task1; 398 task = task2; 399 } else if (task2 instanceof ISelection) { 400 selection = (ISelection) task2; 401 task = task1; 402 } else { 403 return TaskEquality.UNEQUAL; 404 } 405 406 // Iterations, where one has a selection and the other one not can at 407 // most be syntactically 408 // equal but not identical 409 TaskEquality commonDenominatorForAllComparisons = TaskEquality.SYNTACTICALLY_EQUAL; 410 411 for (final ITask child : selection.getChildren()) { 412 final TaskEquality taskEquality = callRuleManager(task, child, 413 commonDenominatorForAllComparisons); 414 415 if ((taskEquality == null) 416 || (taskEquality == TaskEquality.UNEQUAL)) { 417 return TaskEquality.UNEQUAL; 418 } 419 420 commonDenominatorForAllComparisons = commonDenominatorForAllComparisons 421 .getCommonDenominator(taskEquality); 422 } 423 424 return commonDenominatorForAllComparisons; 425 } 386 426 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/SelectionComparisonRule.java
r1294 r1733 24 24 /** 25 25 * <p> 26 * this task comparison rule is capable of comparing selections. If both selections do not have 27 * children, they are treated as lexically equal. If they have children, each child of both 28 * selections is compared to each child of the respective other selection. The resulting equality 29 * is the most concrete one of all these comparisons. I.e. if all children are at least lexically 30 * equal, then the selections are lexically equal. If all children are at least syntactically 31 * equal, then the selections are syntactically equal. If all children are at least semantically 32 * equal, then the selections are semantically equal. If only one of the selections has children, 33 * then the selections are unequal. The comparison is broken up, if only a specific equality is 34 * checked for and this equality is ensured. 26 * this task comparison rule is capable of comparing selections. If both 27 * selections do not have children, they are treated as lexically equal. If they 28 * have children, each child of both selections is compared to each child of the 29 * respective other selection. The resulting equality is the most concrete one 30 * of all these comparisons. I.e. if all children are at least lexically equal, 31 * then the selections are lexically equal. If all children are at least 32 * syntactically equal, then the selections are syntactically equal. If all 33 * children are at least semantically equal, then the selections are 34 * semantically equal. If only one of the selections has children, then the 35 * selections are unequal. The comparison is broken up, if only a specific 36 * equality is checked for and this equality is ensured. 35 37 * </p> 36 38 * … … 40 42 public class SelectionComparisonRule implements TaskComparisonRule { 41 43 42 /* (non-Javadoc) 43 * @see TaskComparisonRule#isApplicable(ITask, ITask) 44 */ 45 @Override 46 public boolean isApplicable(ITask task1, ITask task2) { 47 return (task1 instanceof ISelection) && (task2 instanceof ISelection); 48 } 49 50 /* (non-Javadoc) 51 * @see TaskComparisonRule#areLexicallyEqual(ITask, ITask) 52 */ 53 @Override 54 public boolean areLexicallyEqual(ITask task1, ITask task2) { 55 TaskEquality equality = getEquality(task1, task2, TaskEquality.LEXICALLY_EQUAL); 56 return (equality != null) && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL)); 57 } 58 59 /* (non-Javadoc) 60 * @see TaskComparisonRule#areSyntacticallyEqual(ITask, ITask) 61 */ 62 @Override 63 public boolean areSyntacticallyEqual(ITask task1, ITask task2) { 64 TaskEquality equality = getEquality(task1, task2, TaskEquality.SYNTACTICALLY_EQUAL); 65 return (equality != null) && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)); 66 } 67 68 /* (non-Javadoc) 69 * @see TaskComparisonRule#areSemanticallyEqual(ITask, ITask) 70 */ 71 @Override 72 public boolean areSemanticallyEqual(ITask task1, ITask task2) { 73 TaskEquality equality = getEquality(task1, task2, TaskEquality.SEMANTICALLY_EQUAL); 74 return (equality != null) && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL)); 75 } 76 77 /* (non-Javadoc) 78 * @see TaskComparisonRule#compare(ITask, ITask) 79 */ 80 @Override 81 public TaskEquality compare(ITask task1, ITask task2) { 82 return getEquality(task1, task2, null); 83 } 84 85 /* (non-Javadoc) 86 * @see TaskComparisonRule#isApplicable(ITaskInstance, ITaskInstance) 87 */ 88 @Override 89 public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2) { 90 return isApplicable(instance1.getTask(), instance2.getTask()); 91 } 92 93 /* (non-Javadoc) 94 * @see TaskComparisonRule#areLexicallyEqual(ITaskInstance, ITaskInstance) 95 */ 96 @Override 97 public boolean areLexicallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 98 TaskEquality equality = getEquality(instance1, instance2, TaskEquality.LEXICALLY_EQUAL); 99 return (equality != null) && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL)); 100 } 101 102 /* (non-Javadoc) 103 * @see TaskComparisonRule#areSyntacticallyEqual(ITaskInstance, ITaskInstance) 104 */ 105 @Override 106 public boolean areSyntacticallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 107 TaskEquality equality = getEquality(instance1, instance2, TaskEquality.SYNTACTICALLY_EQUAL); 108 return (equality != null) && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)); 109 } 110 111 /* (non-Javadoc) 112 * @see TaskComparisonRule#areSemanticallyEqual(ITaskInstance, ITaskInstance) 113 */ 114 @Override 115 public boolean areSemanticallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 116 TaskEquality equality = getEquality(instance1, instance2, TaskEquality.SEMANTICALLY_EQUAL); 117 return (equality != null) && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL)); 118 } 119 120 /* (non-Javadoc) 121 * @see TaskComparisonRule#compare(ITaskInstance, ITaskInstance) 122 */ 123 @Override 124 public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) { 125 return getEquality(instance1, instance2, null); 126 } 127 128 /** 129 * <p> 130 * compares two selections with each other checking for the provided required level of 131 * equality. If this level is ensured, the method immediately returns. The more concrete 132 * the required equality level, the more checks this method performs. 133 * </p> 134 * 135 * @param task1 the first task to be compared 136 * @param task2 the second task to be compared 137 * @param requiredEqualityLevel the equality level to be checked for 138 * 139 * @return the determined equality. 140 */ 141 private TaskEquality getEquality(ITask task1, ITask task2, TaskEquality requiredEqualityLevel) { 142 List<ITask> children1 = ((ISelection) task1).getChildren(); 143 List<ITask> children2 = ((ISelection) task2).getChildren(); 144 145 // if both selections do not have children, they are lexically equal. If only one of them 146 // has children, they are unequal. 147 if ((children1.size() == 0) && (children2.size() == 0)) { 148 return TaskEquality.LEXICALLY_EQUAL; 149 } 150 else if ((children1.size() == 0) || (children2.size() == 0)) { 151 return TaskEquality.UNEQUAL; 152 } 153 154 if (requiredEqualityLevel == null) { 155 // calculate the common equality level for all children of both selections. 156 // do it in both directions to ensure commutative comparison 157 return getMostConcreteEqualityLevel(children1, children2); 158 } 159 else { 160 // we are searching for a specific equality 161 if (checkEqualityLevel(children1, children2, requiredEqualityLevel)) { 162 return requiredEqualityLevel; 163 } 164 else { 165 return TaskEquality.UNEQUAL; 166 } 167 } 168 } 169 170 /** 171 * <p> 172 * determines the most concrete equality level for all tasks in the first list compared to all 173 * tasks in the second list. It is sufficient, if there is one task in one list for which there 174 * exist an equal task in the other list. 175 * </p> 176 * 177 * @param children1 the first list to be compared 178 * @param children2 the second list to be compared 179 * 180 * @return the most concrete task equality identified for all tasks in the first list with 181 * respect to the second list 182 */ 183 private TaskEquality getMostConcreteEqualityLevel(List<ITask> children1, List<ITask> children2) 184 { 185 TaskEquality childEquality; 186 TaskEquality currentEquality; 187 for (ITask child1 : children1) { 188 childEquality = null; 189 for (ITask child2 : children2) { 190 currentEquality = callRuleManager(child1, child2, null); 191 if ((currentEquality != null) && (currentEquality != TaskEquality.UNEQUAL)) { 192 if (childEquality == null) { 193 childEquality = currentEquality; 194 } 195 else { 196 childEquality = childEquality.getCommonDenominator(currentEquality); 197 } 198 199 if (childEquality.isAtLeast(TaskEquality.LEXICALLY_EQUAL)) { 200 // as we calculate the most concrete equality, we can break up here 201 return TaskEquality.LEXICALLY_EQUAL; 202 } 203 } 204 } 205 } 206 207 // as the comparison should be commutative, we do not need to check, if in list 2 there is 208 // a child equal to one in list 1 209 return TaskEquality.UNEQUAL; 210 } 211 212 /** 213 * <p> 214 * ensures for the two given lists, that for at least one task in the first list there is a task 215 * in the second list being on the given level equal to the task in the first list. 216 * </p> 217 * 218 * @param children1 the first list to be compared 219 * @param children2 the second list to be compared 220 * @param requiredEqualityLevel the equality level to be checked for 221 * 222 * @return true if there is a task in the first list that has an equal task in the second list 223 * when considering the given equality level, false else. 224 */ 225 private boolean checkEqualityLevel(List<ITask> children1, 226 List<ITask> children2, 227 TaskEquality requiredEqualityLevel) 228 { 229 TaskEquality currentEquality; 230 for (ITask child1 : children1) { 231 for (ITask child2 : children2) { 232 currentEquality = callRuleManager(child1, child2, requiredEqualityLevel); 233 if ((currentEquality != null) && (currentEquality.isAtLeast(requiredEqualityLevel))) 234 { 235 // we found at least one equal child with sufficient equality in the 236 // second list. So be can break up for this child. 237 return true; 238 } 239 } 240 } 241 242 return false; 243 } 244 245 /** 246 * <p> 247 * used to to call the task equality rule manager for the comparison of the two provided 248 * children. If no required equality level is provided, than the most concrete equality is 249 * returned. Otherwise, the required equality is returned as long as the children are equal 250 * on that level. 251 * </p> 252 * 253 * @param child1 the first task to be compared 254 * @param child2 the second task to be compared 255 * @param requiredEqualityLevel the equality level to be checked for 256 * 257 * @return the determined equality 258 */ 259 private TaskEquality callRuleManager(ITask child1, 260 ITask child2, 261 TaskEquality requiredEqualityLevel) 262 { 263 if (requiredEqualityLevel == null) { 264 return TaskEqualityRuleManager.getInstance().compare(child1, child2); 265 } 266 else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual 267 (child1, child2, requiredEqualityLevel)) 268 { 269 return requiredEqualityLevel; 270 } 271 else { 272 return TaskEquality.UNEQUAL; 273 } 274 } 275 276 /** 277 * <p> 278 * compares two selection instances with each other checking for the provided required level of 279 * equality. If this level is ensured, the method immediately returns. The more concrete 280 * the required equality level, the more checks this method performs. 281 * </p> 282 * 283 * @param taskInstance1 the first task instance to be compared 284 * @param taskInstance2 the second task instance to be compared 285 * @param requiredEqualityLevel the equality level to be checked for 286 * 287 * @return the determined equality. 288 */ 289 private TaskEquality getEquality(ITaskInstance taskInstance1, 290 ITaskInstance taskInstance2, 291 TaskEquality requiredEqualityLevel) 292 { 293 ITaskInstance child1 = ((ISelectionInstance) taskInstance1).getChild(); 294 ITaskInstance child2 = ((ISelectionInstance) taskInstance2).getChild(); 295 296 // if both selections do not have children, they are lexically equal. If only one of them 297 // has children, they are unequal. 298 if ((child1 == null) && (child2 == null)) { 299 return TaskEquality.LEXICALLY_EQUAL; 300 } 301 else if ((child1 == null) || (child2 == null)) { 302 return TaskEquality.UNEQUAL; 303 } 304 305 TaskEquality equality = callRuleManager(child1, child2, requiredEqualityLevel); 306 307 if (equality == TaskEquality.IDENTICAL) { 308 // two different selection instances can be at most lexically equal even if their 309 // children are identical 310 return TaskEquality.LEXICALLY_EQUAL; 311 } 312 else { 313 return equality; 314 } 315 } 316 317 /** 318 * <p> 319 * used to to call the task equality rule manager for the comparison of the two provided 320 * children. If no required equality level is provided, than the most concrete equality is 321 * returned. Otherwise, the required equality is returned as long as the children are equal 322 * on that level. 323 * </p> 324 * 325 * @param taskInstance1 the first task instance to be compared 326 * @param taskInstance2 the second task instance to be compared 327 * @param requiredEqualityLevel the equality level to be checked for 328 * 329 * @return the determined equality 330 */ 331 private TaskEquality callRuleManager(ITaskInstance taskInstance1, 332 ITaskInstance taskInstance2, 333 TaskEquality requiredEqualityLevel) 334 { 335 if (requiredEqualityLevel == null) { 336 return TaskEqualityRuleManager.getInstance().compare(taskInstance1, taskInstance2); 337 } 338 else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual 339 (taskInstance1, taskInstance2, requiredEqualityLevel)) 340 { 341 return requiredEqualityLevel; 342 } 343 else { 344 return TaskEquality.UNEQUAL; 345 } 346 } 44 /* 45 * (non-Javadoc) 46 * 47 * @see TaskComparisonRule#areLexicallyEqual(ITask, ITask) 48 */ 49 @Override 50 public boolean areLexicallyEqual(ITask task1, ITask task2) { 51 final TaskEquality equality = getEquality(task1, task2, 52 TaskEquality.LEXICALLY_EQUAL); 53 return (equality != null) 54 && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL)); 55 } 56 57 /* 58 * (non-Javadoc) 59 * 60 * @see TaskComparisonRule#areLexicallyEqual(ITaskInstance, ITaskInstance) 61 */ 62 @Override 63 public boolean areLexicallyEqual(ITaskInstance instance1, 64 ITaskInstance instance2) { 65 final TaskEquality equality = getEquality(instance1, instance2, 66 TaskEquality.LEXICALLY_EQUAL); 67 return (equality != null) 68 && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL)); 69 } 70 71 /* 72 * (non-Javadoc) 73 * 74 * @see TaskComparisonRule#areSemanticallyEqual(ITask, ITask) 75 */ 76 @Override 77 public boolean areSemanticallyEqual(ITask task1, ITask task2) { 78 final TaskEquality equality = getEquality(task1, task2, 79 TaskEquality.SEMANTICALLY_EQUAL); 80 return (equality != null) 81 && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL)); 82 } 83 84 /* 85 * (non-Javadoc) 86 * 87 * @see TaskComparisonRule#areSemanticallyEqual(ITaskInstance, 88 * ITaskInstance) 89 */ 90 @Override 91 public boolean areSemanticallyEqual(ITaskInstance instance1, 92 ITaskInstance instance2) { 93 final TaskEquality equality = getEquality(instance1, instance2, 94 TaskEquality.SEMANTICALLY_EQUAL); 95 return (equality != null) 96 && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL)); 97 } 98 99 /* 100 * (non-Javadoc) 101 * 102 * @see TaskComparisonRule#areSyntacticallyEqual(ITask, ITask) 103 */ 104 @Override 105 public boolean areSyntacticallyEqual(ITask task1, ITask task2) { 106 final TaskEquality equality = getEquality(task1, task2, 107 TaskEquality.SYNTACTICALLY_EQUAL); 108 return (equality != null) 109 && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)); 110 } 111 112 /* 113 * (non-Javadoc) 114 * 115 * @see TaskComparisonRule#areSyntacticallyEqual(ITaskInstance, 116 * ITaskInstance) 117 */ 118 @Override 119 public boolean areSyntacticallyEqual(ITaskInstance instance1, 120 ITaskInstance instance2) { 121 final TaskEquality equality = getEquality(instance1, instance2, 122 TaskEquality.SYNTACTICALLY_EQUAL); 123 return (equality != null) 124 && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)); 125 } 126 127 /** 128 * <p> 129 * used to to call the task equality rule manager for the comparison of the 130 * two provided children. If no required equality level is provided, than 131 * the most concrete equality is returned. Otherwise, the required equality 132 * is returned as long as the children are equal on that level. 133 * </p> 134 * 135 * @param child1 136 * the first task to be compared 137 * @param child2 138 * the second task to be compared 139 * @param requiredEqualityLevel 140 * the equality level to be checked for 141 * 142 * @return the determined equality 143 */ 144 private TaskEquality callRuleManager(ITask child1, ITask child2, 145 TaskEquality requiredEqualityLevel) { 146 if (requiredEqualityLevel == null) { 147 return TaskEqualityRuleManager.getInstance() 148 .compare(child1, child2); 149 } else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual( 150 child1, child2, requiredEqualityLevel)) { 151 return requiredEqualityLevel; 152 } else { 153 return TaskEquality.UNEQUAL; 154 } 155 } 156 157 /** 158 * <p> 159 * used to to call the task equality rule manager for the comparison of the 160 * two provided children. If no required equality level is provided, than 161 * the most concrete equality is returned. Otherwise, the required equality 162 * is returned as long as the children are equal on that level. 163 * </p> 164 * 165 * @param taskInstance1 166 * the first task instance to be compared 167 * @param taskInstance2 168 * the second task instance to be compared 169 * @param requiredEqualityLevel 170 * the equality level to be checked for 171 * 172 * @return the determined equality 173 */ 174 private TaskEquality callRuleManager(ITaskInstance taskInstance1, 175 ITaskInstance taskInstance2, TaskEquality requiredEqualityLevel) { 176 if (requiredEqualityLevel == null) { 177 return TaskEqualityRuleManager.getInstance().compare(taskInstance1, 178 taskInstance2); 179 } else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual( 180 taskInstance1, taskInstance2, requiredEqualityLevel)) { 181 return requiredEqualityLevel; 182 } else { 183 return TaskEquality.UNEQUAL; 184 } 185 } 186 187 /** 188 * <p> 189 * ensures for the two given lists, that for at least one task in the first 190 * list there is a task in the second list being on the given level equal to 191 * the task in the first list. 192 * </p> 193 * 194 * @param children1 195 * the first list to be compared 196 * @param children2 197 * the second list to be compared 198 * @param requiredEqualityLevel 199 * the equality level to be checked for 200 * 201 * @return true if there is a task in the first list that has an equal task 202 * in the second list when considering the given equality level, 203 * false else. 204 */ 205 private boolean checkEqualityLevel(List<ITask> children1, 206 List<ITask> children2, TaskEquality requiredEqualityLevel) { 207 TaskEquality currentEquality; 208 for (final ITask child1 : children1) { 209 for (final ITask child2 : children2) { 210 currentEquality = callRuleManager(child1, child2, 211 requiredEqualityLevel); 212 if ((currentEquality != null) 213 && (currentEquality.isAtLeast(requiredEqualityLevel))) { 214 // we found at least one equal child with sufficient 215 // equality in the 216 // second list. So be can break up for this child. 217 return true; 218 } 219 } 220 } 221 222 return false; 223 } 224 225 /* 226 * (non-Javadoc) 227 * 228 * @see TaskComparisonRule#compare(ITask, ITask) 229 */ 230 @Override 231 public TaskEquality compare(ITask task1, ITask task2) { 232 return getEquality(task1, task2, null); 233 } 234 235 /* 236 * (non-Javadoc) 237 * 238 * @see TaskComparisonRule#compare(ITaskInstance, ITaskInstance) 239 */ 240 @Override 241 public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) { 242 return getEquality(instance1, instance2, null); 243 } 244 245 /** 246 * <p> 247 * compares two selections with each other checking for the provided 248 * required level of equality. If this level is ensured, the method 249 * immediately returns. The more concrete the required equality level, the 250 * more checks this method performs. 251 * </p> 252 * 253 * @param task1 254 * the first task to be compared 255 * @param task2 256 * the second task to be compared 257 * @param requiredEqualityLevel 258 * the equality level to be checked for 259 * 260 * @return the determined equality. 261 */ 262 private TaskEquality getEquality(ITask task1, ITask task2, 263 TaskEquality requiredEqualityLevel) { 264 final List<ITask> children1 = ((ISelection) task1).getChildren(); 265 final List<ITask> children2 = ((ISelection) task2).getChildren(); 266 267 // if both selections do not have children, they are lexically equal. If 268 // only one of them 269 // has children, they are unequal. 270 if ((children1.size() == 0) && (children2.size() == 0)) { 271 return TaskEquality.LEXICALLY_EQUAL; 272 } else if ((children1.size() == 0) || (children2.size() == 0)) { 273 return TaskEquality.UNEQUAL; 274 } 275 276 if (requiredEqualityLevel == null) { 277 // calculate the common equality level for all children of both 278 // selections. 279 // do it in both directions to ensure commutative comparison 280 return getMostConcreteEqualityLevel(children1, children2); 281 } else { 282 // we are searching for a specific equality 283 if (checkEqualityLevel(children1, children2, requiredEqualityLevel)) { 284 return requiredEqualityLevel; 285 } else { 286 return TaskEquality.UNEQUAL; 287 } 288 } 289 } 290 291 /** 292 * <p> 293 * compares two selection instances with each other checking for the 294 * provided required level of equality. If this level is ensured, the method 295 * immediately returns. The more concrete the required equality level, the 296 * more checks this method performs. 297 * </p> 298 * 299 * @param taskInstance1 300 * the first task instance to be compared 301 * @param taskInstance2 302 * the second task instance to be compared 303 * @param requiredEqualityLevel 304 * the equality level to be checked for 305 * 306 * @return the determined equality. 307 */ 308 private TaskEquality getEquality(ITaskInstance taskInstance1, 309 ITaskInstance taskInstance2, TaskEquality requiredEqualityLevel) { 310 final ITaskInstance child1 = ((ISelectionInstance) taskInstance1) 311 .getChild(); 312 final ITaskInstance child2 = ((ISelectionInstance) taskInstance2) 313 .getChild(); 314 315 // if both selections do not have children, they are lexically equal. If 316 // only one of them 317 // has children, they are unequal. 318 if ((child1 == null) && (child2 == null)) { 319 return TaskEquality.LEXICALLY_EQUAL; 320 } else if ((child1 == null) || (child2 == null)) { 321 return TaskEquality.UNEQUAL; 322 } 323 324 final TaskEquality equality = callRuleManager(child1, child2, 325 requiredEqualityLevel); 326 327 if (equality == TaskEquality.IDENTICAL) { 328 // two different selection instances can be at most lexically equal 329 // even if their 330 // children are identical 331 return TaskEquality.LEXICALLY_EQUAL; 332 } else { 333 return equality; 334 } 335 } 336 337 /** 338 * <p> 339 * determines the most concrete equality level for all tasks in the first 340 * list compared to all tasks in the second list. It is sufficient, if there 341 * is one task in one list for which there exist an equal task in the other 342 * list. 343 * </p> 344 * 345 * @param children1 346 * the first list to be compared 347 * @param children2 348 * the second list to be compared 349 * 350 * @return the most concrete task equality identified for all tasks in the 351 * first list with respect to the second list 352 */ 353 private TaskEquality getMostConcreteEqualityLevel(List<ITask> children1, 354 List<ITask> children2) { 355 TaskEquality childEquality; 356 TaskEquality currentEquality; 357 for (final ITask child1 : children1) { 358 childEquality = null; 359 for (final ITask child2 : children2) { 360 currentEquality = callRuleManager(child1, child2, null); 361 if ((currentEquality != null) 362 && (currentEquality != TaskEquality.UNEQUAL)) { 363 if (childEquality == null) { 364 childEquality = currentEquality; 365 } else { 366 childEquality = childEquality 367 .getCommonDenominator(currentEquality); 368 } 369 370 if (childEquality.isAtLeast(TaskEquality.LEXICALLY_EQUAL)) { 371 // as we calculate the most concrete equality, we can 372 // break up here 373 return TaskEquality.LEXICALLY_EQUAL; 374 } 375 } 376 } 377 } 378 379 // as the comparison should be commutative, we do not need to check, if 380 // in list 2 there is 381 // a child equal to one in list 1 382 return TaskEquality.UNEQUAL; 383 } 384 385 /* 386 * (non-Javadoc) 387 * 388 * @see TaskComparisonRule#isApplicable(ITask, ITask) 389 */ 390 @Override 391 public boolean isApplicable(ITask task1, ITask task2) { 392 return (task1 instanceof ISelection) && (task2 instanceof ISelection); 393 } 394 395 /* 396 * (non-Javadoc) 397 * 398 * @see TaskComparisonRule#isApplicable(ITaskInstance, ITaskInstance) 399 */ 400 @Override 401 public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2) { 402 return isApplicable(instance1.getTask(), instance2.getTask()); 403 } 347 404 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/SequenceComparisonRule.java
r1294 r1733 24 24 /** 25 25 * <p> 26 * This rule is capable of comparing sequences. If both sequences do not have children, they are27 * treated as lexically equal. Sequences are lexically equal, if they have the same number and28 * order of lexically equal children. The rule can not decide, if two sequences are syntactically29 * or semantically equal.26 * This rule is capable of comparing sequences. If both sequences do not have 27 * children, they are treated as lexically equal. Sequences are lexically equal, 28 * if they have the same number and order of lexically equal children. The rule 29 * can not decide, if two sequences are syntactically or semantically equal. 30 30 * </p> 31 31 * … … 35 35 public class SequenceComparisonRule implements TaskComparisonRule { 36 36 37 /* (non-Javadoc) 38 * @see TaskComparisonRule#isApplicable(ITask, ITask) 39 */ 40 @Override 41 public boolean isApplicable(ITask task1, ITask task2) { 42 return (task1 instanceof ISequence) && (task2 instanceof ISequence); 43 } 44 45 /* (non-Javadoc) 46 * @see TaskComparisonRule#areLexicallyEqual(ITask, ITask) 47 */ 48 @Override 49 public boolean areLexicallyEqual(ITask task1, ITask task2) { 50 TaskEquality equality = getEquality(task1, task2, TaskEquality.LEXICALLY_EQUAL); 51 return (equality != null) && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL)); 52 } 53 54 /* (non-Javadoc) 55 * @see TaskComparisonRule#areSyntacticallyEqual(ITask, ITask) 56 */ 57 @Override 58 public boolean areSyntacticallyEqual(ITask task1, ITask task2) { 59 TaskEquality equality = getEquality(task1, task2, TaskEquality.SYNTACTICALLY_EQUAL); 60 return (equality != null) && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)); 61 } 62 63 /* (non-Javadoc) 64 * @see TaskComparisonRule#areSemanticallyEqual(ITask, ITask) 65 */ 66 @Override 67 public boolean areSemanticallyEqual(ITask task1, ITask task2) { 68 TaskEquality equality = getEquality(task1, task2, TaskEquality.SEMANTICALLY_EQUAL); 69 return (equality != null) && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL)); 70 } 71 72 /* (non-Javadoc) 73 * @see TaskComparisonRule#compare(ITask, ITask) 74 */ 75 @Override 76 public TaskEquality compare(ITask task1, ITask task2) { 77 return getEquality(task1, task2, null); 78 } 79 80 /* (non-Javadoc) 81 * @see TaskComparisonRule#isApplicable(ITaskInstance, ITaskInstance) 82 */ 83 @Override 84 public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2) { 85 return isApplicable(instance1.getTask(), instance2.getTask()); 86 } 87 88 /* (non-Javadoc) 89 * @see TaskComparisonRule#areLexicallyEqual(ITaskInstance, ITaskInstance) 90 */ 91 @Override 92 public boolean areLexicallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 93 TaskEquality equality = getEquality(instance1, instance2, TaskEquality.LEXICALLY_EQUAL); 94 return (equality != null) && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL)); 95 } 96 97 /* (non-Javadoc) 98 * @see TaskComparisonRule#areSyntacticallyEqual(ITaskInstance, ITaskInstance) 99 */ 100 @Override 101 public boolean areSyntacticallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 102 TaskEquality equality = getEquality(instance1, instance2, TaskEquality.SYNTACTICALLY_EQUAL); 103 return (equality != null) && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)); 104 } 105 106 /* (non-Javadoc) 107 * @see TaskComparisonRule#areSemanticallyEqual(ITaskInstance, ITaskInstance) 108 */ 109 @Override 110 public boolean areSemanticallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 111 TaskEquality equality = getEquality(instance1, instance2, TaskEquality.SEMANTICALLY_EQUAL); 112 return (equality != null) && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL)); 113 } 114 115 /* (non-Javadoc) 116 * @see TaskComparisonRule#compare(ITaskInstance, ITaskInstance) 117 */ 118 @Override 119 public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) { 120 return getEquality(instance1, instance2, null); 121 } 122 123 /** 124 * <p> 125 * compares two sequences with each other checking for the provided required level of 126 * equality. If this level is ensured, the method immediately returns. The more concrete 127 * the required equality level, the more checks this method performs. 128 * </p> 129 * 130 * @param task1 the first task to be compared 131 * @param task2 the second task to be compared 132 * @param requiredEqualityLevel the equality level to be checked for 133 * 134 * @return the determined equality. 135 */ 136 private TaskEquality getEquality(ITask task1, ITask task2, TaskEquality requiredEqualityLevel) { 137 List<ITask> children1 = ((ISequence) task1).getChildren(); 138 List<ITask> children2 = ((ISequence) task2).getChildren(); 139 140 // if both sequences do not have children, they are equal although this doesn't make sense 141 if ((children1.size() == 0) && (children2.size() == 0)) { 142 return TaskEquality.LEXICALLY_EQUAL; 143 } 144 145 if (children1.size() != children2.size()) { 146 return TaskEquality.UNEQUAL; 147 } 148 149 TaskEquality resultingEquality = TaskEquality.LEXICALLY_EQUAL; 150 for (int i = 0; i < children1.size(); i++) { 151 ITask child1 = children1.get(i); 152 ITask child2 = children2.get(i); 153 154 TaskEquality taskEquality = callRuleManager(child1, child2, requiredEqualityLevel); 155 156 if ((taskEquality == null) || (taskEquality == TaskEquality.UNEQUAL)) { 157 return TaskEquality.UNEQUAL; 158 } 159 160 resultingEquality = resultingEquality.getCommonDenominator(taskEquality); 161 } 162 163 return resultingEquality; 164 } 165 166 /** 167 * <p> 168 * used to to call the task equality rule manager for the comparison of the two provided 169 * children. If no required equality level is provided, than the most concrete equality is 170 * returned. Otherwise, the required equality is returned as long as the children are equal 171 * on that level. 172 * </p> 173 * 174 * @param child1 the first task to be compared 175 * @param child2 the second task to be compared 176 * @param requiredEqualityLevel the equality level to be checked for 177 * 178 * @return the determined equality 179 */ 180 private TaskEquality callRuleManager(ITask child1, 181 ITask child2, 182 TaskEquality requiredEqualityLevel) 183 { 184 if (requiredEqualityLevel == null) { 185 return TaskEqualityRuleManager.getInstance().compare(child1, child2); 186 } 187 else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual 188 (child1, child2, requiredEqualityLevel)) 189 { 190 return requiredEqualityLevel; 191 } 192 else { 193 return TaskEquality.UNEQUAL; 194 } 195 } 196 197 /** 198 * <p> 199 * compares two sequence instances with each other checking for the provided required level of 200 * equality. If this level is ensured, the method immediately returns. The more concrete 201 * the required equality level, the more checks this method performs. 202 * </p> 203 * 204 * @param taskInstance1 the first task instance to be compared 205 * @param taskInstance2 the second task instance to be compared 206 * @param requiredEqualityLevel the equality level to be checked for 207 * 208 * @return the determined equality. 209 */ 210 private TaskEquality getEquality(ITaskInstance taskInstance1, 211 ITaskInstance taskInstance2, 212 TaskEquality requiredEqualityLevel) 213 { 214 ISequenceInstance sequence1 = (ISequenceInstance) taskInstance1; 215 ISequenceInstance sequence2 = (ISequenceInstance) taskInstance2; 216 217 // if both sequences do not have children, they are equal although this doesn't make sense 218 if ((sequence1.size() == 0) && (sequence2.size() == 0)) { 219 return TaskEquality.LEXICALLY_EQUAL; 220 } 221 222 if (sequence1.size() != sequence2.size()) { 223 return TaskEquality.UNEQUAL; 224 } 225 226 TaskEquality resultingEquality = TaskEquality.LEXICALLY_EQUAL; 227 for (int i = 0; i < sequence1.size(); i++) { 228 ITaskInstance child1 = sequence1.get(i); 229 ITaskInstance child2 = sequence2.get(i); 230 231 TaskEquality taskEquality = callRuleManager(child1, child2, requiredEqualityLevel); 232 233 if ((taskEquality == null) || (taskEquality == TaskEquality.UNEQUAL)) { 234 return TaskEquality.UNEQUAL; 235 } 236 237 resultingEquality = resultingEquality.getCommonDenominator(taskEquality); 238 } 239 240 return resultingEquality; 241 } 242 243 /** 244 * <p> 245 * used to to call the task equality rule manager for the comparison of the two provided 246 * children. If no required equality level is provided, than the most concrete equality is 247 * returned. Otherwise, the required equality is returned as long as the children are equal 248 * on that level. 249 * </p> 250 * 251 * @param taskInstance1 the first task instance to be compared 252 * @param taskInstance2 the second task instance to be compared 253 * @param requiredEqualityLevel the equality level to be checked for 254 * 255 * @return the determined equality 256 */ 257 private TaskEquality callRuleManager(ITaskInstance taskInstance1, 258 ITaskInstance taskInstance2, 259 TaskEquality requiredEqualityLevel) 260 { 261 if (requiredEqualityLevel == null) { 262 return TaskEqualityRuleManager.getInstance().compare(taskInstance1, taskInstance2); 263 } 264 else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual 265 (taskInstance1, taskInstance2, requiredEqualityLevel)) 266 { 267 return requiredEqualityLevel; 268 } 269 else { 270 return TaskEquality.UNEQUAL; 271 } 272 } 37 /* 38 * (non-Javadoc) 39 * 40 * @see TaskComparisonRule#areLexicallyEqual(ITask, ITask) 41 */ 42 @Override 43 public boolean areLexicallyEqual(ITask task1, ITask task2) { 44 final TaskEquality equality = getEquality(task1, task2, 45 TaskEquality.LEXICALLY_EQUAL); 46 return (equality != null) 47 && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL)); 48 } 49 50 /* 51 * (non-Javadoc) 52 * 53 * @see TaskComparisonRule#areLexicallyEqual(ITaskInstance, ITaskInstance) 54 */ 55 @Override 56 public boolean areLexicallyEqual(ITaskInstance instance1, 57 ITaskInstance instance2) { 58 final TaskEquality equality = getEquality(instance1, instance2, 59 TaskEquality.LEXICALLY_EQUAL); 60 return (equality != null) 61 && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL)); 62 } 63 64 /* 65 * (non-Javadoc) 66 * 67 * @see TaskComparisonRule#areSemanticallyEqual(ITask, ITask) 68 */ 69 @Override 70 public boolean areSemanticallyEqual(ITask task1, ITask task2) { 71 final TaskEquality equality = getEquality(task1, task2, 72 TaskEquality.SEMANTICALLY_EQUAL); 73 return (equality != null) 74 && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL)); 75 } 76 77 /* 78 * (non-Javadoc) 79 * 80 * @see TaskComparisonRule#areSemanticallyEqual(ITaskInstance, 81 * ITaskInstance) 82 */ 83 @Override 84 public boolean areSemanticallyEqual(ITaskInstance instance1, 85 ITaskInstance instance2) { 86 final TaskEquality equality = getEquality(instance1, instance2, 87 TaskEquality.SEMANTICALLY_EQUAL); 88 return (equality != null) 89 && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL)); 90 } 91 92 /* 93 * (non-Javadoc) 94 * 95 * @see TaskComparisonRule#areSyntacticallyEqual(ITask, ITask) 96 */ 97 @Override 98 public boolean areSyntacticallyEqual(ITask task1, ITask task2) { 99 final TaskEquality equality = getEquality(task1, task2, 100 TaskEquality.SYNTACTICALLY_EQUAL); 101 return (equality != null) 102 && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)); 103 } 104 105 /* 106 * (non-Javadoc) 107 * 108 * @see TaskComparisonRule#areSyntacticallyEqual(ITaskInstance, 109 * ITaskInstance) 110 */ 111 @Override 112 public boolean areSyntacticallyEqual(ITaskInstance instance1, 113 ITaskInstance instance2) { 114 final TaskEquality equality = getEquality(instance1, instance2, 115 TaskEquality.SYNTACTICALLY_EQUAL); 116 return (equality != null) 117 && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)); 118 } 119 120 /** 121 * <p> 122 * used to to call the task equality rule manager for the comparison of the 123 * two provided children. If no required equality level is provided, than 124 * the most concrete equality is returned. Otherwise, the required equality 125 * is returned as long as the children are equal on that level. 126 * </p> 127 * 128 * @param child1 129 * the first task to be compared 130 * @param child2 131 * the second task to be compared 132 * @param requiredEqualityLevel 133 * the equality level to be checked for 134 * 135 * @return the determined equality 136 */ 137 private TaskEquality callRuleManager(ITask child1, ITask child2, 138 TaskEquality requiredEqualityLevel) { 139 if (requiredEqualityLevel == null) { 140 return TaskEqualityRuleManager.getInstance() 141 .compare(child1, child2); 142 } else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual( 143 child1, child2, requiredEqualityLevel)) { 144 return requiredEqualityLevel; 145 } else { 146 return TaskEquality.UNEQUAL; 147 } 148 } 149 150 /** 151 * <p> 152 * used to to call the task equality rule manager for the comparison of the 153 * two provided children. If no required equality level is provided, than 154 * the most concrete equality is returned. Otherwise, the required equality 155 * is returned as long as the children are equal on that level. 156 * </p> 157 * 158 * @param taskInstance1 159 * the first task instance to be compared 160 * @param taskInstance2 161 * the second task instance to be compared 162 * @param requiredEqualityLevel 163 * the equality level to be checked for 164 * 165 * @return the determined equality 166 */ 167 private TaskEquality callRuleManager(ITaskInstance taskInstance1, 168 ITaskInstance taskInstance2, TaskEquality requiredEqualityLevel) { 169 if (requiredEqualityLevel == null) { 170 return TaskEqualityRuleManager.getInstance().compare(taskInstance1, 171 taskInstance2); 172 } else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual( 173 taskInstance1, taskInstance2, requiredEqualityLevel)) { 174 return requiredEqualityLevel; 175 } else { 176 return TaskEquality.UNEQUAL; 177 } 178 } 179 180 /* 181 * (non-Javadoc) 182 * 183 * @see TaskComparisonRule#compare(ITask, ITask) 184 */ 185 @Override 186 public TaskEquality compare(ITask task1, ITask task2) { 187 return getEquality(task1, task2, null); 188 } 189 190 /* 191 * (non-Javadoc) 192 * 193 * @see TaskComparisonRule#compare(ITaskInstance, ITaskInstance) 194 */ 195 @Override 196 public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) { 197 return getEquality(instance1, instance2, null); 198 } 199 200 /** 201 * <p> 202 * compares two sequences with each other checking for the provided required 203 * level of equality. If this level is ensured, the method immediately 204 * returns. The more concrete the required equality level, the more checks 205 * this method performs. 206 * </p> 207 * 208 * @param task1 209 * the first task to be compared 210 * @param task2 211 * the second task to be compared 212 * @param requiredEqualityLevel 213 * the equality level to be checked for 214 * 215 * @return the determined equality. 216 */ 217 private TaskEquality getEquality(ITask task1, ITask task2, 218 TaskEquality requiredEqualityLevel) { 219 final List<ITask> children1 = ((ISequence) task1).getChildren(); 220 final List<ITask> children2 = ((ISequence) task2).getChildren(); 221 222 // if both sequences do not have children, they are equal although this 223 // doesn't make sense 224 if ((children1.size() == 0) && (children2.size() == 0)) { 225 return TaskEquality.LEXICALLY_EQUAL; 226 } 227 228 if (children1.size() != children2.size()) { 229 return TaskEquality.UNEQUAL; 230 } 231 232 TaskEquality resultingEquality = TaskEquality.LEXICALLY_EQUAL; 233 for (int i = 0; i < children1.size(); i++) { 234 final ITask child1 = children1.get(i); 235 final ITask child2 = children2.get(i); 236 237 final TaskEquality taskEquality = callRuleManager(child1, child2, 238 requiredEqualityLevel); 239 240 if ((taskEquality == null) 241 || (taskEquality == TaskEquality.UNEQUAL)) { 242 return TaskEquality.UNEQUAL; 243 } 244 245 resultingEquality = resultingEquality 246 .getCommonDenominator(taskEquality); 247 } 248 249 return resultingEquality; 250 } 251 252 /** 253 * <p> 254 * compares two sequence instances with each other checking for the provided 255 * required level of equality. If this level is ensured, the method 256 * immediately returns. The more concrete the required equality level, the 257 * more checks this method performs. 258 * </p> 259 * 260 * @param taskInstance1 261 * the first task instance to be compared 262 * @param taskInstance2 263 * the second task instance to be compared 264 * @param requiredEqualityLevel 265 * the equality level to be checked for 266 * 267 * @return the determined equality. 268 */ 269 private TaskEquality getEquality(ITaskInstance taskInstance1, 270 ITaskInstance taskInstance2, TaskEquality requiredEqualityLevel) { 271 final ISequenceInstance sequence1 = (ISequenceInstance) taskInstance1; 272 final ISequenceInstance sequence2 = (ISequenceInstance) taskInstance2; 273 274 // if both sequences do not have children, they are equal although this 275 // doesn't make sense 276 if ((sequence1.size() == 0) && (sequence2.size() == 0)) { 277 return TaskEquality.LEXICALLY_EQUAL; 278 } 279 280 if (sequence1.size() != sequence2.size()) { 281 return TaskEquality.UNEQUAL; 282 } 283 284 TaskEquality resultingEquality = TaskEquality.LEXICALLY_EQUAL; 285 for (int i = 0; i < sequence1.size(); i++) { 286 final ITaskInstance child1 = sequence1.get(i); 287 final ITaskInstance child2 = sequence2.get(i); 288 289 final TaskEquality taskEquality = callRuleManager(child1, child2, 290 requiredEqualityLevel); 291 292 if ((taskEquality == null) 293 || (taskEquality == TaskEquality.UNEQUAL)) { 294 return TaskEquality.UNEQUAL; 295 } 296 297 resultingEquality = resultingEquality 298 .getCommonDenominator(taskEquality); 299 } 300 301 return resultingEquality; 302 } 303 304 /* 305 * (non-Javadoc) 306 * 307 * @see TaskComparisonRule#isApplicable(ITask, ITask) 308 */ 309 @Override 310 public boolean isApplicable(ITask task1, ITask task2) { 311 return (task1 instanceof ISequence) && (task2 instanceof ISequence); 312 } 313 314 /* 315 * (non-Javadoc) 316 * 317 * @see TaskComparisonRule#isApplicable(ITaskInstance, ITaskInstance) 318 */ 319 @Override 320 public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2) { 321 return isApplicable(instance1.getTask(), instance2.getTask()); 322 } 273 323 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/TaskAndIterationComparisonRule.java
r1294 r1733 23 23 * <p> 24 24 * This class is capable of comparing any task which is not an iteration with an 25 * iteration. This is needed, because iterations may iterate exactly that task. In this 26 * case, the iteration would be equal to that task if it was executed exactly once. The rule 27 * returns lexically equal, it the child of the iteration is lexically equal to the task 28 * or if the child of the iteration is a selection and this selections contains a lexically equal 29 * task. The same applies for syntactical and semantical equality. 25 * iteration. This is needed, because iterations may iterate exactly that task. 26 * In this case, the iteration would be equal to that task if it was executed 27 * exactly once. The rule returns lexically equal, it the child of the iteration 28 * is lexically equal to the task or if the child of the iteration is a 29 * selection and this selections contains a lexically equal task. The same 30 * applies for syntactical and semantical equality. 30 31 * </p> 31 32 * 32 33 * @author Patrick Harms 33 34 */ 34 35 public class TaskAndIterationComparisonRule implements TaskComparisonRule { 35 36 /* (non-Javadoc) 37 * @see TaskComparisonRule#isApplicable(ITask, ITask) 38 */ 39 @Override 40 public boolean isApplicable(ITask task1, ITask task2) { 41 return ((task1 instanceof IIteration) && (!(task2 instanceof IIteration))) || 42 ((task2 instanceof IIteration) && (!(task1 instanceof IIteration))); 43 } 44 45 /* (non-Javadoc) 46 * @see TaskComparisonRule#areLexicallyEqual(ITask, ITask) 47 */ 48 @Override 49 public boolean areLexicallyEqual(ITask task1, ITask task2) { 50 TaskEquality equality = getEquality(task1, task2, TaskEquality.LEXICALLY_EQUAL); 51 return (equality != null) && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL)); 52 } 53 54 /* (non-Javadoc) 55 * @see TaskComparisonRule#areSyntacticallyEqual(ITask, ITask) 56 */ 57 @Override 58 public boolean areSyntacticallyEqual(ITask task1, ITask task2) { 59 TaskEquality equality = getEquality(task1, task2, TaskEquality.SYNTACTICALLY_EQUAL); 60 return (equality != null) && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)); 61 } 62 63 /* (non-Javadoc) 64 * @see TaskComparisonRule#areSemanticallyEqual(ITask, ITask) 65 */ 66 @Override 67 public boolean areSemanticallyEqual(ITask task1, ITask task2) { 68 TaskEquality equality = getEquality(task1, task2, TaskEquality.SEMANTICALLY_EQUAL); 69 return (equality != null) && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL)); 70 } 71 72 /* (non-Javadoc) 73 * @see TaskComparisonRule#compare(ITask, ITask) 74 */ 75 @Override 76 public TaskEquality compare(ITask task1, ITask task2) { 77 return getEquality(task1, task2, null); 78 } 79 80 /* (non-Javadoc) 81 * @see TaskComparisonRule#isApplicable(ITaskInstance, ITaskInstance) 82 */ 83 @Override 84 public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2) { 85 return isApplicable(instance1.getTask(), instance2.getTask()); 86 } 87 88 /* (non-Javadoc) 89 * @see TaskComparisonRule#areLexicallyEqual(ITaskInstance, ITaskInstance) 90 */ 91 @Override 92 public boolean areLexicallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 93 TaskEquality equality = getEquality(instance1, instance2, TaskEquality.LEXICALLY_EQUAL); 94 return (equality != null) && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL)); 95 } 96 97 /* (non-Javadoc) 98 * @see TaskComparisonRule#areSyntacticallyEqual(ITaskInstance, ITaskInstance) 99 */ 100 @Override 101 public boolean areSyntacticallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 102 TaskEquality equality = getEquality(instance1, instance2, TaskEquality.SYNTACTICALLY_EQUAL); 103 return (equality != null) && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)); 104 } 105 106 /* (non-Javadoc) 107 * @see TaskComparisonRule#areSemanticallyEqual(ITaskInstance, ITaskInstance) 108 */ 109 @Override 110 public boolean areSemanticallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 111 TaskEquality equality = getEquality(instance1, instance2, TaskEquality.SEMANTICALLY_EQUAL); 112 return (equality != null) && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL)); 113 } 114 115 /* (non-Javadoc) 116 * @see TaskComparisonRule#compare(ITaskInstance, ITaskInstance) 117 */ 118 @Override 119 public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) { 120 return getEquality(instance1, instance2, null); 121 } 122 123 /** 124 * <p> 125 * compares two tasks with each other checking for the provided required level of 126 * equality. One of the tasks must be an iteration, the other one not. If this is not the 127 * case, the method returns null. The returned equality level is at most lexical equality 128 * as the iteration can not be identical to something not being an iteration. 129 * </p> 130 * 131 * @param task1 the first task to be compared 132 * @param task2 the second task to be compared 133 * @param requiredEqualityLevel the equality level to be checked for 134 * 135 * @return the determined equality. 136 */ 137 private TaskEquality getEquality(ITask task1, ITask task2, TaskEquality requiredEqualityLevel) { 138 IIteration iteration = null; 139 ITask task = null; 140 141 if (task1 instanceof IIteration) { 142 if (task2 instanceof IIteration) { 143 // the rule is not responsible for two iterations 144 return null; 145 } 146 147 iteration = (IIteration) task1; 148 task = task2; 149 } 150 else if (task2 instanceof IIteration) { 151 if (task1 instanceof IIteration) { 152 // the rule is not responsible for two iterations 153 return null; 154 } 155 156 iteration = (IIteration) task2; 157 task = task1; 158 } 159 else { 160 return null; 161 } 162 163 ITask child = iteration.getMarkedTask(); 164 165 // now, that we found the iteration and the task, lets compare the child of the iteration 166 // with the task. 167 if (child == null) { 168 return null; 169 } 170 171 TaskEquality taskEquality = callRuleManager(child, task, requiredEqualityLevel); 172 173 // although the subtask may be identical to the task, we can not return identical, as 174 // the iteration is not identical to the task, but at most lexically equal 175 if (taskEquality == TaskEquality.IDENTICAL) { 176 return TaskEquality.LEXICALLY_EQUAL; 177 } 178 else { 179 return taskEquality; 180 } 181 182 } 183 184 /** 185 * <p> 186 * used to to call the task equality rule manager for the comparison of the two provided 187 * children. If no required equality level is provided, than the most concrete equality is 188 * returned. Otherwise, the required equality is returned as long as the children are equal 189 * on that level. 190 * </p> 191 * 192 * @param child1 the first task to be compared 193 * @param child2 the second task to be compared 194 * @param requiredEqualityLevel the equality level to be checked for 195 * 196 * @return the determined equality 197 */ 198 private TaskEquality callRuleManager(ITask child1, 199 ITask child2, 200 TaskEquality requiredEqualityLevel) 201 { 202 if (requiredEqualityLevel == null) { 203 return TaskEqualityRuleManager.getInstance().compare(child1, child2); 204 } 205 else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual 206 (child1, child2, requiredEqualityLevel)) 207 { 208 return requiredEqualityLevel; 209 } 210 else { 211 return TaskEquality.UNEQUAL; 212 } 213 } 214 215 /** 216 * <p> 217 * compares two task instances with each other checking for the provided required level of 218 * equality. One of the task instances must be a iteration, the other one not. If this is not 219 * the case, the method returns null. The returned equality level is at most lexical equality 220 * as the iteration can not be identical to something not being a iteration. 221 * </p> 222 * 223 * @param taskInstance1 the first task instance to be compared 224 * @param taskInstance2 the second task instance to be compared 225 * @param requiredEqualityLevel the equality level to be checked for 226 * 227 * @return the determined equality. 228 */ 229 private TaskEquality getEquality(ITaskInstance taskInstance1, 230 ITaskInstance taskInstance2, 231 TaskEquality requiredEqualityLevel) 232 { 233 IIterationInstance iteration = null; 234 ITaskInstance task = null; 235 236 if (taskInstance1 instanceof IIterationInstance) { 237 if (taskInstance2 instanceof IIterationInstance) { 238 // the rule is not responsible for two iterations 239 return null; 240 } 241 242 iteration = (IIterationInstance) taskInstance1; 243 task = taskInstance2; 244 } 245 else if (taskInstance2 instanceof IIterationInstance) { 246 if (taskInstance1 instanceof IIterationInstance) { 247 // the rule is not responsible for two iterations 248 return null; 249 } 250 251 iteration = (IIterationInstance) taskInstance2; 252 task = taskInstance1; 253 } 254 else { 255 return null; 256 } 257 258 // now, that we found the iteration and the task, lets compare the children of the iteration 259 // with the task. 260 261 if (iteration.size() < 1) { 262 return null; 263 } 264 265 TaskEquality mostConcreteNodeEquality = null; 266 267 for (ITaskInstance child : iteration) { 268 TaskEquality taskEquality = callRuleManager(child, task, requiredEqualityLevel); 269 270 if (taskEquality != TaskEquality.UNEQUAL) { 271 if (mostConcreteNodeEquality == null) { 272 mostConcreteNodeEquality = taskEquality; 273 } 274 else if (mostConcreteNodeEquality.isAtLeast(taskEquality)) { 275 mostConcreteNodeEquality = taskEquality; 276 277 } 278 279 if ((requiredEqualityLevel != null) && 280 (mostConcreteNodeEquality.isAtLeast(requiredEqualityLevel))) 281 { 282 // if we found one child of the selection that is as equal as required, then 283 // we can consider the selection to be sufficiently equal to the other task. 284 // So we break up checking further children. 285 break; 286 } 287 } 288 } 289 290 // although the subtask may be identical to the task, we can not return identical, as 291 // the selection is not identical to the task, but at most lexically equal 292 if (mostConcreteNodeEquality == TaskEquality.IDENTICAL) { 293 return TaskEquality.LEXICALLY_EQUAL; 294 } 295 else { 296 return mostConcreteNodeEquality; 297 } 298 299 } 300 301 /** 302 * <p> 303 * used to to call the task equality rule manager for the comparison of the two provided 304 * children. If no required equality level is provided, than the most concrete equality is 305 * returned. Otherwise, the required equality is returned as long as the children are equal 306 * on that level. 307 * </p> 308 * 309 * @param taskInstance1 the first task instance to be compared 310 * @param taskInstance2 the second task instance to be compared 311 * @param requiredEqualityLevel the equality level to be checked for 312 * 313 * @return the determined equality 314 */ 315 private TaskEquality callRuleManager(ITaskInstance taskInstance1, 316 ITaskInstance taskInstance2, 317 TaskEquality requiredEqualityLevel) 318 { 319 if (requiredEqualityLevel == null) { 320 return TaskEqualityRuleManager.getInstance().compare(taskInstance1, taskInstance2); 321 } 322 else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual 323 (taskInstance1, taskInstance2, requiredEqualityLevel)) 324 { 325 return requiredEqualityLevel; 326 } 327 else { 328 return TaskEquality.UNEQUAL; 329 } 330 } 36 37 /* 38 * (non-Javadoc) 39 * 40 * @see TaskComparisonRule#areLexicallyEqual(ITask, ITask) 41 */ 42 @Override 43 public boolean areLexicallyEqual(ITask task1, ITask task2) { 44 final TaskEquality equality = getEquality(task1, task2, 45 TaskEquality.LEXICALLY_EQUAL); 46 return (equality != null) 47 && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL)); 48 } 49 50 /* 51 * (non-Javadoc) 52 * 53 * @see TaskComparisonRule#areLexicallyEqual(ITaskInstance, ITaskInstance) 54 */ 55 @Override 56 public boolean areLexicallyEqual(ITaskInstance instance1, 57 ITaskInstance instance2) { 58 final TaskEquality equality = getEquality(instance1, instance2, 59 TaskEquality.LEXICALLY_EQUAL); 60 return (equality != null) 61 && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL)); 62 } 63 64 /* 65 * (non-Javadoc) 66 * 67 * @see TaskComparisonRule#areSemanticallyEqual(ITask, ITask) 68 */ 69 @Override 70 public boolean areSemanticallyEqual(ITask task1, ITask task2) { 71 final TaskEquality equality = getEquality(task1, task2, 72 TaskEquality.SEMANTICALLY_EQUAL); 73 return (equality != null) 74 && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL)); 75 } 76 77 /* 78 * (non-Javadoc) 79 * 80 * @see TaskComparisonRule#areSemanticallyEqual(ITaskInstance, 81 * ITaskInstance) 82 */ 83 @Override 84 public boolean areSemanticallyEqual(ITaskInstance instance1, 85 ITaskInstance instance2) { 86 final TaskEquality equality = getEquality(instance1, instance2, 87 TaskEquality.SEMANTICALLY_EQUAL); 88 return (equality != null) 89 && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL)); 90 } 91 92 /* 93 * (non-Javadoc) 94 * 95 * @see TaskComparisonRule#areSyntacticallyEqual(ITask, ITask) 96 */ 97 @Override 98 public boolean areSyntacticallyEqual(ITask task1, ITask task2) { 99 final TaskEquality equality = getEquality(task1, task2, 100 TaskEquality.SYNTACTICALLY_EQUAL); 101 return (equality != null) 102 && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)); 103 } 104 105 /* 106 * (non-Javadoc) 107 * 108 * @see TaskComparisonRule#areSyntacticallyEqual(ITaskInstance, 109 * ITaskInstance) 110 */ 111 @Override 112 public boolean areSyntacticallyEqual(ITaskInstance instance1, 113 ITaskInstance instance2) { 114 final TaskEquality equality = getEquality(instance1, instance2, 115 TaskEquality.SYNTACTICALLY_EQUAL); 116 return (equality != null) 117 && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)); 118 } 119 120 /** 121 * <p> 122 * used to to call the task equality rule manager for the comparison of the 123 * two provided children. If no required equality level is provided, than 124 * the most concrete equality is returned. Otherwise, the required equality 125 * is returned as long as the children are equal on that level. 126 * </p> 127 * 128 * @param child1 129 * the first task to be compared 130 * @param child2 131 * the second task to be compared 132 * @param requiredEqualityLevel 133 * the equality level to be checked for 134 * 135 * @return the determined equality 136 */ 137 private TaskEquality callRuleManager(ITask child1, ITask child2, 138 TaskEquality requiredEqualityLevel) { 139 if (requiredEqualityLevel == null) { 140 return TaskEqualityRuleManager.getInstance() 141 .compare(child1, child2); 142 } else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual( 143 child1, child2, requiredEqualityLevel)) { 144 return requiredEqualityLevel; 145 } else { 146 return TaskEquality.UNEQUAL; 147 } 148 } 149 150 /** 151 * <p> 152 * used to to call the task equality rule manager for the comparison of the 153 * two provided children. If no required equality level is provided, than 154 * the most concrete equality is returned. Otherwise, the required equality 155 * is returned as long as the children are equal on that level. 156 * </p> 157 * 158 * @param taskInstance1 159 * the first task instance to be compared 160 * @param taskInstance2 161 * the second task instance to be compared 162 * @param requiredEqualityLevel 163 * the equality level to be checked for 164 * 165 * @return the determined equality 166 */ 167 private TaskEquality callRuleManager(ITaskInstance taskInstance1, 168 ITaskInstance taskInstance2, TaskEquality requiredEqualityLevel) { 169 if (requiredEqualityLevel == null) { 170 return TaskEqualityRuleManager.getInstance().compare(taskInstance1, 171 taskInstance2); 172 } else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual( 173 taskInstance1, taskInstance2, requiredEqualityLevel)) { 174 return requiredEqualityLevel; 175 } else { 176 return TaskEquality.UNEQUAL; 177 } 178 } 179 180 /* 181 * (non-Javadoc) 182 * 183 * @see TaskComparisonRule#compare(ITask, ITask) 184 */ 185 @Override 186 public TaskEquality compare(ITask task1, ITask task2) { 187 return getEquality(task1, task2, null); 188 } 189 190 /* 191 * (non-Javadoc) 192 * 193 * @see TaskComparisonRule#compare(ITaskInstance, ITaskInstance) 194 */ 195 @Override 196 public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) { 197 return getEquality(instance1, instance2, null); 198 } 199 200 /** 201 * <p> 202 * compares two tasks with each other checking for the provided required 203 * level of equality. One of the tasks must be an iteration, the other one 204 * not. If this is not the case, the method returns null. The returned 205 * equality level is at most lexical equality as the iteration can not be 206 * identical to something not being an iteration. 207 * </p> 208 * 209 * @param task1 210 * the first task to be compared 211 * @param task2 212 * the second task to be compared 213 * @param requiredEqualityLevel 214 * the equality level to be checked for 215 * 216 * @return the determined equality. 217 */ 218 private TaskEquality getEquality(ITask task1, ITask task2, 219 TaskEquality requiredEqualityLevel) { 220 IIteration iteration = null; 221 ITask task = null; 222 223 if (task1 instanceof IIteration) { 224 if (task2 instanceof IIteration) { 225 // the rule is not responsible for two iterations 226 return null; 227 } 228 229 iteration = (IIteration) task1; 230 task = task2; 231 } else if (task2 instanceof IIteration) { 232 if (task1 instanceof IIteration) { 233 // the rule is not responsible for two iterations 234 return null; 235 } 236 237 iteration = (IIteration) task2; 238 task = task1; 239 } else { 240 return null; 241 } 242 243 final ITask child = iteration.getMarkedTask(); 244 245 // now, that we found the iteration and the task, lets compare the child 246 // of the iteration 247 // with the task. 248 if (child == null) { 249 return null; 250 } 251 252 final TaskEquality taskEquality = callRuleManager(child, task, 253 requiredEqualityLevel); 254 255 // although the subtask may be identical to the task, we can not return 256 // identical, as 257 // the iteration is not identical to the task, but at most lexically 258 // equal 259 if (taskEquality == TaskEquality.IDENTICAL) { 260 return TaskEquality.LEXICALLY_EQUAL; 261 } else { 262 return taskEquality; 263 } 264 265 } 266 267 /** 268 * <p> 269 * compares two task instances with each other checking for the provided 270 * required level of equality. One of the task instances must be a 271 * iteration, the other one not. If this is not the case, the method returns 272 * null. The returned equality level is at most lexical equality as the 273 * iteration can not be identical to something not being a iteration. 274 * </p> 275 * 276 * @param taskInstance1 277 * the first task instance to be compared 278 * @param taskInstance2 279 * the second task instance to be compared 280 * @param requiredEqualityLevel 281 * the equality level to be checked for 282 * 283 * @return the determined equality. 284 */ 285 private TaskEquality getEquality(ITaskInstance taskInstance1, 286 ITaskInstance taskInstance2, TaskEquality requiredEqualityLevel) { 287 IIterationInstance iteration = null; 288 ITaskInstance task = null; 289 290 if (taskInstance1 instanceof IIterationInstance) { 291 if (taskInstance2 instanceof IIterationInstance) { 292 // the rule is not responsible for two iterations 293 return null; 294 } 295 296 iteration = (IIterationInstance) taskInstance1; 297 task = taskInstance2; 298 } else if (taskInstance2 instanceof IIterationInstance) { 299 if (taskInstance1 instanceof IIterationInstance) { 300 // the rule is not responsible for two iterations 301 return null; 302 } 303 304 iteration = (IIterationInstance) taskInstance2; 305 task = taskInstance1; 306 } else { 307 return null; 308 } 309 310 // now, that we found the iteration and the task, lets compare the 311 // children of the iteration 312 // with the task. 313 314 if (iteration.size() < 1) { 315 return null; 316 } 317 318 TaskEquality mostConcreteNodeEquality = null; 319 320 for (final ITaskInstance child : iteration) { 321 final TaskEquality taskEquality = callRuleManager(child, task, 322 requiredEqualityLevel); 323 324 if (taskEquality != TaskEquality.UNEQUAL) { 325 if (mostConcreteNodeEquality == null) { 326 mostConcreteNodeEquality = taskEquality; 327 } else if (mostConcreteNodeEquality.isAtLeast(taskEquality)) { 328 mostConcreteNodeEquality = taskEquality; 329 330 } 331 332 if ((requiredEqualityLevel != null) 333 && (mostConcreteNodeEquality 334 .isAtLeast(requiredEqualityLevel))) { 335 // if we found one child of the selection that is as equal 336 // as required, then 337 // we can consider the selection to be sufficiently equal to 338 // the other task. 339 // So we break up checking further children. 340 break; 341 } 342 } 343 } 344 345 // although the subtask may be identical to the task, we can not return 346 // identical, as 347 // the selection is not identical to the task, but at most lexically 348 // equal 349 if (mostConcreteNodeEquality == TaskEquality.IDENTICAL) { 350 return TaskEquality.LEXICALLY_EQUAL; 351 } else { 352 return mostConcreteNodeEquality; 353 } 354 355 } 356 357 /* 358 * (non-Javadoc) 359 * 360 * @see TaskComparisonRule#isApplicable(ITask, ITask) 361 */ 362 @Override 363 public boolean isApplicable(ITask task1, ITask task2) { 364 return ((task1 instanceof IIteration) && (!(task2 instanceof IIteration))) 365 || ((task2 instanceof IIteration) && (!(task1 instanceof IIteration))); 366 } 367 368 /* 369 * (non-Javadoc) 370 * 371 * @see TaskComparisonRule#isApplicable(ITaskInstance, ITaskInstance) 372 */ 373 @Override 374 public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2) { 375 return isApplicable(instance1.getTask(), instance2.getTask()); 376 } 331 377 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/TaskAndSelectionComparisonRule.java
r1294 r1733 25 25 * <p> 26 26 * This class is capable of comparing any task which is not a selection with a 27 * selection. This is needed, because selections may contain exactly that task. Therefore, if 28 * this task is selected out of a selection the selection is equal to the task itself. 29 * The rule returns lexically equal, if the selection contains a lexically equal task. The same 30 * applies for syntactical and semantical equality. 27 * selection. This is needed, because selections may contain exactly that task. 28 * Therefore, if this task is selected out of a selection the selection is equal 29 * to the task itself. The rule returns lexically equal, if the selection 30 * contains a lexically equal task. The same applies for syntactical and 31 * semantical equality. 31 32 * </p> 32 33 * 33 34 * @author Patrick Harms 34 35 */ 35 36 public class TaskAndSelectionComparisonRule implements TaskComparisonRule { 36 37 /* (non-Javadoc) 38 * @see TaskComparisonRule#isApplicable(ITask, ITask) 39 */ 40 @Override 41 public boolean isApplicable(ITask task1, ITask task2) { 42 return ((task1 instanceof ISelection) && (!(task2 instanceof ISelection))) || 43 ((task2 instanceof ISelection) && (!(task1 instanceof ISelection))); 44 } 45 46 /* (non-Javadoc) 47 * @see TaskComparisonRule#areLexicallyEqual(ITask, ITask) 48 */ 49 @Override 50 public boolean areLexicallyEqual(ITask task1, ITask task2) { 51 TaskEquality equality = getEquality(task1, task2, TaskEquality.LEXICALLY_EQUAL); 52 return (equality != null) && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL)); 53 } 54 55 /* (non-Javadoc) 56 * @see TaskComparisonRule#areSyntacticallyEqual(ITask, ITask) 57 */ 58 @Override 59 public boolean areSyntacticallyEqual(ITask task1, ITask task2) { 60 TaskEquality equality = getEquality(task1, task2, TaskEquality.SYNTACTICALLY_EQUAL); 61 return (equality != null) && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)); 62 } 63 64 /* (non-Javadoc) 65 * @see TaskComparisonRule#areSemanticallyEqual(ITask, ITask) 66 */ 67 @Override 68 public boolean areSemanticallyEqual(ITask task1, ITask task2) { 69 TaskEquality equality = getEquality(task1, task2, TaskEquality.SEMANTICALLY_EQUAL); 70 return (equality != null) && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL)); 71 } 72 73 /* (non-Javadoc) 74 * @see TaskComparisonRule#compare(ITask, ITask) 75 */ 76 @Override 77 public TaskEquality compare(ITask task1, ITask task2) { 78 return getEquality(task1, task2, null); 79 } 80 81 /* (non-Javadoc) 82 * @see TaskComparisonRule#isApplicable(ITaskInstance, ITaskInstance) 83 */ 84 @Override 85 public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2) { 86 return isApplicable(instance1.getTask(), instance2.getTask()); 87 } 88 89 /* (non-Javadoc) 90 * @see TaskComparisonRule#areLexicallyEqual(ITaskInstance, ITaskInstance) 91 */ 92 @Override 93 public boolean areLexicallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 94 TaskEquality equality = getEquality(instance1, instance2, TaskEquality.LEXICALLY_EQUAL); 95 return (equality != null) && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL)); 96 } 97 98 /* (non-Javadoc) 99 * @see TaskComparisonRule#areSyntacticallyEqual(ITaskInstance, ITaskInstance) 100 */ 101 @Override 102 public boolean areSyntacticallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 103 TaskEquality equality = getEquality(instance1, instance2, TaskEquality.SYNTACTICALLY_EQUAL); 104 return (equality != null) && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)); 105 } 106 107 /* (non-Javadoc) 108 * @see TaskComparisonRule#areSemanticallyEqual(ITaskInstance, ITaskInstance) 109 */ 110 @Override 111 public boolean areSemanticallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 112 TaskEquality equality = getEquality(instance1, instance2, TaskEquality.SEMANTICALLY_EQUAL); 113 return (equality != null) && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL)); 114 } 115 116 /* (non-Javadoc) 117 * @see TaskComparisonRule#compare(ITaskInstance, ITaskInstance) 118 */ 119 @Override 120 public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) { 121 return getEquality(instance1, instance2, null); 122 } 123 124 /** 125 * <p> 126 * compares two tasks with each other checking for the provided required level of 127 * equality. One of the tasks must be a selection, the other one not. If this is not the 128 * case, the method returns null. The returned equality level is at most lexical equality 129 * as the selection can not be identical to something not being a selection. 130 * </p> 131 * 132 * @param task1 the first task to be compared 133 * @param task2 the second task to be compared 134 * @param requiredEqualityLevel the equality level to be checked for 135 * 136 * @return the determined equality. 137 */ 138 private TaskEquality getEquality(ITask task1, ITask task2, TaskEquality requiredEqualityLevel) { 139 ISelection selection = null; 140 ITask task = null; 141 142 if (task1 instanceof ISelection) { 143 if (task2 instanceof ISelection) { 144 // the rule is not responsible for two selections 145 return null; 146 } 147 148 selection = (ISelection) task1; 149 task = task2; 150 } 151 else if (task2 instanceof ISelection) { 152 if (task1 instanceof ISelection) { 153 // the rule is not responsible for two selections 154 return null; 155 } 156 157 selection = (ISelection) task2; 158 task = task1; 159 } 160 else { 161 return null; 162 } 163 164 // now, that we found the selection and the task, lets compare the children of the selection 165 // with the task. 166 List<ITask> children = selection.getChildren(); 167 168 if (children.size() < 1) { 169 return null; 170 } 171 172 TaskEquality mostConcreteNodeEquality = null; 173 174 for (ITask child : children) { 175 TaskEquality taskEquality = callRuleManager(child, task, requiredEqualityLevel); 176 177 if (taskEquality != TaskEquality.UNEQUAL) { 178 if (mostConcreteNodeEquality == null) { 179 mostConcreteNodeEquality = taskEquality; 180 } 181 else if (mostConcreteNodeEquality.isAtLeast(taskEquality)) { 182 mostConcreteNodeEquality = taskEquality; 183 184 } 185 186 if ((requiredEqualityLevel != null) && 187 (mostConcreteNodeEquality.isAtLeast(requiredEqualityLevel))) 188 { 189 // if we found one child of the selection that is as equal as required, then 190 // we can consider the selection to be sufficiently equal to the other task. 191 // So we break up checking further children. 192 break; 193 } 194 } 195 } 196 197 // although the subtask may be identical to the task, we can not return identical, as 198 // the selection is not identical to the task, but at most lexically equal 199 if (mostConcreteNodeEquality == TaskEquality.IDENTICAL) { 200 return TaskEquality.LEXICALLY_EQUAL; 201 } 202 else { 203 return mostConcreteNodeEquality; 204 } 205 206 } 207 208 /** 209 * <p> 210 * used to to call the task equality rule manager for the comparison of the two provided 211 * children. If no required equality level is provided, than the most concrete equality is 212 * returned. Otherwise, the required equality is returned as long as the children are equal 213 * on that level. 214 * </p> 215 * 216 * @param child1 the first task to be compared 217 * @param child2 the second task to be compared 218 * @param requiredEqualityLevel the equality level to be checked for 219 * 220 * @return the determined equality 221 */ 222 private TaskEquality callRuleManager(ITask child1, 223 ITask child2, 224 TaskEquality requiredEqualityLevel) 225 { 226 if (requiredEqualityLevel == null) { 227 return TaskEqualityRuleManager.getInstance().compare(child1, child2); 228 } 229 else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual 230 (child1, child2, requiredEqualityLevel)) 231 { 232 return requiredEqualityLevel; 233 } 234 else { 235 return TaskEquality.UNEQUAL; 236 } 237 } 238 239 /** 240 * <p> 241 * compares two task instances with each other checking for the provided required level of 242 * equality. One of the task instances must be a selection, the other one not. If this is not 243 * the case, the method returns null. The returned equality level is at most lexical equality 244 * as the selection can not be identical to something not being a selection. 245 * </p> 246 * 247 * @param taskInstance1 the first task instance to be compared 248 * @param taskInstance2 the second task instance to be compared 249 * @param requiredEqualityLevel the equality level to be checked for 250 * 251 * @return the determined equality. 252 */ 253 private TaskEquality getEquality(ITaskInstance taskInstance1, 254 ITaskInstance taskInstance2, 255 TaskEquality requiredEqualityLevel) 256 { 257 ISelectionInstance selection = null; 258 ITaskInstance task = null; 259 260 if (taskInstance1 instanceof ISelectionInstance) { 261 if (taskInstance2 instanceof ISelectionInstance) { 262 // the rule is not responsible for two selections 263 return null; 264 } 265 266 selection = (ISelectionInstance) taskInstance1; 267 task = taskInstance2; 268 } 269 else if (taskInstance2 instanceof ISelectionInstance) { 270 if (taskInstance1 instanceof ISelectionInstance) { 271 // the rule is not responsible for two selections 272 return null; 273 } 274 275 selection = (ISelectionInstance) taskInstance2; 276 task = taskInstance1; 277 } 278 else { 279 return null; 280 } 281 282 // now, that we found the selection and the task, lets compare the child of the selection 283 // with the task. 284 ITaskInstance child = selection.getChild(); 285 286 if (child == null) { 287 return null; 288 } 289 290 TaskEquality taskEquality = callRuleManager(child, task, requiredEqualityLevel); 291 292 // although the subtask may be identical to the task, we can not return identical, as 293 // the selection is not identical to the task, but at most lexically equal 294 if (taskEquality == TaskEquality.IDENTICAL) { 295 return TaskEquality.LEXICALLY_EQUAL; 296 } 297 else { 298 return taskEquality; 299 } 300 301 } 302 303 /** 304 * <p> 305 * used to to call the task equality rule manager for the comparison of the two provided 306 * children. If no required equality level is provided, than the most concrete equality is 307 * returned. Otherwise, the required equality is returned as long as the children are equal 308 * on that level. 309 * </p> 310 * 311 * @param taskInstance1 the first task instance to be compared 312 * @param taskInstance2 the second task instance to be compared 313 * @param requiredEqualityLevel the equality level to be checked for 314 * 315 * @return the determined equality 316 */ 317 private TaskEquality callRuleManager(ITaskInstance taskInstance1, 318 ITaskInstance taskInstance2, 319 TaskEquality requiredEqualityLevel) 320 { 321 if (requiredEqualityLevel == null) { 322 return TaskEqualityRuleManager.getInstance().compare(taskInstance1, taskInstance2); 323 } 324 else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual 325 (taskInstance1, taskInstance2, requiredEqualityLevel)) 326 { 327 return requiredEqualityLevel; 328 } 329 else { 330 return TaskEquality.UNEQUAL; 331 } 332 } 37 38 /* 39 * (non-Javadoc) 40 * 41 * @see TaskComparisonRule#areLexicallyEqual(ITask, ITask) 42 */ 43 @Override 44 public boolean areLexicallyEqual(ITask task1, ITask task2) { 45 final TaskEquality equality = getEquality(task1, task2, 46 TaskEquality.LEXICALLY_EQUAL); 47 return (equality != null) 48 && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL)); 49 } 50 51 /* 52 * (non-Javadoc) 53 * 54 * @see TaskComparisonRule#areLexicallyEqual(ITaskInstance, ITaskInstance) 55 */ 56 @Override 57 public boolean areLexicallyEqual(ITaskInstance instance1, 58 ITaskInstance instance2) { 59 final TaskEquality equality = getEquality(instance1, instance2, 60 TaskEquality.LEXICALLY_EQUAL); 61 return (equality != null) 62 && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL)); 63 } 64 65 /* 66 * (non-Javadoc) 67 * 68 * @see TaskComparisonRule#areSemanticallyEqual(ITask, ITask) 69 */ 70 @Override 71 public boolean areSemanticallyEqual(ITask task1, ITask task2) { 72 final TaskEquality equality = getEquality(task1, task2, 73 TaskEquality.SEMANTICALLY_EQUAL); 74 return (equality != null) 75 && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL)); 76 } 77 78 /* 79 * (non-Javadoc) 80 * 81 * @see TaskComparisonRule#areSemanticallyEqual(ITaskInstance, 82 * ITaskInstance) 83 */ 84 @Override 85 public boolean areSemanticallyEqual(ITaskInstance instance1, 86 ITaskInstance instance2) { 87 final TaskEquality equality = getEquality(instance1, instance2, 88 TaskEquality.SEMANTICALLY_EQUAL); 89 return (equality != null) 90 && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL)); 91 } 92 93 /* 94 * (non-Javadoc) 95 * 96 * @see TaskComparisonRule#areSyntacticallyEqual(ITask, ITask) 97 */ 98 @Override 99 public boolean areSyntacticallyEqual(ITask task1, ITask task2) { 100 final TaskEquality equality = getEquality(task1, task2, 101 TaskEquality.SYNTACTICALLY_EQUAL); 102 return (equality != null) 103 && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)); 104 } 105 106 /* 107 * (non-Javadoc) 108 * 109 * @see TaskComparisonRule#areSyntacticallyEqual(ITaskInstance, 110 * ITaskInstance) 111 */ 112 @Override 113 public boolean areSyntacticallyEqual(ITaskInstance instance1, 114 ITaskInstance instance2) { 115 final TaskEquality equality = getEquality(instance1, instance2, 116 TaskEquality.SYNTACTICALLY_EQUAL); 117 return (equality != null) 118 && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)); 119 } 120 121 /** 122 * <p> 123 * used to to call the task equality rule manager for the comparison of the 124 * two provided children. If no required equality level is provided, than 125 * the most concrete equality is returned. Otherwise, the required equality 126 * is returned as long as the children are equal on that level. 127 * </p> 128 * 129 * @param child1 130 * the first task to be compared 131 * @param child2 132 * the second task to be compared 133 * @param requiredEqualityLevel 134 * the equality level to be checked for 135 * 136 * @return the determined equality 137 */ 138 private TaskEquality callRuleManager(ITask child1, ITask child2, 139 TaskEquality requiredEqualityLevel) { 140 if (requiredEqualityLevel == null) { 141 return TaskEqualityRuleManager.getInstance() 142 .compare(child1, child2); 143 } else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual( 144 child1, child2, requiredEqualityLevel)) { 145 return requiredEqualityLevel; 146 } else { 147 return TaskEquality.UNEQUAL; 148 } 149 } 150 151 /** 152 * <p> 153 * used to to call the task equality rule manager for the comparison of the 154 * two provided children. If no required equality level is provided, than 155 * the most concrete equality is returned. Otherwise, the required equality 156 * is returned as long as the children are equal on that level. 157 * </p> 158 * 159 * @param taskInstance1 160 * the first task instance to be compared 161 * @param taskInstance2 162 * the second task instance to be compared 163 * @param requiredEqualityLevel 164 * the equality level to be checked for 165 * 166 * @return the determined equality 167 */ 168 private TaskEquality callRuleManager(ITaskInstance taskInstance1, 169 ITaskInstance taskInstance2, TaskEquality requiredEqualityLevel) { 170 if (requiredEqualityLevel == null) { 171 return TaskEqualityRuleManager.getInstance().compare(taskInstance1, 172 taskInstance2); 173 } else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual( 174 taskInstance1, taskInstance2, requiredEqualityLevel)) { 175 return requiredEqualityLevel; 176 } else { 177 return TaskEquality.UNEQUAL; 178 } 179 } 180 181 /* 182 * (non-Javadoc) 183 * 184 * @see TaskComparisonRule#compare(ITask, ITask) 185 */ 186 @Override 187 public TaskEquality compare(ITask task1, ITask task2) { 188 return getEquality(task1, task2, null); 189 } 190 191 /* 192 * (non-Javadoc) 193 * 194 * @see TaskComparisonRule#compare(ITaskInstance, ITaskInstance) 195 */ 196 @Override 197 public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) { 198 return getEquality(instance1, instance2, null); 199 } 200 201 /** 202 * <p> 203 * compares two tasks with each other checking for the provided required 204 * level of equality. One of the tasks must be a selection, the other one 205 * not. If this is not the case, the method returns null. The returned 206 * equality level is at most lexical equality as the selection can not be 207 * identical to something not being a selection. 208 * </p> 209 * 210 * @param task1 211 * the first task to be compared 212 * @param task2 213 * the second task to be compared 214 * @param requiredEqualityLevel 215 * the equality level to be checked for 216 * 217 * @return the determined equality. 218 */ 219 private TaskEquality getEquality(ITask task1, ITask task2, 220 TaskEquality requiredEqualityLevel) { 221 ISelection selection = null; 222 ITask task = null; 223 224 if (task1 instanceof ISelection) { 225 if (task2 instanceof ISelection) { 226 // the rule is not responsible for two selections 227 return null; 228 } 229 230 selection = (ISelection) task1; 231 task = task2; 232 } else if (task2 instanceof ISelection) { 233 if (task1 instanceof ISelection) { 234 // the rule is not responsible for two selections 235 return null; 236 } 237 238 selection = (ISelection) task2; 239 task = task1; 240 } else { 241 return null; 242 } 243 244 // now, that we found the selection and the task, lets compare the 245 // children of the selection 246 // with the task. 247 final List<ITask> children = selection.getChildren(); 248 249 if (children.size() < 1) { 250 return null; 251 } 252 253 TaskEquality mostConcreteNodeEquality = null; 254 255 for (final ITask child : children) { 256 final TaskEquality taskEquality = callRuleManager(child, task, 257 requiredEqualityLevel); 258 259 if (taskEquality != TaskEquality.UNEQUAL) { 260 if (mostConcreteNodeEquality == null) { 261 mostConcreteNodeEquality = taskEquality; 262 } else if (mostConcreteNodeEquality.isAtLeast(taskEquality)) { 263 mostConcreteNodeEquality = taskEquality; 264 265 } 266 267 if ((requiredEqualityLevel != null) 268 && (mostConcreteNodeEquality 269 .isAtLeast(requiredEqualityLevel))) { 270 // if we found one child of the selection that is as equal 271 // as required, then 272 // we can consider the selection to be sufficiently equal to 273 // the other task. 274 // So we break up checking further children. 275 break; 276 } 277 } 278 } 279 280 // although the subtask may be identical to the task, we can not return 281 // identical, as 282 // the selection is not identical to the task, but at most lexically 283 // equal 284 if (mostConcreteNodeEquality == TaskEquality.IDENTICAL) { 285 return TaskEquality.LEXICALLY_EQUAL; 286 } else { 287 return mostConcreteNodeEquality; 288 } 289 290 } 291 292 /** 293 * <p> 294 * compares two task instances with each other checking for the provided 295 * required level of equality. One of the task instances must be a 296 * selection, the other one not. If this is not the case, the method returns 297 * null. The returned equality level is at most lexical equality as the 298 * selection can not be identical to something not being a selection. 299 * </p> 300 * 301 * @param taskInstance1 302 * the first task instance to be compared 303 * @param taskInstance2 304 * the second task instance to be compared 305 * @param requiredEqualityLevel 306 * the equality level to be checked for 307 * 308 * @return the determined equality. 309 */ 310 private TaskEquality getEquality(ITaskInstance taskInstance1, 311 ITaskInstance taskInstance2, TaskEquality requiredEqualityLevel) { 312 ISelectionInstance selection = null; 313 ITaskInstance task = null; 314 315 if (taskInstance1 instanceof ISelectionInstance) { 316 if (taskInstance2 instanceof ISelectionInstance) { 317 // the rule is not responsible for two selections 318 return null; 319 } 320 321 selection = (ISelectionInstance) taskInstance1; 322 task = taskInstance2; 323 } else if (taskInstance2 instanceof ISelectionInstance) { 324 if (taskInstance1 instanceof ISelectionInstance) { 325 // the rule is not responsible for two selections 326 return null; 327 } 328 329 selection = (ISelectionInstance) taskInstance2; 330 task = taskInstance1; 331 } else { 332 return null; 333 } 334 335 // now, that we found the selection and the task, lets compare the child 336 // of the selection 337 // with the task. 338 final ITaskInstance child = selection.getChild(); 339 340 if (child == null) { 341 return null; 342 } 343 344 final TaskEquality taskEquality = callRuleManager(child, task, 345 requiredEqualityLevel); 346 347 // although the subtask may be identical to the task, we can not return 348 // identical, as 349 // the selection is not identical to the task, but at most lexically 350 // equal 351 if (taskEquality == TaskEquality.IDENTICAL) { 352 return TaskEquality.LEXICALLY_EQUAL; 353 } else { 354 return taskEquality; 355 } 356 357 } 358 359 /* 360 * (non-Javadoc) 361 * 362 * @see TaskComparisonRule#isApplicable(ITask, ITask) 363 */ 364 @Override 365 public boolean isApplicable(ITask task1, ITask task2) { 366 return ((task1 instanceof ISelection) && (!(task2 instanceof ISelection))) 367 || ((task2 instanceof ISelection) && (!(task1 instanceof ISelection))); 368 } 369 370 /* 371 * (non-Javadoc) 372 * 373 * @see TaskComparisonRule#isApplicable(ITaskInstance, ITaskInstance) 374 */ 375 @Override 376 public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2) { 377 return isApplicable(instance1.getTask(), instance2.getTask()); 378 } 333 379 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/TaskComparisonRule.java
r1294 r1733 20 20 /** 21 21 * <p> 22 * A task comparison rule is used by the {@link TaskEqualityRuleManager} to compare tasks and 23 * task instances with each other. It provides several methods to be called for a comparison. 22 * A task comparison rule is used by the {@link TaskEqualityRuleManager} to 23 * compare tasks and task instances with each other. It provides several methods 24 * to be called for a comparison. 24 25 * </p> 25 26 * … … 29 30 public interface TaskComparisonRule { 30 31 31 /** 32 * <p> 33 * checks if the rule is applicable for comparing the two provided tasks 34 * </p> 35 * 36 * @param task1 the first task to compare 37 * @param task2 the second task to compare 38 * 39 * @return true, if the rule is applicable, false else 40 */ 41 public boolean isApplicable(ITask task1, ITask task2); 32 /** 33 * <p> 34 * checks, if the provided tasks are lexically equal 35 * </p> 36 * 37 * @param task1 38 * the first task to compare 39 * @param task2 40 * the second task to compare 41 * 42 * @return true, if the tasks are equal, false else 43 */ 44 public boolean areLexicallyEqual(ITask task1, ITask task2); 42 45 43 /** 44 * <p> 45 * checks, if the provided tasks are lexically equal 46 * </p> 47 * 48 * @param task1 the first task to compare 49 * @param task2 the second task to compare 50 * 51 * @return true, if the tasks are equal, false else 52 */ 53 public boolean areLexicallyEqual(ITask task1, ITask task2); 46 /** 47 * <p> 48 * checks, if the provided task instances are lexically equal 49 * </p> 50 * 51 * @param instance1 52 * the first task instance to compare 53 * @param instance2 54 * the second task instance to compare 55 * 56 * @return true, if the tasks are equal, false else 57 */ 58 public boolean areLexicallyEqual(ITaskInstance instance1, 59 ITaskInstance instance2); 54 60 55 /** 56 * <p> 57 * checks, if the provided tasks are syntactically equal 58 * </p> 59 * 60 * @param task1 the first task to compare 61 * @param task2 the second task to compare 62 * 63 * @return true, if the tasks are equal, false else 64 */ 65 public boolean areSyntacticallyEqual(ITask task1, ITask task2); 61 /** 62 * <p> 63 * checks, if the provided tasks are semantically equal 64 * </p> 65 * 66 * @param task1 67 * the first task to compare 68 * @param task2 69 * the second task to compare 70 * 71 * @return true, if the tasks are equal, false else 72 */ 73 public boolean areSemanticallyEqual(ITask task1, ITask task2); 66 74 67 /** 68 * <p> 69 * checks, if the provided tasks are semantically equal 70 * </p> 71 * 72 * @param task1 the first task to compare 73 * @param task2 the second task to compare 74 * 75 * @return true, if the tasks are equal, false else 76 */ 77 public boolean areSemanticallyEqual(ITask task1, ITask task2); 75 /** 76 * <p> 77 * checks, if the provided task instances are semantically equal 78 * </p> 79 * 80 * @param instance1 81 * the first task instance to compare 82 * @param instance2 83 * the second task instance to compare 84 * 85 * @return true, if the tasks are equal, false else 86 */ 87 public boolean areSemanticallyEqual(ITaskInstance instance1, 88 ITaskInstance instance2); 78 89 79 80 81 * compares two tasks with each other. The result of the method is either a task equality or 82 * null. If it is null, it means, that the rule is not able to correctly compare the two given 83 * tasks 84 * </p> 85 * 86 * @param task1 the first task to compare 87 * @param task2the second task to compare88 89 * @return as described 90 91 public TaskEquality compare(ITask task1, ITask task2);90 /** 91 * <p> 92 * checks, if the provided tasks are syntactically equal 93 * </p> 94 * 95 * @param task1 96 * the first task to compare 97 * @param task2 98 * the second task to compare 99 * 100 * @return true, if the tasks are equal, false else 101 */ 102 public boolean areSyntacticallyEqual(ITask task1, ITask task2); 92 103 93 /** 94 * <p> 95 * checks if the rule is applicable for comparing the two provided task instances 96 * </p> 97 * 98 * @param instance1 the first task instance to compare 99 * @param instance2 the second task instance to compare 100 * 101 * @return true, if the rule is applicable, false else 102 */ 103 public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2); 104 /** 105 * <p> 106 * checks, if the provided task instances are syntactically equal 107 * </p> 108 * 109 * @param instance1 110 * the first task instance to compare 111 * @param instance2 112 * the second task instance to compare 113 * 114 * @return true, if the tasks are equal, false else 115 */ 116 public boolean areSyntacticallyEqual(ITaskInstance instance1, 117 ITaskInstance instance2); 104 118 105 /** 106 * <p> 107 * checks, if the provided task instances are lexically equal 108 * </p> 109 * 110 * @param instance1 the first task instance to compare 111 * @param instance2 the second task instance to compare 112 * 113 * @return true, if the tasks are equal, false else 114 */ 115 public boolean areLexicallyEqual(ITaskInstance instance1, ITaskInstance instance2); 119 /** 120 * <p> 121 * compares two tasks with each other. The result of the method is either a 122 * task equality or null. If it is null, it means, that the rule is not able 123 * to correctly compare the two given tasks 124 * </p> 125 * 126 * @param task1 127 * the first task to compare 128 * @param task2 129 * the second task to compare 130 * 131 * @return as described 132 */ 133 public TaskEquality compare(ITask task1, ITask task2); 116 134 117 /** 118 * <p> 119 * checks, if the provided task instances are syntactically equal 120 * </p> 121 * 122 * @param instance1 the first task instance to compare 123 * @param instance2 the second task instance to compare 124 * 125 * @return true, if the tasks are equal, false else 126 */ 127 public boolean areSyntacticallyEqual(ITaskInstance instance1, ITaskInstance instance2); 135 /** 136 * <p> 137 * compares two task instances with each other. The result of the method is 138 * either a task instance equality or null. If it is null, it means, that 139 * the rule is not able to correctly compare the two given task instances 140 * </p> 141 * 142 * @param instance1 143 * the first task instance to compare 144 * @param instance2 145 * the second task instance to compare 146 * 147 * @return as described 148 */ 149 public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2); 128 150 129 /** 130 * <p> 131 * checks, if the provided task instances are semantically equal 132 * </p> 133 * 134 * @param instance1 the first task instance to compare 135 * @param instance2 the second task instance to compare 136 * 137 * @return true, if the tasks are equal, false else 138 */ 139 public boolean areSemanticallyEqual(ITaskInstance instance1, ITaskInstance instance2); 151 /** 152 * <p> 153 * checks if the rule is applicable for comparing the two provided tasks 154 * </p> 155 * 156 * @param task1 157 * the first task to compare 158 * @param task2 159 * the second task to compare 160 * 161 * @return true, if the rule is applicable, false else 162 */ 163 public boolean isApplicable(ITask task1, ITask task2); 140 164 141 /** 142 * <p> 143 * compares two task instances with each other. The result of the method is either a task 144 * instance equality or null. If it is null, it means, that the rule is not able to correctly 145 * compare the two given task instances 146 * </p> 147 * 148 * @param instance1 the first task instance to compare 149 * @param instance2 the second task instance to compare 150 * 151 * @return as described 152 */ 153 public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2); 165 /** 166 * <p> 167 * checks if the rule is applicable for comparing the two provided task 168 * instances 169 * </p> 170 * 171 * @param instance1 172 * the first task instance to compare 173 * @param instance2 174 * the second task instance to compare 175 * 176 * @return true, if the rule is applicable, false else 177 */ 178 public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2); 154 179 155 180 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/TaskEquality.java
r1156 r1733 17 17 /** 18 18 * <p> 19 * A task equality denotes, how equal two tasks are. There are different equality levels 20 * which are similar to the usual design levels of GUI design. These levels are 19 * A task equality denotes, how equal two tasks are. There are different 20 * equality levels which are similar to the usual design levels of GUI design. 21 * These levels are 21 22 * <ul> 22 * <li>conceptual design: defines the concepts to be edited using a GUI</li> 23 * <li>semantical design: defines the possible functions for editing the concepts</li> 24 * <li>syntactical design: defines, which steps are needed to execute the functions</li> 25 * <li>lexical design: defines on the key stroke level, how the steps for executing a function 26 * can be performed</li> 23 * <li>conceptual design: defines the concepts to be edited using a GUI</li> 24 * <li>semantical design: defines the possible functions for editing the 25 * concepts</li> 26 * <li>syntactical design: defines, which steps are needed to execute the 27 * functions</li> 28 * <li>lexical design: defines on the key stroke level, how the steps for 29 * executing a function can be performed</li> 27 30 * </ul> 28 * It is not possible to compare two tasks conceptually. But the other design levels can be29 * identified and compared.31 * It is not possible to compare two tasks conceptually. But the other design 32 * levels can be identified and compared. 30 33 * </p> 31 34 * <p> 32 * Tasks can be identical. This is the case if in the java virtual machine, their comparison 33 * using the <code>==</code> operator or the equals method return true. 35 * Tasks can be identical. This is the case if in the java virtual machine, 36 * their comparison using the <code>==</code> operator or the equals method 37 * return true. 34 38 * </p> 35 39 * <p> 36 * Tasks are lexically equal, if they represent the same events on a key stroke level to be 37 * carried out to execute the task. Identical tasks are also syntactically equal. 40 * Tasks are lexically equal, if they represent the same events on a key stroke 41 * level to be carried out to execute the task. Identical tasks are also 42 * syntactically equal. 38 43 * </p> 39 44 * <p> 40 * Nodes are syntactically equal, if they differ in their events on key stroke level, but the 41 * syntactical result is the same. For example, entering the text "hello" into a text field can 42 * be done by entering the letters in their correct order, but also by copying the text into the 43 * text field. The syntactical result is the same: The text "hello" was entered. But the tasks 44 * lexically differ because the events on key stroke level are different. On the other hand, 45 * lexically equal tasks are also syntactically equal. 45 * Nodes are syntactically equal, if they differ in their events on key stroke 46 * level, but the syntactical result is the same. For example, entering the text 47 * "hello" into a text field can be done by entering the letters in their 48 * correct order, but also by copying the text into the text field. The 49 * syntactical result is the same: The text "hello" was entered. But the tasks 50 * lexically differ because the events on key stroke level are different. On the 51 * other hand, lexically equal tasks are also syntactically equal. 46 52 * </p> 47 53 * <p> 48 * Tasks are semantically equal, if they execute the same function for editing the concepts. An 49 * example are a click on a button and a short cut, both executing the same function. These tasks 50 * are syntactically and, therefore, also lexically different, but semantically equal. 51 * Syntactically equal tasks are always also semantically equal. 54 * Tasks are semantically equal, if they execute the same function for editing 55 * the concepts. An example are a click on a button and a short cut, both 56 * executing the same function. These tasks are syntactically and, therefore, 57 * also lexically different, but semantically equal. Syntactically equal tasks 58 * are always also semantically equal. 52 59 * </p> 53 60 * … … 56 63 */ 57 64 public enum TaskEquality { 58 IDENTICAL, 59 LEXICALLY_EQUAL, 60 SYNTACTICALLY_EQUAL, 61 SEMANTICALLY_EQUAL, 62 UNEQUAL; 65 IDENTICAL, LEXICALLY_EQUAL, SYNTACTICALLY_EQUAL, SEMANTICALLY_EQUAL, UNEQUAL; 63 66 64 /** 65 * <p> 66 * Checks for the current task equality, if it is at least identical to the 67 * provided one or even more concrete. As an example, the task equality identical also 68 * indicates, that the tasks are e.g. lexically, syntactically and semantically equal. 69 * Therefore, the method called on <code>IDENTICAL</code> with <code>SEMANTICALLY_EQUAL</code> 70 * as parameter will return true. If this method is called on <code>SYNTACTICALLY_EQUAL</code> 71 * with the parameter <code>IDENTICAL</code> instead, it returns false; 72 * </p> 73 * 74 * @param taskEquality the task equality to compare with. 75 * 76 * @return as described 77 */ 78 public boolean isAtLeast(TaskEquality taskEquality) 79 { 80 switch (taskEquality) { 81 case IDENTICAL: 82 return 83 (this == IDENTICAL); 84 case LEXICALLY_EQUAL: 85 return 86 (this == IDENTICAL) || 87 (this == LEXICALLY_EQUAL); 88 case SYNTACTICALLY_EQUAL: 89 return 90 (this == IDENTICAL) || 91 (this == LEXICALLY_EQUAL) || 92 (this == SYNTACTICALLY_EQUAL); 93 case SEMANTICALLY_EQUAL: 94 return 95 (this == IDENTICAL) || 96 (this == LEXICALLY_EQUAL) || 97 (this == SYNTACTICALLY_EQUAL) || 98 (this == SEMANTICALLY_EQUAL); 99 case UNEQUAL: 100 return 101 (this == UNEQUAL); 102 default : 103 return false; 104 } 105 } 67 /** 68 * <p> 69 * returns the common denominator of this task equality and the provided 70 * one. I.e. if one equality is e.g. syntactical and the other one only 71 * semantical, then semantical is returned. 72 * </p> 73 * 74 * @param otherEquality 75 * the equality, to compare this with 76 * 77 * @return as described 78 */ 79 public TaskEquality getCommonDenominator(TaskEquality otherEquality) { 80 if (this.isAtLeast(otherEquality)) { 81 return otherEquality; 82 } else if (otherEquality.isAtLeast(this)) { 83 return this; 84 } else { 85 return TaskEquality.UNEQUAL; 86 } 87 } 106 88 107 /** 108 * <p> 109 * returns the common denominator of this task equality and the provided one. I.e. if one 110 * equality is e.g. syntactical and the other one only semantical, then semantical is returned. 111 * </p> 112 * 113 * @param otherEquality the equality, to compare this with 114 * 115 * @return as described 116 */ 117 public TaskEquality getCommonDenominator(TaskEquality otherEquality) { 118 if (this.isAtLeast(otherEquality)) { 119 return otherEquality; 120 } 121 else if (otherEquality.isAtLeast(this)) { 122 return this; 123 } 124 else { 125 return TaskEquality.UNEQUAL; 126 } 127 } 89 /** 90 * <p> 91 * Checks for the current task equality, if it is at least identical to the 92 * provided one or even more concrete. As an example, the task equality 93 * identical also indicates, that the tasks are e.g. lexically, 94 * syntactically and semantically equal. Therefore, the method called on 95 * <code>IDENTICAL</code> with <code>SEMANTICALLY_EQUAL</code> as parameter 96 * will return true. If this method is called on 97 * <code>SYNTACTICALLY_EQUAL</code> with the parameter 98 * <code>IDENTICAL</code> instead, it returns false; 99 * </p> 100 * 101 * @param taskEquality 102 * the task equality to compare with. 103 * 104 * @return as described 105 */ 106 public boolean isAtLeast(TaskEquality taskEquality) { 107 switch (taskEquality) { 108 case IDENTICAL: 109 return (this == IDENTICAL); 110 case LEXICALLY_EQUAL: 111 return (this == IDENTICAL) || (this == LEXICALLY_EQUAL); 112 case SYNTACTICALLY_EQUAL: 113 return (this == IDENTICAL) || (this == LEXICALLY_EQUAL) 114 || (this == SYNTACTICALLY_EQUAL); 115 case SEMANTICALLY_EQUAL: 116 return (this == IDENTICAL) || (this == LEXICALLY_EQUAL) 117 || (this == SYNTACTICALLY_EQUAL) 118 || (this == SEMANTICALLY_EQUAL); 119 case UNEQUAL: 120 return (this == UNEQUAL); 121 default: 122 return false; 123 } 124 } 128 125 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/TaskEqualityRuleManager.java
r1294 r1733 23 23 /** 24 24 * <p> 25 * The task equality rule manager is capable of comparing tasks and task instances based on its 26 * internal list of comparison rules. These rules are asked for comparing the two provided tasks or 27 * task instance. If a rule returns a task equality other than null, this equality is returned. 28 * Otherwise the next rule is asked. 25 * The task equality rule manager is capable of comparing tasks and task 26 * instances based on its internal list of comparison rules. These rules are 27 * asked for comparing the two provided tasks or task instance. If a rule 28 * returns a task equality other than null, this equality is returned. Otherwise 29 * the next rule is asked. 29 30 * </p> 30 31 * … … 32 33 */ 33 34 public class TaskEqualityRuleManager { 34 35 /** 36 * <p> 37 * the singleton instance of this class 38 * </p> 39 */ 40 private static final TaskEqualityRuleManager instance = new TaskEqualityRuleManager(); 41 42 /** 43 * <p> 44 * the rules that can be used for comparing tasks 45 * </p> 46 */ 47 private List<TaskComparisonRule> mRuleIndex = null; 48 49 /** 50 * <p> 51 * initializes the task equality rule manager by filling the internal list of comparison rules. 52 * </p> 53 */ 54 private TaskEqualityRuleManager() { 55 mRuleIndex = new ArrayList<TaskComparisonRule>(); 56 mRuleIndex.add(new TaskIdentityRule()); 57 mRuleIndex.add(new GUIEventTaskComparisonRule()); 58 mRuleIndex.add(new EventTaskComparisonRule()); 59 mRuleIndex.add(new IterationComparisonRule()); 60 mRuleIndex.add(new SequenceComparisonRule()); 61 mRuleIndex.add(new SelectionComparisonRule()); 62 mRuleIndex.add(new TaskAndIterationComparisonRule()); 63 mRuleIndex.add(new TaskAndSelectionComparisonRule()); 64 } 65 66 67 /** 68 * <p> 69 * returns the singleton instance of this class 70 * </p> 71 * 72 * @return as described 73 */ 74 public static TaskEqualityRuleManager getInstance() { 75 return instance; 76 } 77 78 /** 79 * <p> 80 * this method performs a comparison of the two provided tasks. It iterates its internal 81 * comparison rules. If the first rule returns a task equality other than null, 82 * this equality is returned. Otherwise the next rule is tried. If no rule returns an equality 83 * <code>NodeEquality.UNEQUAL</code> is returned. 84 * </p> 85 * 86 * @param task1 the first task to be compared 87 * @param task2 the second task to be compared 88 * 89 * @return as described 90 * 91 * @throws IllegalStateException in the case, the {@link #init()} method was not called on the 92 * manager before a call to this method. 93 */ 94 public TaskEquality compare(ITask task1, ITask task2) 95 throws IllegalStateException 96 { 97 if (mRuleIndex == null) { 98 throw new IllegalStateException("not initialized"); 99 } 100 101 // LOG.info("checking for equality of " + task1 + " and " + task2); 102 TaskEquality taskEquality = null; 103 104 for (TaskComparisonRule rule : mRuleIndex) { 105 if (rule.isApplicable(task1, task2)) { 106 taskEquality = rule.compare(task1, task2); 107 if (taskEquality != null) { 108 // LOG.warning("used rule " + rule + " for equality check"); 109 return taskEquality; 110 } 111 } 112 } 113 114 // LOG.warning("no rule could be applied --> handling tasks as unequal"); 115 116 return TaskEquality.UNEQUAL; 117 } 118 119 /** 120 * <p> 121 * this method two tasks with respect to the fiven equality level and returns true, if this 122 * level is given. 123 * </p> 124 * 125 * @param task1 the first task to be compared 126 * @param task2 the second task to be compared 127 * @param equalityLevel the level of equality to be checked for 128 * 129 * @return as described 130 * 131 * @throws IllegalStateException in the case, the {@link #init()} method was not called on the 132 * manager before a call to this method. 133 */ 134 public boolean areAtLeastEqual(ITask task1, ITask task2, TaskEquality equalityLevel) { 135 if (equalityLevel == null) { 136 throw new IllegalArgumentException("required equality level must not be null"); 137 } 138 139 switch (equalityLevel) { 140 case IDENTICAL: 141 return areIdentical(task1, task2); 142 case LEXICALLY_EQUAL: 143 return areLexicallyEqual(task1, task2); 144 case SYNTACTICALLY_EQUAL: 145 return areSyntacticallyEqual(task1, task2); 146 case SEMANTICALLY_EQUAL: 147 return areSemanticallyEqual(task1, task2); 148 case UNEQUAL: 149 return !areSemanticallyEqual(task1, task2); 150 default: 151 throw new IllegalArgumentException("unknown required equality: " + equalityLevel); 152 } 153 } 154 155 /** 156 * <p> 157 * this method checks if the two given tasks are identical. For this, it iterates its internal 158 * comparison rules. If the first rule returns true, than this method returns true as well. 159 * If no rule returns true, this method returns false. 160 * </p> 161 * 162 * @param task1 the first task to be compared 163 * @param task2 the second task to be compared 164 * 165 * @return as described 166 * 167 * @throws IllegalStateException in the case, the {@link #init()} method was not called on the 168 * manager before a call to this method. 169 */ 170 public boolean areIdentical(ITask task1, ITask task2) { 171 if (mRuleIndex == null) { 172 throw new IllegalStateException("not initialized"); 173 } 174 175 for (TaskComparisonRule rule : mRuleIndex) { 176 if (rule.isApplicable(task1, task2) && rule.areLexicallyEqual(task1, task2)) { 177 return true; 178 } 179 } 180 181 return false; 182 } 183 184 /** 185 * <p> 186 * this method checks if the two given tasks are lexically equal. For this, it iterates its 187 * internal comparison rules. If the first rule returns true, than this method returns true 188 * as well. If no rule returns true, this method returns false. 189 * </p> 190 * 191 * @param task1 the first task to be compared 192 * @param task2 the second task to be compared 193 * 194 * @return as described 195 * 196 * @throws IllegalStateException in the case, the {@link #init()} method was not called on the 197 * manager before a call to this method. 198 */ 199 public boolean areLexicallyEqual(ITask task1, ITask task2) { 200 if (mRuleIndex == null) { 201 throw new IllegalStateException("not initialized"); 202 } 203 204 for (TaskComparisonRule rule : mRuleIndex) { 205 if (rule.isApplicable(task1, task2) && rule.areLexicallyEqual(task1, task2)) { 206 return true; 207 } 208 } 209 210 return false; 211 } 212 213 /** 214 * <p> 215 * this method checks if the two given tasks are syntactically equal. For this, it iterates its 216 * internal comparison rules. If the first rule returns true, than this method returns true 217 * as well. If no rule returns true, this method returns false. 218 * </p> 219 * 220 * @param task1 the first task to be compared 221 * @param task2 the second task to be compared 222 * 223 * @return as described 224 * 225 * @throws IllegalStateException in the case, the {@link #init()} method was not called on the 226 * manager before a call to this method. 227 */ 228 public boolean areSyntacticallyEqual(ITask task1, ITask task2) { 229 if (mRuleIndex == null) { 230 throw new IllegalStateException("not initialized"); 231 } 232 233 for (TaskComparisonRule rule : mRuleIndex) { 234 if (rule.isApplicable(task1, task2) && rule.areSyntacticallyEqual(task1, task2)) { 235 return true; 236 } 237 } 238 239 return false; 240 } 241 242 /** 243 * <p> 244 * this method checks if the two given tasks are semantically equal. For this, it iterates its 245 * internal comparison rules. If the first rule returns true, than this method returns true 246 * as well. If no rule returns true, this method returns false. 247 * </p> 248 * 249 * @param task1 the first task to be compared 250 * @param task2 the second task to be compared 251 * 252 * @return as described 253 * 254 * @throws IllegalStateException in the case, the {@link #init()} method was not called on the 255 * manager before a call to this method. 256 */ 257 public boolean areSemanticallyEqual(ITask task1, ITask task2) { 258 if (mRuleIndex == null) { 259 throw new IllegalStateException("not initialized"); 260 } 261 262 for (TaskComparisonRule rule : mRuleIndex) { 263 if (rule.isApplicable(task1, task2) && rule.areSemanticallyEqual(task1, task2)) { 264 return true; 265 } 266 } 267 268 return false; 269 } 270 271 /** 272 * <p> 273 * this method performs a comparison of the two provided task instances. It iterates its 274 * internal comparison rules. If the first rule returns a task instance equality other than 275 * null, this equality is returned. Otherwise the next rule is tried. If no rule returns an 276 * equality <code>TaskEquality.UNEQUAL</code> is returned. 277 * </p> 278 * 279 * @param instance1 the first task instance to be compared 280 * @param instance2 the second task instance to be compared 281 * 282 * @return as described 283 * 284 * @throws IllegalStateException in the case, the {@link #init()} method was not called on the 285 * manager before a call to this method. 286 */ 287 public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) 288 throws IllegalStateException 289 { 290 if (mRuleIndex == null) { 291 throw new IllegalStateException("not initialized"); 292 } 293 294 // LOG.info("checking for equality of " + instance1 + " and " + instance2); 295 TaskEquality instanceEquality = null; 296 297 for (TaskComparisonRule rule : mRuleIndex) { 298 if (rule.isApplicable(instance1, instance2)) { 299 instanceEquality = rule.compare(instance1, instance2); 300 if (instanceEquality != null) { 301 // LOG.warning("used rule " + rule + " for equality check"); 302 return instanceEquality; 303 } 304 } 305 } 306 307 // LOG.warning("no rule could be applied --> handling tasks as unequal"); 308 309 return TaskEquality.UNEQUAL; 310 } 311 312 /** 313 * <p> 314 * this method compares two task instances with respect to the given equality level and returns 315 * true, if this level is given. 316 * </p> 317 * 318 * @param instance1 the first task instance to be compared 319 * @param instance2 the second task instance to be compared 320 * @param equalityLevel the level of equality to be checked for 321 * 322 * @return as described 323 * 324 * @throws IllegalStateException in the case, the {@link #init()} method was not called on the 325 * manager before a call to this method. 326 */ 327 public boolean areAtLeastEqual(ITaskInstance instance1, 328 ITaskInstance instance2, 329 TaskEquality equalityLevel) 330 { 331 if (equalityLevel == null) { 332 throw new IllegalArgumentException("required equality level must not be null"); 333 } 334 335 switch (equalityLevel) { 336 case IDENTICAL: 337 return areIdentical(instance1, instance2); 338 case LEXICALLY_EQUAL: 339 return areLexicallyEqual(instance1, instance2); 340 case SYNTACTICALLY_EQUAL: 341 return areSyntacticallyEqual(instance1, instance2); 342 case SEMANTICALLY_EQUAL: 343 return areSemanticallyEqual(instance1, instance2); 344 case UNEQUAL: 345 return !areSemanticallyEqual(instance1, instance2); 346 default: 347 throw new IllegalArgumentException("unknown required equality: " + equalityLevel); 348 } 349 } 350 351 /** 352 * <p> 353 * this method checks if the two given task instances are identical. For this, it iterates its 354 * internal comparison rules. If the first rule returns true, than this method returns true 355 * as well. If no rule returns true, this method returns false. 356 * </p> 357 * 358 * @param instance1 the first task instance to be compared 359 * @param instance2 the second task instance to be compared 360 * 361 * @return as described 362 * 363 * @throws IllegalStateException in the case, the {@link #init()} method was not called on the 364 * manager before a call to this method. 365 */ 366 public boolean areIdentical(ITaskInstance instance1, ITaskInstance instance2) { 367 if (mRuleIndex == null) { 368 throw new IllegalStateException("not initialized"); 369 } 370 371 for (TaskComparisonRule rule : mRuleIndex) { 372 if (rule.isApplicable(instance1, instance2) && 373 rule.areLexicallyEqual(instance1, instance2)) 374 { 375 return true; 376 } 377 } 378 379 return false; 380 } 381 382 /** 383 * <p> 384 * this method checks if the two given task instances are lexically equal. For this, it 385 * iterates its internal comparison rules. If the first rule returns true, than this method 386 * returns true, as well. If no rule returns true, this method returns false. 387 * </p> 388 * 389 * @param instance1 the first task instance to be compared 390 * @param instance2 the second task instance to be compared 391 * 392 * @return as described 393 * 394 * @throws IllegalStateException in the case, the {@link #init()} method was not called on the 395 * manager before a call to this method. 396 */ 397 public boolean areLexicallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 398 if (mRuleIndex == null) { 399 throw new IllegalStateException("not initialized"); 400 } 401 402 for (TaskComparisonRule rule : mRuleIndex) { 403 if (rule.isApplicable(instance1, instance2) && 404 rule.areLexicallyEqual(instance1, instance2)) 405 { 406 return true; 407 } 408 } 409 410 return false; 411 } 412 413 /** 414 * <p> 415 * this method checks if the two given task instances are syntactically equal. For this, it 416 * iterates its internal comparison rules. If the first rule returns true, than this method 417 * returns true, as well. If no rule returns true, this method returns false. 418 * </p> 419 * 420 * @param instance1 the first task instance to be compared 421 * @param instance2 the second task instance to be compared 422 * 423 * @return as described 424 * 425 * @throws IllegalStateException in the case, the {@link #init()} method was not called on the 426 * manager before a call to this method. 427 */ 428 public boolean areSyntacticallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 429 if (mRuleIndex == null) { 430 throw new IllegalStateException("not initialized"); 431 } 432 433 for (TaskComparisonRule rule : mRuleIndex) { 434 if (rule.isApplicable(instance1, instance2) && 435 rule.areSyntacticallyEqual(instance1, instance2)) 436 { 437 return true; 438 } 439 } 440 441 return false; 442 } 443 444 /** 445 * <p> 446 * this method checks if the two given task instances are semantically equal. For this, it 447 * iterates its internal comparison rules. If the first rule returns true, than this method 448 * returns true, as well. If no rule returns true, this method returns false. 449 * </p> 450 * 451 * @param instance1 the first task instance to be compared 452 * @param instance2 the second task instance to be compared 453 * 454 * @return as described 455 * 456 * @throws IllegalStateException in the case, the {@link #init()} method was not called on the 457 * manager before a call to this method. 458 */ 459 public boolean areSemanticallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 460 if (mRuleIndex == null) { 461 throw new IllegalStateException("not initialized"); 462 } 463 464 for (TaskComparisonRule rule : mRuleIndex) { 465 if (rule.isApplicable(instance1, instance2) && 466 rule.areSemanticallyEqual(instance1, instance2)) 467 { 468 return true; 469 } 470 } 471 472 return false; 473 } 35 36 /** 37 * <p> 38 * returns the singleton instance of this class 39 * </p> 40 * 41 * @return as described 42 */ 43 public static TaskEqualityRuleManager getInstance() { 44 return instance; 45 } 46 47 /** 48 * <p> 49 * the singleton instance of this class 50 * </p> 51 */ 52 private static final TaskEqualityRuleManager instance = new TaskEqualityRuleManager(); 53 54 /** 55 * <p> 56 * the rules that can be used for comparing tasks 57 * </p> 58 */ 59 private List<TaskComparisonRule> mRuleIndex = null; 60 61 /** 62 * <p> 63 * initializes the task equality rule manager by filling the internal list 64 * of comparison rules. 65 * </p> 66 */ 67 private TaskEqualityRuleManager() { 68 mRuleIndex = new ArrayList<TaskComparisonRule>(); 69 mRuleIndex.add(new TaskIdentityRule()); 70 mRuleIndex.add(new GUIEventTaskComparisonRule()); 71 mRuleIndex.add(new EventTaskComparisonRule()); 72 mRuleIndex.add(new IterationComparisonRule()); 73 mRuleIndex.add(new SequenceComparisonRule()); 74 mRuleIndex.add(new SelectionComparisonRule()); 75 mRuleIndex.add(new TaskAndIterationComparisonRule()); 76 mRuleIndex.add(new TaskAndSelectionComparisonRule()); 77 } 78 79 /** 80 * <p> 81 * this method two tasks with respect to the fiven equality level and 82 * returns true, if this level is given. 83 * </p> 84 * 85 * @param task1 86 * the first task to be compared 87 * @param task2 88 * the second task to be compared 89 * @param equalityLevel 90 * the level of equality to be checked for 91 * 92 * @return as described 93 * 94 * @throws IllegalStateException 95 * in the case, the {@link #init()} method was not called on the 96 * manager before a call to this method. 97 */ 98 public boolean areAtLeastEqual(ITask task1, ITask task2, 99 TaskEquality equalityLevel) { 100 if (equalityLevel == null) { 101 throw new IllegalArgumentException( 102 "required equality level must not be null"); 103 } 104 105 switch (equalityLevel) { 106 case IDENTICAL: 107 return areIdentical(task1, task2); 108 case LEXICALLY_EQUAL: 109 return areLexicallyEqual(task1, task2); 110 case SYNTACTICALLY_EQUAL: 111 return areSyntacticallyEqual(task1, task2); 112 case SEMANTICALLY_EQUAL: 113 return areSemanticallyEqual(task1, task2); 114 case UNEQUAL: 115 return !areSemanticallyEqual(task1, task2); 116 default: 117 throw new IllegalArgumentException("unknown required equality: " 118 + equalityLevel); 119 } 120 } 121 122 /** 123 * <p> 124 * this method compares two task instances with respect to the given 125 * equality level and returns true, if this level is given. 126 * </p> 127 * 128 * @param instance1 129 * the first task instance to be compared 130 * @param instance2 131 * the second task instance to be compared 132 * @param equalityLevel 133 * the level of equality to be checked for 134 * 135 * @return as described 136 * 137 * @throws IllegalStateException 138 * in the case, the {@link #init()} method was not called on the 139 * manager before a call to this method. 140 */ 141 public boolean areAtLeastEqual(ITaskInstance instance1, 142 ITaskInstance instance2, TaskEquality equalityLevel) { 143 if (equalityLevel == null) { 144 throw new IllegalArgumentException( 145 "required equality level must not be null"); 146 } 147 148 switch (equalityLevel) { 149 case IDENTICAL: 150 return areIdentical(instance1, instance2); 151 case LEXICALLY_EQUAL: 152 return areLexicallyEqual(instance1, instance2); 153 case SYNTACTICALLY_EQUAL: 154 return areSyntacticallyEqual(instance1, instance2); 155 case SEMANTICALLY_EQUAL: 156 return areSemanticallyEqual(instance1, instance2); 157 case UNEQUAL: 158 return !areSemanticallyEqual(instance1, instance2); 159 default: 160 throw new IllegalArgumentException("unknown required equality: " 161 + equalityLevel); 162 } 163 } 164 165 /** 166 * <p> 167 * this method checks if the two given tasks are identical. For this, it 168 * iterates its internal comparison rules. If the first rule returns true, 169 * than this method returns true as well. If no rule returns true, this 170 * method returns false. 171 * </p> 172 * 173 * @param task1 174 * the first task to be compared 175 * @param task2 176 * the second task to be compared 177 * 178 * @return as described 179 * 180 * @throws IllegalStateException 181 * in the case, the {@link #init()} method was not called on the 182 * manager before a call to this method. 183 */ 184 public boolean areIdentical(ITask task1, ITask task2) { 185 if (mRuleIndex == null) { 186 throw new IllegalStateException("not initialized"); 187 } 188 189 for (final TaskComparisonRule rule : mRuleIndex) { 190 if (rule.isApplicable(task1, task2) 191 && rule.areLexicallyEqual(task1, task2)) { 192 return true; 193 } 194 } 195 196 return false; 197 } 198 199 /** 200 * <p> 201 * this method checks if the two given task instances are identical. For 202 * this, it iterates its internal comparison rules. If the first rule 203 * returns true, than this method returns true as well. If no rule returns 204 * true, this method returns false. 205 * </p> 206 * 207 * @param instance1 208 * the first task instance to be compared 209 * @param instance2 210 * the second task instance to be compared 211 * 212 * @return as described 213 * 214 * @throws IllegalStateException 215 * in the case, the {@link #init()} method was not called on the 216 * manager before a call to this method. 217 */ 218 public boolean areIdentical(ITaskInstance instance1, ITaskInstance instance2) { 219 if (mRuleIndex == null) { 220 throw new IllegalStateException("not initialized"); 221 } 222 223 for (final TaskComparisonRule rule : mRuleIndex) { 224 if (rule.isApplicable(instance1, instance2) 225 && rule.areLexicallyEqual(instance1, instance2)) { 226 return true; 227 } 228 } 229 230 return false; 231 } 232 233 /** 234 * <p> 235 * this method checks if the two given tasks are lexically equal. For this, 236 * it iterates its internal comparison rules. If the first rule returns 237 * true, than this method returns true as well. If no rule returns true, 238 * this method returns false. 239 * </p> 240 * 241 * @param task1 242 * the first task to be compared 243 * @param task2 244 * the second task to be compared 245 * 246 * @return as described 247 * 248 * @throws IllegalStateException 249 * in the case, the {@link #init()} method was not called on the 250 * manager before a call to this method. 251 */ 252 public boolean areLexicallyEqual(ITask task1, ITask task2) { 253 if (mRuleIndex == null) { 254 throw new IllegalStateException("not initialized"); 255 } 256 257 for (final TaskComparisonRule rule : mRuleIndex) { 258 if (rule.isApplicable(task1, task2) 259 && rule.areLexicallyEqual(task1, task2)) { 260 return true; 261 } 262 } 263 264 return false; 265 } 266 267 /** 268 * <p> 269 * this method checks if the two given task instances are lexically equal. 270 * For this, it iterates its internal comparison rules. If the first rule 271 * returns true, than this method returns true, as well. If no rule returns 272 * true, this method returns false. 273 * </p> 274 * 275 * @param instance1 276 * the first task instance to be compared 277 * @param instance2 278 * the second task instance to be compared 279 * 280 * @return as described 281 * 282 * @throws IllegalStateException 283 * in the case, the {@link #init()} method was not called on the 284 * manager before a call to this method. 285 */ 286 public boolean areLexicallyEqual(ITaskInstance instance1, 287 ITaskInstance instance2) { 288 if (mRuleIndex == null) { 289 throw new IllegalStateException("not initialized"); 290 } 291 292 for (final TaskComparisonRule rule : mRuleIndex) { 293 if (rule.isApplicable(instance1, instance2) 294 && rule.areLexicallyEqual(instance1, instance2)) { 295 return true; 296 } 297 } 298 299 return false; 300 } 301 302 /** 303 * <p> 304 * this method checks if the two given tasks are semantically equal. For 305 * this, it iterates its internal comparison rules. If the first rule 306 * returns true, than this method returns true as well. If no rule returns 307 * true, this method returns false. 308 * </p> 309 * 310 * @param task1 311 * the first task to be compared 312 * @param task2 313 * the second task to be compared 314 * 315 * @return as described 316 * 317 * @throws IllegalStateException 318 * in the case, the {@link #init()} method was not called on the 319 * manager before a call to this method. 320 */ 321 public boolean areSemanticallyEqual(ITask task1, ITask task2) { 322 if (mRuleIndex == null) { 323 throw new IllegalStateException("not initialized"); 324 } 325 326 for (final TaskComparisonRule rule : mRuleIndex) { 327 if (rule.isApplicable(task1, task2) 328 && rule.areSemanticallyEqual(task1, task2)) { 329 return true; 330 } 331 } 332 333 return false; 334 } 335 336 /** 337 * <p> 338 * this method checks if the two given task instances are semantically 339 * equal. For this, it iterates its internal comparison rules. If the first 340 * rule returns true, than this method returns true, as well. If no rule 341 * returns true, this method returns false. 342 * </p> 343 * 344 * @param instance1 345 * the first task instance to be compared 346 * @param instance2 347 * the second task instance to be compared 348 * 349 * @return as described 350 * 351 * @throws IllegalStateException 352 * in the case, the {@link #init()} method was not called on the 353 * manager before a call to this method. 354 */ 355 public boolean areSemanticallyEqual(ITaskInstance instance1, 356 ITaskInstance instance2) { 357 if (mRuleIndex == null) { 358 throw new IllegalStateException("not initialized"); 359 } 360 361 for (final TaskComparisonRule rule : mRuleIndex) { 362 if (rule.isApplicable(instance1, instance2) 363 && rule.areSemanticallyEqual(instance1, instance2)) { 364 return true; 365 } 366 } 367 368 return false; 369 } 370 371 /** 372 * <p> 373 * this method checks if the two given tasks are syntactically equal. For 374 * this, it iterates its internal comparison rules. If the first rule 375 * returns true, than this method returns true as well. If no rule returns 376 * true, this method returns false. 377 * </p> 378 * 379 * @param task1 380 * the first task to be compared 381 * @param task2 382 * the second task to be compared 383 * 384 * @return as described 385 * 386 * @throws IllegalStateException 387 * in the case, the {@link #init()} method was not called on the 388 * manager before a call to this method. 389 */ 390 public boolean areSyntacticallyEqual(ITask task1, ITask task2) { 391 if (mRuleIndex == null) { 392 throw new IllegalStateException("not initialized"); 393 } 394 395 for (final TaskComparisonRule rule : mRuleIndex) { 396 if (rule.isApplicable(task1, task2) 397 && rule.areSyntacticallyEqual(task1, task2)) { 398 return true; 399 } 400 } 401 402 return false; 403 } 404 405 /** 406 * <p> 407 * this method checks if the two given task instances are syntactically 408 * equal. For this, it iterates its internal comparison rules. If the first 409 * rule returns true, than this method returns true, as well. If no rule 410 * returns true, this method returns false. 411 * </p> 412 * 413 * @param instance1 414 * the first task instance to be compared 415 * @param instance2 416 * the second task instance to be compared 417 * 418 * @return as described 419 * 420 * @throws IllegalStateException 421 * in the case, the {@link #init()} method was not called on the 422 * manager before a call to this method. 423 */ 424 public boolean areSyntacticallyEqual(ITaskInstance instance1, 425 ITaskInstance instance2) { 426 if (mRuleIndex == null) { 427 throw new IllegalStateException("not initialized"); 428 } 429 430 for (final TaskComparisonRule rule : mRuleIndex) { 431 if (rule.isApplicable(instance1, instance2) 432 && rule.areSyntacticallyEqual(instance1, instance2)) { 433 return true; 434 } 435 } 436 437 return false; 438 } 439 440 /** 441 * <p> 442 * this method performs a comparison of the two provided tasks. It iterates 443 * its internal comparison rules. If the first rule returns a task equality 444 * other than null, this equality is returned. Otherwise the next rule is 445 * tried. If no rule returns an equality <code>NodeEquality.UNEQUAL</code> 446 * is returned. 447 * </p> 448 * 449 * @param task1 450 * the first task to be compared 451 * @param task2 452 * the second task to be compared 453 * 454 * @return as described 455 * 456 * @throws IllegalStateException 457 * in the case, the {@link #init()} method was not called on the 458 * manager before a call to this method. 459 */ 460 public TaskEquality compare(ITask task1, ITask task2) 461 throws IllegalStateException { 462 if (mRuleIndex == null) { 463 throw new IllegalStateException("not initialized"); 464 } 465 466 // LOG.info("checking for equality of " + task1 + " and " + task2); 467 TaskEquality taskEquality = null; 468 469 for (final TaskComparisonRule rule : mRuleIndex) { 470 if (rule.isApplicable(task1, task2)) { 471 taskEquality = rule.compare(task1, task2); 472 if (taskEquality != null) { 473 // LOG.warning("used rule " + rule + " for equality check"); 474 return taskEquality; 475 } 476 } 477 } 478 479 // LOG.warning("no rule could be applied --> handling tasks as unequal"); 480 481 return TaskEquality.UNEQUAL; 482 } 483 484 /** 485 * <p> 486 * this method performs a comparison of the two provided task instances. It 487 * iterates its internal comparison rules. If the first rule returns a task 488 * instance equality other than null, this equality is returned. Otherwise 489 * the next rule is tried. If no rule returns an equality 490 * <code>TaskEquality.UNEQUAL</code> is returned. 491 * </p> 492 * 493 * @param instance1 494 * the first task instance to be compared 495 * @param instance2 496 * the second task instance to be compared 497 * 498 * @return as described 499 * 500 * @throws IllegalStateException 501 * in the case, the {@link #init()} method was not called on the 502 * manager before a call to this method. 503 */ 504 public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) 505 throws IllegalStateException { 506 if (mRuleIndex == null) { 507 throw new IllegalStateException("not initialized"); 508 } 509 510 // LOG.info("checking for equality of " + instance1 + " and " + 511 // instance2); 512 TaskEquality instanceEquality = null; 513 514 for (final TaskComparisonRule rule : mRuleIndex) { 515 if (rule.isApplicable(instance1, instance2)) { 516 instanceEquality = rule.compare(instance1, instance2); 517 if (instanceEquality != null) { 518 // LOG.warning("used rule " + rule + " for equality check"); 519 return instanceEquality; 520 } 521 } 522 } 523 524 // LOG.warning("no rule could be applied --> handling tasks as unequal"); 525 526 return TaskEquality.UNEQUAL; 527 } 474 528 475 529 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/TaskIdentityRule.java
r1294 r1733 20 20 /** 21 21 * <p> 22 * This comparison rule returns <code>TaskEquality.IDENTICAL</code> if the comparison of the two23 * tasks using the <code>==</code> operator returns true. Else it returns null to denote, that24 * it can not compare the tasks.22 * This comparison rule returns <code>TaskEquality.IDENTICAL</code> if the 23 * comparison of the two tasks using the <code>==</code> operator returns true. 24 * Else it returns null to denote, that it can not compare the tasks. 25 25 * </p> 26 26 * … … 30 30 public class TaskIdentityRule implements TaskComparisonRule { 31 31 32 /* (non-Javadoc) 33 * @see TaskComparisonRule#isApplicable(ITask, ITask) 34 */ 35 @Override 36 public boolean isApplicable(ITask task1, ITask task2) { 37 return (task1 == task2); 38 } 32 /* 33 * (non-Javadoc) 34 * 35 * @see TaskComparisonRule#areLexicallyEqual(ITask, ITask) 36 */ 37 @Override 38 public boolean areLexicallyEqual(ITask task1, ITask task2) { 39 return (task1 == task2); 40 } 39 41 40 /* (non-Javadoc) 41 * @see TaskComparisonRule#areLexicallyEqual(ITask, ITask) 42 */ 43 @Override 44 public boolean areLexicallyEqual(ITask task1, ITask task2) { 45 return (task1 == task2); 46 } 42 /* 43 * (non-Javadoc) 44 * 45 * @see TaskComparisonRule#areLexicallyEqual(ITaskInstance, ITaskInstance) 46 */ 47 @Override 48 public boolean areLexicallyEqual(ITaskInstance instance1, 49 ITaskInstance instance2) { 50 return (instance1.getTask() == instance2.getTask()); 51 } 47 52 48 /* (non-Javadoc) 49 * @see TaskComparisonRule#areSyntacticallyEqual(ITask, ITask) 50 */ 51 @Override 52 public boolean areSyntacticallyEqual(ITask task1, ITask task2) { 53 return (task1 == task2); 54 } 53 /* 54 * (non-Javadoc) 55 * 56 * @see TaskComparisonRule#areSemanticallyEqual(ITask, ITask) 57 */ 58 @Override 59 public boolean areSemanticallyEqual(ITask task1, ITask task2) { 60 return (task1 == task2); 61 } 55 62 56 /* (non-Javadoc) 57 * @see TaskComparisonRule#areSemanticallyEqual(ITask, ITask) 58 */ 59 @Override 60 public boolean areSemanticallyEqual(ITask task1, ITask task2) { 61 return (task1 == task2); 62 } 63 /* 64 * (non-Javadoc) 65 * 66 * @see TaskComparisonRule#areSemanticallyEqual(ITaskInstance, 67 * ITaskInstance) 68 */ 69 @Override 70 public boolean areSemanticallyEqual(ITaskInstance instance1, 71 ITaskInstance instance2) { 72 return (instance1.getTask() == instance2.getTask()); 73 } 63 74 64 /* (non-Javadoc) 65 * @see TaskComparisonRule#compare(ITask, ITask) 66 */ 67 @Override 68 public TaskEquality compare(ITask task1, ITask task2) { 69 if (isApplicable(task1, task2)) { 70 return TaskEquality.IDENTICAL; 71 } 72 else { 73 return null; 74 } 75 } 75 /* 76 * (non-Javadoc) 77 * 78 * @see TaskComparisonRule#areSyntacticallyEqual(ITask, ITask) 79 */ 80 @Override 81 public boolean areSyntacticallyEqual(ITask task1, ITask task2) { 82 return (task1 == task2); 83 } 76 84 77 /* (non-Javadoc) 78 * @see TaskComparisonRule#isApplicable(ITaskInstance, ITaskInstance) 79 */ 80 @Override 81 public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2) { 82 return (instance1.getTask() == instance2.getTask()); 83 } 85 /* 86 * (non-Javadoc) 87 * 88 * @see TaskComparisonRule#areSyntacticallyEqual(ITaskInstance, 89 * ITaskInstance) 90 */ 91 @Override 92 public boolean areSyntacticallyEqual(ITaskInstance instance1, 93 ITaskInstance instance2) { 94 return (instance1.getTask() == instance2.getTask()); 95 } 84 96 85 /* (non-Javadoc) 86 * @see TaskComparisonRule#areLexicallyEqual(ITaskInstance, ITaskInstance) 87 */ 88 @Override 89 public boolean areLexicallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 90 return (instance1.getTask() == instance2.getTask()); 91 } 97 /* 98 * (non-Javadoc) 99 * 100 * @see TaskComparisonRule#compare(ITask, ITask) 101 */ 102 @Override 103 public TaskEquality compare(ITask task1, ITask task2) { 104 if (isApplicable(task1, task2)) { 105 return TaskEquality.IDENTICAL; 106 } else { 107 return null; 108 } 109 } 92 110 93 /* (non-Javadoc) 94 * @see TaskComparisonRule#areSyntacticallyEqual(ITaskInstance, ITaskInstance) 95 */ 96 @Override 97 public boolean areSyntacticallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 98 return (instance1.getTask() == instance2.getTask()); 99 } 111 /* 112 * (non-Javadoc) 113 * 114 * @see TaskComparisonRule#compare(ITaskInstance, ITaskInstance) 115 */ 116 @Override 117 public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) { 118 if (isApplicable(instance1, instance2)) { 119 return TaskEquality.IDENTICAL; 120 } else { 121 return null; 122 } 123 } 100 124 101 /* (non-Javadoc) 102 * @see TaskComparisonRule#areSemanticallyEqual(ITaskInstance, ITaskInstance) 103 */ 104 @Override 105 public boolean areSemanticallyEqual(ITaskInstance instance1, ITaskInstance instance2) { 106 return (instance1.getTask() == instance2.getTask()); 107 } 125 /* 126 * (non-Javadoc) 127 * 128 * @see TaskComparisonRule#isApplicable(ITask, ITask) 129 */ 130 @Override 131 public boolean isApplicable(ITask task1, ITask task2) { 132 return (task1 == task2); 133 } 108 134 109 /* (non-Javadoc) 110 * @see TaskComparisonRule#compare(ITaskInstance, ITaskInstance) 111 */ 112 @Override 113 public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) { 114 if (isApplicable(instance1, instance2)) { 115 return TaskEquality.IDENTICAL; 116 } 117 else { 118 return null; 119 } 120 } 135 /* 136 * (non-Javadoc) 137 * 138 * @see TaskComparisonRule#isApplicable(ITaskInstance, ITaskInstance) 139 */ 140 @Override 141 public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2) { 142 return (instance1.getTask() == instance2.getTask()); 143 } 121 144 122 145 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/ISessionScopeRule.java
r1146 r1733 21 21 /** 22 22 * <p> 23 * A session scope rule is able to detected temporal relationships between task instances of the 24 * sessions provided to the {@link #apply(List<IUserSession>)} method. The rule creates temporal 25 * relationships between the tasks of the task instances, i.e. substructures in the task tree, if 26 * it detects a temporal relationship and instantiates the temporal relationships according to 27 * their occurrences. 23 * A session scope rule is able to detected temporal relationships between task 24 * instances of the sessions provided to the {@link #apply(List<IUserSession>)} 25 * method. The rule creates temporal relationships between the tasks of the task 26 * instances, i.e. substructures in the task tree, if it detects a temporal 27 * relationship and instantiates the temporal relationships according to their 28 * occurrences. 28 29 * </p> 29 30 * … … 32 33 interface ISessionScopeRule extends ITemporalRelationshipRule { 33 34 34 /** 35 * <p> 36 * Applies the rule to the given sessions. The returned rule application result is null, if the 37 * rule can not be applied, i.e. it does not detect a temporal relationship. It returns a rule 38 * application result with a status {@link RuleApplicationStatus#RULE_APPLICATION_FINISHED} if 39 * the rule was applied. The result contains all newly created tasks and task instances. 40 * </p> 41 * 42 * @param sessions the session on which the rule shall be applied 43 * 44 * @return the rule application result as described. 45 */ 46 RuleApplicationResult apply(List<IUserSession> sessions); 35 /** 36 * <p> 37 * Applies the rule to the given sessions. The returned rule application 38 * result is null, if the rule can not be applied, i.e. it does not detect a 39 * temporal relationship. It returns a rule application result with a status 40 * {@link RuleApplicationStatus#RULE_APPLICATION_FINISHED} if the rule was 41 * applied. The result contains all newly created tasks and task instances. 42 * </p> 43 * 44 * @param sessions 45 * the session on which the rule shall be applied 46 * 47 * @return the rule application result as described. 48 */ 49 RuleApplicationResult apply(List<IUserSession> sessions); 47 50 48 51 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/ITaskInstanceScopeRule.java
r1294 r1733 19 19 /** 20 20 * <p> 21 * a task instance scope rule is able to detected temporal relationships between the children of 22 * a task instance provided to the {@link #apply(ITaskInstance)} method. A rule creates temporal 23 * relationships between the task instances, i.e. substructures in the task tree, if 24 * it detects a temporal relationship and instantiates the temporal relationships accordingly. 21 * a task instance scope rule is able to detected temporal relationships between 22 * the children of a task instance provided to the {@link #apply(ITaskInstance)} 23 * method. A rule creates temporal relationships between the task instances, 24 * i.e. substructures in the task tree, if it detects a temporal relationship 25 * and instantiates the temporal relationships accordingly. 25 26 * </p> 26 27 * … … 29 30 interface ITaskInstanceScopeRule extends ITemporalRelationshipRule { 30 31 31 /** 32 * <p> 33 * applies the rule to the given task instance. The returned rule application result is null, 34 * if the rule can not be applied, i.e. it does not detect a temporal relationship. It returns a 35 * rule application result with a status {@link RuleApplicationStatus#RULE_APPLICATION_FINISHED} 36 * if the rule was applied. The result contains all newly created parent tasks and task instances. 37 * </p> 38 * 39 * @param taskInstance the task instances to apply the rule on 40 * 41 * @return the rule application result as described. 42 */ 43 RuleApplicationResult apply(ITaskInstance taskInstance); 44 32 /** 33 * <p> 34 * applies the rule to the given task instance. The returned rule 35 * application result is null, if the rule can not be applied, i.e. it does 36 * not detect a temporal relationship. It returns a rule application result 37 * with a status {@link RuleApplicationStatus#RULE_APPLICATION_FINISHED} if 38 * the rule was applied. The result contains all newly created parent tasks 39 * and task instances. 40 * </p> 41 * 42 * @param taskInstance 43 * the task instances to apply the rule on 44 * 45 * @return the rule application result as described. 46 */ 47 RuleApplicationResult apply(ITaskInstance taskInstance); 48 45 49 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/ITemporalRelationshipRule.java
r1294 r1733 17 17 /** 18 18 * <p> 19 * a temporal relationship rule is the main interface for all rules applied for generating 20 * temporal relationships in a task tree. It is just a marker interface. More important are the 21 * sub interfaces {@link ISessionScopeRule} and {@link ITaskInstanceScopeRule}. 19 * a temporal relationship rule is the main interface for all rules applied for 20 * generating temporal relationships in a task tree. It is just a marker 21 * interface. More important are the sub interfaces {@link ISessionScopeRule} 22 * and {@link ITaskInstanceScopeRule}. 22 23 * </p> 23 24 * -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/RuleApplicationResult.java
r1707 r1733 24 24 /** 25 25 * <p> 26 * The rule application result describes the result of applying a {@link ITemporalRelationshipRule}. 27 * It contains a {@link RuleApplicationStatus} and a list of all parent task instances and tasks 28 * that were created during a rule application. See the description of 26 * The rule application result describes the result of applying a 27 * {@link ITemporalRelationshipRule}. It contains a 28 * {@link RuleApplicationStatus} and a list of all parent task instances and 29 * tasks that were created during a rule application. See the description of 29 30 * {@link ITemporalRelationshipRule} for more details. 30 31 * </p> … … 34 35 class RuleApplicationResult implements Serializable { 35 36 36 37 37 /** 38 38 * … … 41 41 42 42 /** */ 43 43 private RuleApplicationStatus status = RuleApplicationStatus.NOT_APPLIED; 44 44 45 46 privateList<ITask> newParentTasks = new ArrayList<ITask>();45 /** */ 46 private final List<ITask> newParentTasks = new ArrayList<ITask>(); 47 47 48 49 privateList<ITaskInstance> newParentInstances = new ArrayList<ITaskInstance>();48 /** */ 49 private final List<ITaskInstance> newParentInstances = new ArrayList<ITaskInstance>(); 50 50 51 /** 52 * <p> 53 * create a rule application result with a status {@link RuleApplicationStatus#RULE_NOT_APPLIED} 54 * </p> 55 */ 56 RuleApplicationResult() { 57 // this is the default indicating nothing so far 58 } 51 /** 52 * <p> 53 * create a rule application result with a status 54 * {@link RuleApplicationStatus#RULE_NOT_APPLIED} 55 * </p> 56 */ 57 RuleApplicationResult() { 58 // this is the default indicating nothing so far 59 } 59 60 60 61 62 * set the rule application status 63 64 65 void setRuleApplicationStatus(RuleApplicationStatus status) {66 this.status = status;67 61 /** 62 * <p> 63 * add a further parent task created during the rule application 64 * </p> 65 */ 66 void addNewlyCreatedTask(ITask newParent) { 67 newParentTasks.add(newParent); 68 } 68 69 69 70 71 * return the rule application status 72 73 74 RuleApplicationStatus getRuleApplicationStatus() {75 return status;76 70 /** 71 * <p> 72 * add a further parent task instance created during the rule application 73 * </p> 74 */ 75 void addNewlyCreatedTaskInstance(ITaskInstance newParent) { 76 newParentInstances.add(newParent); 77 } 77 78 78 79 80 * add a further parent taskcreated during the rule application81 82 83 void addNewlyCreatedTask(ITask newParent) {84 newParentTasks.add(newParent);85 79 /** 80 * <p> 81 * return all parent task instances created during the rule application 82 * </p> 83 */ 84 List<ITaskInstance> getNewlyCreatedTaskInstances() { 85 return newParentInstances; 86 } 86 87 87 88 89 90 91 92 93 94 88 /** 89 * <p> 90 * return all parent tasks created during the rule application 91 * </p> 92 */ 93 List<ITask> getNewlyCreatedTasks() { 94 return newParentTasks; 95 } 95 96 96 97 98 * add a further parent task instance created during the rule application 99 100 101 void addNewlyCreatedTaskInstance(ITaskInstance newParent) {102 newParentInstances.add(newParent);103 97 /** 98 * <p> 99 * return the rule application status 100 * </p> 101 */ 102 RuleApplicationStatus getRuleApplicationStatus() { 103 return status; 104 } 104 105 105 106 107 * return all parent task instances created during the rule application 108 109 110 List<ITaskInstance> getNewlyCreatedTaskInstances() {111 return newParentInstances;112 106 /** 107 * <p> 108 * set the rule application status 109 * </p> 110 */ 111 void setRuleApplicationStatus(RuleApplicationStatus status) { 112 this.status = status; 113 } 113 114 114 115 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/RuleApplicationStatus.java
r1281 r1733 17 17 /** 18 18 * <p> 19 * The rule application status describes the result of applying a {@link ITemporalRelationshipRule}. 20 * See the description of {@link ITemporalRelationshipRule} for more details. 19 * The rule application status describes the result of applying a 20 * {@link ITemporalRelationshipRule}. See the description of 21 * {@link ITemporalRelationshipRule} for more details. 21 22 * </p> 22 23 * … … 24 25 */ 25 26 enum RuleApplicationStatus { 26 FINISHED, 27 NOT_APPLIED; 27 FINISHED, NOT_APPLIED; 28 28 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/RuleUtils.java
r1731 r1733 15 15 package de.ugoe.cs.autoquest.tasktrees.temporalrelation; 16 16 17 import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration;18 import de.ugoe.cs.autoquest.tasktrees.treeifc.IIterationInstance;19 17 import de.ugoe.cs.autoquest.tasktrees.treeifc.IMarkingTemporalRelationship; 20 18 import de.ugoe.cs.autoquest.tasktrees.treeifc.IOptional; … … 24 22 import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence; 25 23 import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequenceInstance; 26 import de.ugoe.cs.autoquest.tasktrees.treeifc.IStructuringTemporalRelationship;27 24 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask; 28 25 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskBuilder; … … 42 39 /** 43 40 * <p> 44 * counter for generating unique ids. Starts at 0 for each new program start 45 * </p> 46 */ 47 private static int idCounter = 0; 48 49 public static int missedOptionals = 0; 50 41 * replaces a sub sequence for a specified range of elements in the provided 42 * task instances list by a sub task instance 43 * </p> 44 * 45 * @param parent 46 * the list of which the range shall be replaced 47 * @param startIndex 48 * the start index of the range 49 * @param endIndex 50 * the end index of the range (inclusive) 51 * @param model 52 * the task model (required for instantiating the sub sequence) 53 * @param taskFactory 54 * the task factory used for instantiating the sub sequence 55 * @param taskBuilder 56 * the task builder to perform changes in the task structure 57 * 58 * @return the replacement for the range 59 * @throws 60 */ 61 static ISequenceInstance createNewSubSequenceInRange( 62 ITaskInstanceList parent, int startIndex, int endIndex, 63 ISequence model, ITaskFactory taskFactory, ITaskBuilder taskBuilder) { 64 final ISequenceInstance subsequence = taskFactory 65 .createNewTaskInstance(model); 66 67 // TODO: Debug output 68 /* 69 * System.out.println("PRINTING MODEL: "); for (int i = 0; i < 70 * subsequence.getSequence().getChildren().size(); i++) { 71 * System.out.println(subsequence.getSequence().getChildren().get(i)); 72 * 73 * if (subsequence.getSequence().getChildren().get(i).getType() == 74 * "selection") { for (int j = 0; j < ((ISelection) 75 * subsequence.getSequence().getChildren().get(i)) 76 * .getChildren().size(); j++) { if(((IStructuringTemporalRelationship) 77 * subsequence 78 * .getSequence().getChildren().get(i)).getChildren().get(j).getType() 79 * =="sequence") { ISequence foo = (ISequence) ((ISelection) 80 * (subsequence 81 * .getSequence().getChildren().get(i))).getChildren().get(j); 82 * System.out.println("\t" + foo); for(int k=0; k< 83 * foo.getChildren().size();k++) { System.out.println("\t\t" 84 * +foo.getChildren().get(k)); } System.out.println(); } else{ 85 * System.out.println("\t" + ((ISelection) 86 * subsequence.getSequence().getChildren().get(i)) 87 * .getChildren().get(j)); } 88 * 89 * } } 90 * 91 * } System.out.println(); 92 */ 93 94 // TODO: This is dirty! 95 missedOptionals = 0; 96 int modelindex = 0; 97 for (int i = startIndex; i <= endIndex; i++) { 98 99 if (modelindex == model.getChildren().size()) { 100 break; 101 } 102 final ITask tempTask = model.getChildren().get(modelindex); 103 // System.out.println("Trying to add " + parent.get(startIndex) 104 // + " to the model instance " + tempTask); 105 if (tempTask.getType() == "optionality") { 106 107 if (((IMarkingTemporalRelationship) tempTask).getMarkedTask() == parent 108 .get(startIndex).getTask()) { 109 // System.out.println("Adding OptionalInstance " + 110 // parent.get(startIndex) + " to " + tempTask.getType()); 111 final IOptionalInstance optional = taskFactory 112 .createNewTaskInstance((IOptional) tempTask); 113 taskBuilder.setChild(optional, parent.get(startIndex)); 114 taskBuilder.addChild(subsequence, optional); 115 } else { 116 // System.out.println("Adding Empty optional, not deleting anything from the input sequence"); 117 final IOptionalInstance optional = taskFactory 118 .createNewTaskInstance((IOptional) tempTask); 119 taskBuilder.addChild(subsequence, optional); 120 modelindex++; 121 missedOptionals++; 122 continue; 123 } 124 } else if (tempTask.getType() == "selection") { 125 final ISelectionInstance selection = taskFactory 126 .createNewTaskInstance((ISelection) tempTask); 127 final ISelection tmpSel = (ISelection) tempTask; 128 if ((tmpSel.getChildren().get(0).getType() == "sequence") 129 && (tmpSel.getChildren().get(1).getType() == "sequence")) { 130 ISequenceInstance selseq = null; 131 // The selection I create can just have 2 children 132 if (parent.get(startIndex).getTask().getId() == ((ISequence) tmpSel 133 .getChildren().get(0)).getChildren().get(0).getId()) { 134 selseq = taskFactory 135 .createNewTaskInstance((ISequence) tmpSel 136 .getChildren().get(0)); 137 } else if (parent.get(startIndex).getTask().getId() == ((ISequence) tmpSel 138 .getChildren().get(1)).getChildren().get(0).getId()) { 139 selseq = taskFactory 140 .createNewTaskInstance((ISequence) tmpSel 141 .getChildren().get(1)); 142 } else if ((parent.get(startIndex).getTask().getId() == tmpSel 143 .getChildren().get(0).getId()) 144 || (parent.get(startIndex).getTask().getId() == tmpSel 145 .getChildren().get(1).getId())) { 146 // System.out.println("Session ID: " + 147 // parent.get(startIndex).getTask().getId() + 148 // " tmpSel(0): " + tmpSel.getChildren().get(0).getId() 149 // + " tmpSel(1): " +tmpSel.getChildren().get(1).getId() 150 // ); 151 continue; 152 } 153 154 for (int k = 0; k < selseq.getSequence().getChildren() 155 .size(); k++) { 156 // System.out.println("Trying to add " + 157 // parent.get(startIndex) + " to " + selseq); 158 taskBuilder.addChild(selseq, parent.get(startIndex)); 159 taskBuilder.removeTaskInstance(parent, startIndex); 160 i++; 161 // System.out.println("I:" + i); 162 } 163 // System.out.println("Trying to add " + selseq + " to " + 164 // tmpSel); 165 taskBuilder.setChild(selection, selseq); 166 taskBuilder.addChild(subsequence, selection); 167 modelindex++; 168 continue; 169 } else { 170 // System.out.println("Trying to adding SelectionInstance " 171 // + parent.get(startIndex) + " to " + tempTask); 172 taskBuilder.setChild(selection, parent.get(startIndex)); 173 taskBuilder.addChild(subsequence, selection); 174 } 175 } else if (tempTask.getType() == "sequence") { 176 // System.out.println("Adding SequenceInstance " + 177 // parent.get(startIndex) + " to " + tempTask); 178 taskBuilder.addChild(subsequence, parent.get(startIndex)); 179 } else if (tempTask.getType() == "iteration") { 180 // System.out.println("Adding IterationInstance " + 181 // parent.get(startIndex) + " to " + tempTask); 182 taskBuilder.addChild(subsequence, parent.get(startIndex)); 183 } else { 184 // System.out.println("Adding EventInstance " + 185 // parent.get(startIndex) + " to " + tempTask); 186 // System.out.println("Foo"); 187 taskBuilder.addChild(subsequence, parent.get(startIndex)); 188 } 189 taskBuilder.removeTaskInstance(parent, startIndex); 190 modelindex++; 191 } 192 193 taskBuilder.addTaskInstance(parent, startIndex, subsequence); 194 195 return subsequence; 196 } 197 198 /** 199 * <p> 200 * returns the next available id (uses the id counter) 201 * </p> 202 * 203 * @return the next available id 204 */ 205 static synchronized String getNewId() { 206 return Integer.toString(idCounter++); 207 } 208 51 209 /** 52 210 * <p> … … 73 231 int startIndex, int endIndex, ISequence model, 74 232 ITaskFactory taskFactory, ITaskBuilder taskBuilder) { 75 ISequenceInstance subsequence = taskFactory233 final ISequenceInstance subsequence = taskFactory 76 234 .createNewTaskInstance(model); 77 235 … … 83 241 } 84 242 85 /**86 * <p>87 * replaces a sub sequence for a specified range of elements in the provided88 * task instances list by a sub task instance89 * </p>90 *91 * @param parent92 * the list of which the range shall be replaced93 * @param startIndex94 * the start index of the range95 * @param endIndex96 * the end index of the range (inclusive)97 * @param model98 * the task model (required for instantiating the sub sequence)99 * @param taskFactory100 * the task factory used for instantiating the sub sequence101 * @param taskBuilder102 * the task builder to perform changes in the task structure103 *104 * @return the replacement for the range105 * @throws106 */107 static ISequenceInstance createNewSubSequenceInRange(108 ITaskInstanceList parent, int startIndex, int endIndex,109 ISequence model, ITaskFactory taskFactory, ITaskBuilder taskBuilder) {110 ISequenceInstance subsequence = taskFactory111 .createNewTaskInstance(model);112 113 114 // TODO: Debug output115 /*116 System.out.println("PRINTING MODEL: ");117 for (int i = 0; i < subsequence.getSequence().getChildren().size(); i++) {118 System.out.println(subsequence.getSequence().getChildren().get(i));119 120 if (subsequence.getSequence().getChildren().get(i).getType() == "selection") {121 for (int j = 0; j < ((ISelection) subsequence.getSequence().getChildren().get(i))122 .getChildren().size(); j++) {123 if(((IStructuringTemporalRelationship) subsequence.getSequence().getChildren().get(i)).getChildren().get(j).getType() =="sequence")124 {125 ISequence foo = (ISequence) ((ISelection) (subsequence.getSequence().getChildren().get(i))).getChildren().get(j);126 System.out.println("\t" + foo);127 for(int k=0; k< foo.getChildren().size();k++) {128 System.out.println("\t\t" +foo.getChildren().get(k));129 }130 System.out.println();131 }132 else{133 System.out.println("\t"134 + ((ISelection) subsequence.getSequence().getChildren().get(i))135 .getChildren().get(j));136 }137 138 }139 }140 141 }142 System.out.println();143 */144 145 //TODO: This is dirty!146 missedOptionals=0;147 int modelindex=0;148 for (int i = startIndex; i <= endIndex; i++) {149 150 if(modelindex == model.getChildren().size()) {151 break;152 }153 ITask tempTask = model.getChildren().get(modelindex);154 //System.out.println("Trying to add " + parent.get(startIndex)155 // + " to the model instance " + tempTask);156 if (tempTask.getType() == "optionality") {157 158 if(((IMarkingTemporalRelationship) tempTask).getMarkedTask() == parent.get(startIndex).getTask()) {159 //System.out.println("Adding OptionalInstance " + parent.get(startIndex) + " to " + tempTask.getType());160 IOptionalInstance optional = taskFactory.createNewTaskInstance((IOptional) tempTask);161 taskBuilder.setChild(optional, parent.get(startIndex));162 taskBuilder.addChild(subsequence, optional);163 }164 else {165 //System.out.println("Adding Empty optional, not deleting anything from the input sequence");166 IOptionalInstance optional = taskFactory.createNewTaskInstance((IOptional) tempTask);167 taskBuilder.addChild(subsequence, optional);168 modelindex++;169 missedOptionals++;170 continue;171 }172 } else if (tempTask.getType() == "selection") {173 ISelectionInstance selection = taskFactory.createNewTaskInstance((ISelection) tempTask);174 ISelection tmpSel = (ISelection)tempTask;175 if(tmpSel.getChildren().get(0).getType() == "sequence" && tmpSel.getChildren().get(1).getType()=="sequence") {176 ISequenceInstance selseq = null;177 //The selection I create can just have 2 children178 if(parent.get(startIndex).getTask().getId() == ((ISequence)tmpSel.getChildren().get(0)).getChildren().get(0).getId()) {179 selseq = taskFactory.createNewTaskInstance((ISequence) tmpSel.getChildren().get(0));180 }181 else if(parent.get(startIndex).getTask().getId() == ((ISequence)tmpSel.getChildren().get(1)).getChildren().get(0).getId()) {182 selseq = taskFactory.createNewTaskInstance((ISequence) tmpSel.getChildren().get(1));183 }184 else if(parent.get(startIndex).getTask().getId() == tmpSel.getChildren().get(0).getId() || parent.get(startIndex).getTask().getId() == tmpSel.getChildren().get(1).getId() ) {185 //System.out.println("Session ID: " + parent.get(startIndex).getTask().getId() + " tmpSel(0): " + tmpSel.getChildren().get(0).getId() + " tmpSel(1): " +tmpSel.getChildren().get(1).getId() );186 continue;187 }188 189 for (int k=0;k<selseq.getSequence().getChildren().size();k++) {190 //System.out.println("Trying to add " + parent.get(startIndex) + " to " + selseq);191 taskBuilder.addChild(selseq,parent.get(startIndex));192 taskBuilder.removeTaskInstance(parent, startIndex);193 i++;194 //System.out.println("I:" + i);195 }196 //System.out.println("Trying to add " + selseq + " to " + tmpSel);197 taskBuilder.setChild(selection, selseq);198 taskBuilder.addChild(subsequence, selection);199 modelindex++;200 continue;201 }202 else203 {204 //System.out.println("Trying to adding SelectionInstance " + parent.get(startIndex) + " to " + tempTask);205 taskBuilder.setChild(selection, parent.get(startIndex));206 taskBuilder.addChild(subsequence,selection);207 }208 } else if (tempTask.getType() == "sequence") {209 //System.out.println("Adding SequenceInstance " + parent.get(startIndex) + " to " + tempTask);210 taskBuilder.addChild(subsequence, parent.get(startIndex));211 } else if (tempTask.getType() == "iteration") {212 //System.out.println("Adding IterationInstance " + parent.get(startIndex) + " to " + tempTask);213 taskBuilder.addChild(subsequence, parent.get(startIndex));214 } else {215 //System.out.println("Adding EventInstance " + parent.get(startIndex) + " to " + tempTask);216 //System.out.println("Foo");217 taskBuilder.addChild(subsequence, parent.get(startIndex));218 }219 taskBuilder.removeTaskInstance(parent, startIndex);220 modelindex++;221 }222 223 taskBuilder.addTaskInstance(parent, startIndex, subsequence);224 225 return subsequence;226 }227 228 229 243 // Print out the progress 230 static void printProgressPercentage(String message, int count, int size) {244 static void printProgressPercentage(String message, int count, int size) { 231 245 if (size > 100) { 232 if (( count % (size / 100) == 0)) {246 if (((count % (size / 100)) == 0)) { 233 247 // Console.traceln(Level.INFO,("Thread" + 234 248 // Thread.currentThread().getName() + ": " + Math.round((float) 235 249 // count/size*100))+ "%"); 236 System.out.println(message + " in thread" + Thread.currentThread().getName() 237 + ": " + Math.round((float) count / size * 100) + "%"); 250 System.out.println(message + " in thread" 251 + Thread.currentThread().getName() + ": " 252 + Math.round(((float) count / size) * 100) + "%"); 238 253 } 239 254 } else { … … 241 256 // Thread.currentThread().getName() + ": " +Math.round((float) 242 257 // count/size*100))+ "%"); 243 System.out.println(message + " in thread" + Thread.currentThread().getName() 244 + ": " + Math.round((float) count / size * 100) + "%"); 258 System.out.println(message + " in thread" 259 + Thread.currentThread().getName() + ": " 260 + Math.round(((float) count / size) * 100) + "%"); 245 261 246 262 } 247 263 } 248 264 249 250 /** 251 * <p> 252 * returns the next available id (uses the id counter) 253 * </p> 254 * 255 * @return the next available id 256 */ 257 static synchronized String getNewId() { 258 return Integer.toString(idCounter++); 259 } 265 /** 266 * <p> 267 * counter for generating unique ids. Starts at 0 for each new program start 268 * </p> 269 */ 270 private static int idCounter = 0; 271 272 public static int missedOptionals = 0; 260 273 261 274 /** -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/SequenceForTaskDetectionRule.java
r1401 r1733 45 45 /** 46 46 * <p> 47 * This class implements the major rule for creating task trees based on a set of recorded 48 * user sessions. For this, it first harmonizes all tasks. This eases later comparison. Then it 49 * searches the sessions for iterations and replaces them accordingly. Then it searches for sub 50 * sequences being the longest and occurring most often. For each found sub sequence, it replaces 51 * the occurrences by creating appropriate {@link ISequence}s. Afterwards, again searches for 52 * iterations and then again for sub sequences until no more replacements are done. 47 * This class implements the major rule for creating task trees based on a set 48 * of recorded user sessions. For this, it first harmonizes all tasks. This 49 * eases later comparison. Then it searches the sessions for iterations and 50 * replaces them accordingly. Then it searches for sub sequences being the 51 * longest and occurring most often. For each found sub sequence, it replaces 52 * the occurrences by creating appropriate {@link ISequence}s. Afterwards, again 53 * searches for iterations and then again for sub sequences until no more 54 * replacements are done. 53 55 * </p> 54 56 * <p> 55 * For determining the longest sequence occurring most often, the implementation uses a56 * {@link Trie}. The depth of the tree is initially 3. If the algorithm has a longest sequence57 * occurring most often whose length is equal to the depth of the trie, it recalculates the trie58 * with an increased depth.57 * For determining the longest sequence occurring most often, the implementation 58 * uses a {@link Trie}. The depth of the tree is initially 3. If the algorithm 59 * has a longest sequence occurring most often whose length is equal to the 60 * depth of the trie, it recalculates the trie with an increased depth. 59 61 * </p> 60 62 * … … 62 64 */ 63 65 class SequenceForTaskDetectionRule implements ISessionScopeRule { 64 65 /** 66 * <p> 67 * the task factory to be used for creating substructures for the temporal 68 * relationships identified during rul application 69 * </p> 70 */ 71 private ITaskFactory taskFactory; 72 /** 73 * <p> 74 * the task builder to be used for creating substructures for the temporal relationships 75 * identified during rule application 76 * </p> 77 */ 78 private ITaskBuilder taskBuilder; 79 80 /** 81 * <p> 82 * the task handling strategy to be used for comparing tasks for preparation, i.e., before 83 * the tasks are harmonized 84 * </p> 85 */ 86 private TaskHandlingStrategy preparationTaskHandlingStrategy; 87 88 /** 89 * <p> 90 * the task handling strategy to be used for comparing tasks during iteration detection an trie 91 * generation, i.e., after the tasks are harmonized 92 * </p> 93 */ 94 private TaskHandlingStrategy identityTaskHandlingStrategy;; 95 96 /** 97 * <p> 98 * instantiates the rule and initializes it with a task equality to be considered when 99 * comparing tasks as well as a task factory and builder to be used for creating task 100 * structures. 101 * </p> 102 * 103 * @param minimalTaskEquality the task equality to be considered when comparing tasks 104 * @param taskFactory the task factory to be used for creating substructures 105 * @param taskBuilder the task builder to be used for creating substructures 106 */ 107 SequenceForTaskDetectionRule(TaskEquality minimalTaskEquality, 108 ITaskFactory taskFactory, 109 ITaskBuilder taskBuilder) 110 { 111 this.taskFactory = taskFactory; 112 this.taskBuilder = taskBuilder; 113 114 this.preparationTaskHandlingStrategy = new TaskHandlingStrategy(minimalTaskEquality); 115 this.identityTaskHandlingStrategy = new TaskHandlingStrategy(TaskEquality.IDENTICAL); 116 } 117 118 /* (non-Javadoc) 119 * @see java.lang.Object#toString() 120 */ 121 @Override 122 public String toString() { 123 return "SequenceForTaskDetectionRule"; 124 } 125 126 /* (non-Javadoc) 127 * @see de.ugoe.cs.autoquest.tasktrees.temporalrelation.ISessionScopeRule#apply(java.util.List) 128 */ 129 @Override 130 public RuleApplicationResult apply(List<IUserSession> sessions) { 131 RuleApplicationData appData = new RuleApplicationData(sessions); 132 133 // this is the real rule application. Loop while something is replaced. 134 harmonizeEventTaskInstancesModel(appData); 135 do { 136 System.out.println(); 137 138 appData.getStopWatch().start("whole loop"); 139 detectAndReplaceIterations(appData); 140 141 appData.getStopWatch().start("task replacement"); 142 detectAndReplaceTasks(appData); 143 appData.getStopWatch().stop("task replacement"); 144 appData.getStopWatch().stop("whole loop"); 145 146 //((TaskTreeNodeComparator) taskComparator).getStopWatch().dumpStatistics(System.out); 147 //((TaskTreeNodeComparator) taskComparator).getStopWatch().reset(); 148 149 appData.getStopWatch().dumpStatistics(System.out); 150 appData.getStopWatch().reset(); 151 152 } 153 while (appData.detectedAndReplacedTasks()); 154 155 Console.println 156 ("created " + appData.getResult().getNewlyCreatedTasks().size() + 157 " new tasks and " + appData.getResult().getNewlyCreatedTaskInstances().size() + 158 " appropriate instances\n"); 159 160 if ((appData.getResult().getNewlyCreatedTasks().size() > 0) || 161 (appData.getResult().getNewlyCreatedTaskInstances().size() > 0)) 162 { 163 appData.getResult().setRuleApplicationStatus(RuleApplicationStatus.FINISHED); 164 } 165 166 return appData.getResult(); 167 } 168 169 /** 170 * <p> 171 * harmonizes the event task instances by unifying tasks. This is done, as initially the 172 * event tasks being equal with respect to the considered task equality are distinct objects. 173 * The comparison of these distinct objects is more time consuming than comparing the object 174 * references. 175 * </p> 176 * 177 * @param appData the rule application data combining all data used for applying this rule 178 */ 179 private void harmonizeEventTaskInstancesModel(RuleApplicationData appData) { 180 Console.traceln(Level.INFO, "harmonizing task model of event task instances"); 181 appData.getStopWatch().start("harmonizing event tasks"); 182 183 SymbolMap<ITaskInstance, ITask> uniqueTasks = 184 preparationTaskHandlingStrategy.createSymbolMap(); 185 TaskInstanceComparator comparator = preparationTaskHandlingStrategy.getTaskComparator(); 186 187 int unifiedTasks = 0; 188 ITask task; 189 List<IUserSession> sessions = appData.getSessions(); 190 int sessionNo = 0; 191 for (IUserSession session : sessions) { 192 Console.traceln(Level.FINE, "handling " + (++sessionNo) + ". " + session); 193 for (ITaskInstance taskInstance : session) { 194 task = uniqueTasks.getValue(taskInstance); 195 196 if (task == null) { 197 uniqueTasks.addSymbol(taskInstance, taskInstance.getTask()); 198 } 199 else { 200 taskBuilder.setTask(taskInstance, task); 201 unifiedTasks++; 202 } 203 } 204 205 comparator.clearBuffers(); 206 } 207 208 appData.getStopWatch().stop("harmonizing event tasks"); 209 Console.traceln(Level.INFO, "harmonized " + unifiedTasks + " task occurrences (still " + 210 uniqueTasks.size() + " different tasks)"); 211 212 appData.getStopWatch().dumpStatistics(System.out); 213 appData.getStopWatch().reset(); 214 } 215 216 /** 217 * <p> 218 * searches for direct iterations of single tasks in all sequences and replaces them with 219 * {@link IIteration}s, respectively appropriate instances. Also all single occurrences of 220 * a task that is iterated somewhen are replaced with iterations to have again an efficient 221 * way for task comparisons. 222 * </p> 223 * 224 * @param appData the rule application data combining all data used for applying this rule 225 */ 226 private void detectAndReplaceIterations(RuleApplicationData appData) { 227 Console.traceln(Level.FINE, "detecting iterations"); 228 appData.getStopWatch().start("detecting iterations"); 229 230 List<IUserSession> sessions = appData.getSessions(); 231 232 Set<ITask> iteratedTasks = searchIteratedTasks(sessions); 233 234 if (iteratedTasks.size() > 0) { 235 replaceIterationsOf(iteratedTasks, sessions, appData); 236 } 237 238 appData.getStopWatch().stop("detecting iterations"); 239 Console.traceln(Level.INFO, "replaced " + iteratedTasks.size() + " iterated tasks"); 240 } 241 242 /** 243 * <p> 244 * searches the provided sessions for task iterations. If a task is iterated, it is added 245 * to the returned set. 246 * </p> 247 * 248 * @param the session to search for iterations in 249 * 250 * @return a set of tasks being iterated somewhere 251 */ 252 private Set<ITask> searchIteratedTasks(List<IUserSession> sessions) { 253 Set<ITask> iteratedTasks = new HashSet<ITask>(); 254 for (IUserSession session : sessions) { 255 for (int i = 0; i < (session.size() - 1); i++) { 256 // we prepared the task instances to refer to unique tasks, if they are treated 257 // as equal. Therefore, we just compare the identity of the tasks of the task 258 // instances 259 if (session.get(i).getTask() == session.get(i + 1).getTask()) { 260 iteratedTasks.add(session.get(i).getTask()); 261 } 262 } 263 } 264 265 return iteratedTasks; 266 } 267 268 /** 269 * <p> 270 * replaces all occurrences of all tasks provided in the set with iterations 271 * </p> 272 * 273 * @param iteratedTasks the tasks to be replaced with iterations 274 * @param sessions the sessions in which the tasks are to be replaced 275 * @param appData the rule application data combining all data used for applying this rule 276 */ 277 private void replaceIterationsOf(Set<ITask> iteratedTasks, 278 List<IUserSession> sessions, 279 RuleApplicationData appData) 280 { 281 Map<ITask, IIteration> iterations = new HashMap<ITask, IIteration>(); 282 Map<IIteration, List<IIterationInstance>> iterationInstances = 283 new HashMap<IIteration, List<IIterationInstance>>(); 284 285 for (ITask iteratedTask : iteratedTasks) { 286 IIteration iteration = taskFactory.createNewIteration(); 287 iterations.put(iteratedTask, iteration); 288 iterationInstances.put(iteration, new LinkedList<IIterationInstance>()); 289 } 290 291 IIterationInstance iterationInstance; 292 293 for (IUserSession session : sessions) { 294 int index = 0; 295 iterationInstance = null; 296 297 while (index < session.size()) { 298 // we prepared the task instances to refer to unique tasks, if they are treated 299 // as equal. Therefore, we just compare the identity of the tasks of the task 300 // instances 301 ITask currentTask = session.get(index).getTask(); 302 IIteration iteration = iterations.get(currentTask); 303 if (iteration != null) { 304 if ((iterationInstance == null) || (iterationInstance.getTask() != iteration)) 305 { 306 iterationInstance = taskFactory.createNewTaskInstance(iteration); 307 iterationInstances.get(iteration).add(iterationInstance); 308 taskBuilder.addTaskInstance(session, index, iterationInstance); 309 index++; 310 } 311 312 taskBuilder.addChild(iterationInstance, session.get(index)); 313 taskBuilder.removeTaskInstance(session, index); 314 } 315 else { 316 if (iterationInstance != null) { 317 iterationInstance = null; 318 } 319 index++; 320 } 321 } 322 } 323 324 for (Map.Entry<IIteration, List<IIterationInstance>> entry : iterationInstances.entrySet()) 325 { 326 harmonizeIterationInstancesModel(entry.getKey(), entry.getValue()); 327 } 328 } 329 330 /** 331 * <p> 332 * TODO clarify why this is done 333 * </p> 334 */ 335 private void harmonizeIterationInstancesModel(IIteration iteration, 336 List<IIterationInstance> iterationInstances) 337 { 338 List<ITask> iteratedTaskVariants = new LinkedList<ITask>(); 339 TaskInstanceComparator comparator = preparationTaskHandlingStrategy.getTaskComparator(); 340 341 // merge the lexically different variants of iterated task to a unique list 342 for (IIterationInstance iterationInstance : iterationInstances) { 343 for (ITaskInstance executionVariant : iterationInstance) { 344 ITask candidate = executionVariant.getTask(); 345 346 boolean found = false; 347 for (ITask taskVariant : iteratedTaskVariants) { 348 if (comparator.areLexicallyEqual(taskVariant, candidate)) { 349 taskBuilder.setTask(executionVariant, taskVariant); 350 found = true; 351 break; 352 } 353 } 354 355 if (!found) { 356 iteratedTaskVariants.add(candidate); 357 } 358 } 359 } 360 361 // if there are more than one lexically different variant of iterated tasks, adapt the 362 // iteration model to be a selection of different variants. In this case also adapt 363 // the generated iteration instances to correctly contain selection instances. If there 364 // is only one variant of an iterated task, simply set this as the marked task of the 365 // iteration. In this case, the instances can be preserved as is 366 if (iteratedTaskVariants.size() > 1) { 367 ISelection selection = taskFactory.createNewSelection(); 368 369 for (ITask variant : iteratedTaskVariants) { 370 taskBuilder.addChild(selection, variant); 371 } 372 373 taskBuilder.setMarkedTask(iteration, selection); 374 375 for (IIterationInstance instance : iterationInstances) { 376 for (int i = 0; i < instance.size(); i++) { 377 ISelectionInstance selectionInstance = 378 taskFactory.createNewTaskInstance(selection); 379 taskBuilder.setChild(selectionInstance, instance.get(i)); 380 taskBuilder.setTaskInstance(instance, i, selectionInstance); 381 } 382 } 383 } 384 else { 385 taskBuilder.setMarkedTask(iteration, iteratedTaskVariants.get(0)); 386 } 387 } 388 389 /** 390 * TODO go on commenting 391 * @param appData the rule application data combining all data used for applying this rule 392 */ 393 private void detectAndReplaceTasks(RuleApplicationData appData) { 394 Console.traceln(Level.FINE, "detecting and replacing tasks"); 395 appData.getStopWatch().start("detecting tasks"); 396 397 getSequencesOccuringMostOften(appData); 398 399 appData.getStopWatch().stop("detecting tasks"); 400 appData.getStopWatch().start("replacing tasks"); 401 402 replaceSequencesOccurringMostOften(appData); 403 404 appData.getStopWatch().stop("replacing tasks"); 405 Console.traceln(Level.INFO, "detected and replaced " + appData.getLastFoundTasks().size() + 406 " tasks occuring " + appData.getLastFoundTasks().getOccurrenceCount() + 407 " times"); 408 } 409 410 /** 411 * @param appData the rule application data combining all data used for applying this rule 412 */ 413 private void getSequencesOccuringMostOften(RuleApplicationData appData) { 414 Console.traceln(Level.FINE, "determining most prominent tasks"); 415 416 Tasks tasks; 417 boolean createNewTrie = (appData.getLastTrie() == null) || 418 appData.detectedAndReplacedTasks(); // tree has changed 419 420 do { 421 if (createNewTrie) { 422 createNewTrie(appData); 423 } 424 425 MaxCountAndLongestTasksFinder finder = new MaxCountAndLongestTasksFinder(); 426 appData.getLastTrie().process(finder); 427 428 tasks = finder.getFoundTasks(); 429 430 createNewTrie = false; 431 432 for (List<ITaskInstance> task : tasks) { 433 if (task.size() >= appData.getTrainedSequenceLength()) { 434 // Trie must be recreated with a longer sequence length to be sure that 435 // the found sequences occurring most often are found in their whole length 436 appData.setTrainedSequenceLength(appData.getTrainedSequenceLength() + 1); 437 createNewTrie = true; 438 break; 439 } 440 } 441 } 442 while (createNewTrie); 443 444 // create a normal trie for comparison 445 /*System.out.println("creating test trie for comparison"); 446 447 appData.getStopWatch().start("testtrie"); 448 Trie<ITaskInstance> trie = new Trie<ITaskInstance>(identityTaskComparator); 449 450 for (IUserSession session : appData.getSessions()) { 451 trie.train(session.getExecutedTasks(), appData.getTrainedSequenceLength()); 452 } 453 454 appData.getStopWatch().stop("testtrie"); 455 456 MaxCountAndLongestTasksFinder finder = new MaxCountAndLongestTasksFinder(); 457 trie.process(finder); 458 459 boolean allTasksEqual = finder.getFoundTasks().size() == tasks.size(); 460 461 allTasksEqual &= finder.getFoundTasks().occurrenceCount == tasks.occurrenceCount; 462 463 for (List<ITaskInstance> task1 : finder.getFoundTasks()) { 464 boolean foundTask = false; 465 for (List<ITaskInstance> task2 : tasks) { 466 boolean tasksEqual = false; 467 if (task1.size() == task2.size()) { 468 tasksEqual = true; 469 for (int i = 0; i < task1.size(); i++) { 470 if (!identityTaskComparator.equals(task1.get(i).getTask(), task2.get(i).getTask())) 471 { 472 tasksEqual = false; 473 } 474 } 475 } 476 477 if (tasksEqual) { 478 foundTask = true; 479 break; 480 } 481 } 482 483 if (!foundTask) { 484 System.out.println("different is " + task1); 485 allTasksEqual = false; 486 break; 487 } 488 } 489 490 if (!allTasksEqual) { 491 System.out.println(finder.getFoundTasks()); 492 System.out.println(tasks); 493 494 throw new IllegalArgumentException("both tries calculated different subsequences"); 495 } 496 497 /*TrieStatisticsDumper dumper = new TrieStatisticsDumper(); 498 appData.getLastTrie().process(dumper); 499 dumper.dumpCounters();*/ 500 501 appData.setLastFoundTasks(tasks); 502 503 Console.traceln(Level.FINE, "found " + appData.getLastFoundTasks().size() + " tasks " + 504 "occurring " + appData.getLastFoundTasks().getOccurrenceCount() + " times"); 505 } 506 507 /** 508 * @param appData the rule application data combining all data used for applying this rule 509 */ 510 private void createNewTrie(RuleApplicationData appData) { 511 Console.traceln(Level.FINER, "training trie with a maximum sequence length of " + 512 appData.getTrainedSequenceLength()); 513 514 appData.getStopWatch().start("training trie"); 515 516 // we prepared the task instances to refer to unique tasks, if they are treated 517 // as equal. Therefore, we just compare the identity of the tasks of the task 518 // instances 519 appData.setLastTrie(new TaskInstanceTrie(identityTaskHandlingStrategy)); 520 521 appData.getLastTrie().trainSessions 522 (appData.getSessions(), appData.getTrainedSequenceLength()); 523 524 appData.getStopWatch().stop("training trie"); 525 } 526 527 /** 528 * @param appData the rule application data combining all data used for applying this rule 529 */ 530 private void replaceSequencesOccurringMostOften(RuleApplicationData appData) { 531 appData.detectedAndReplacedTasks(false); 532 533 if ((appData.getLastFoundTasks().size() > 0) && 534 (appData.getLastFoundTasks().getOccurrenceCount() > 1)) 535 { 536 Console.traceln(Level.FINER, "replacing tasks occurrences"); 537 538 for (List<ITaskInstance> task : appData.getLastFoundTasks()) { 539 ISequence sequence = taskFactory.createNewSequence(); 540 541 Console.traceln(Level.FINEST, "replacing " + sequence.getId() + ": " + task); 542 543 List<ISequenceInstance> sequenceInstances = 544 replaceTaskOccurrences(task, appData.getSessions(), sequence); 545 546 harmonizeSequenceInstancesModel(sequence, sequenceInstances,task.size()); 547 appData.detectedAndReplacedTasks 548 (appData.detectedAndReplacedTasks() || (sequenceInstances.size() > 0)); 549 550 if (sequenceInstances.size() < appData.getLastFoundTasks().getOccurrenceCount()) { 551 Console.traceln(Level.FINE, sequence.getId() + ": replaced task only " + 552 sequenceInstances.size() + " times instead of expected " + 553 appData.getLastFoundTasks().getOccurrenceCount()); 554 } 555 } 556 } 557 558 } 559 560 /** 561 * 562 */ 563 private void harmonizeSequenceInstancesModel(ISequence sequence, 564 List<ISequenceInstance> sequenceInstances, 565 int sequenceLength) 566 { 567 TaskInstanceComparator comparator = preparationTaskHandlingStrategy.getTaskComparator(); 568 569 // ensure for each subtask that lexically different variants are preserved 570 for (int subTaskIndex = 0; subTaskIndex < sequenceLength; subTaskIndex++) { 571 List<ITask> subTaskVariants = new LinkedList<ITask>(); 572 573 for (ISequenceInstance sequenceInstance : sequenceInstances) { 574 ITask candidate = sequenceInstance.get(subTaskIndex).getTask(); 575 576 boolean found = false; 577 578 for (int i = 0; i < subTaskVariants.size(); i++) { 579 if (comparator.areLexicallyEqual(subTaskVariants.get(i), candidate)) { 580 taskBuilder.setTask 581 (sequenceInstance.get(subTaskIndex), subTaskVariants.get(i)); 582 583 found = true; 584 break; 585 } 586 } 587 588 if (!found) { 589 subTaskVariants.add(candidate); 590 } 591 } 592 593 // if there are more than one lexically different variant of the sub task at 594 // the considered position, adapt the sequence model at that position to have 595 // a selection of the different variants. In this case also adapt the 596 // generated sequence instances to correctly contain selection instances. If 597 // there is only one variant of sub tasks at the given position, simply set 598 // this variant as the sub task of the selection. In this case, the instances 599 // can be preserved as is 600 if (subTaskVariants.size() > 1) { 601 ISelection selection = taskFactory.createNewSelection(); 602 603 for (ITask variant : subTaskVariants) { 604 taskBuilder.addChild(selection, variant); 605 } 606 607 taskBuilder.addChild(sequence, selection); 608 609 for (ISequenceInstance instance : sequenceInstances) { 610 ISelectionInstance selectionInstance = 611 taskFactory.createNewTaskInstance(selection); 612 taskBuilder.setChild(selectionInstance, instance.get(subTaskIndex)); 613 taskBuilder.setTaskInstance(instance, subTaskIndex, selectionInstance); 614 } 615 } 616 else if (subTaskVariants.size() == 1) { 617 taskBuilder.addChild(sequence, subTaskVariants.get(0)); 618 } 619 } 620 } 621 622 /** 623 * @param tree 624 */ 625 private List<ISequenceInstance> replaceTaskOccurrences(List<ITaskInstance> task, 626 List<IUserSession> sessions, 627 ISequence temporalTaskModel) 628 { 629 List<ISequenceInstance> sequenceInstances = new LinkedList<ISequenceInstance>(); 630 631 for (IUserSession session : sessions) { 632 int index = -1; 633 634 do { 635 index = getSubListIndex(session, task, ++index); 636 637 if (index > -1) { 638 sequenceInstances.add 639 (RuleUtils.createNewSubSequenceInRange 640 (session, index, index + task.size() - 1, temporalTaskModel, 641 taskFactory, taskBuilder)); 642 } 643 } 644 while (index > -1); 645 } 646 647 return sequenceInstances; 648 } 649 650 /** 651 * @param trie 652 * @param object 653 * @return 654 */ 655 private int getSubListIndex(ITaskInstanceList list, 656 List<ITaskInstance> subList, 657 int startIndex) 658 { 659 boolean matchFound; 660 int result = -1; 661 662 for (int i = startIndex; i <= list.size() - subList.size(); i++) { 663 matchFound = true; 664 665 for (int j = 0; j < subList.size(); j++) { 666 // we prepared the task instances to refer to unique tasks, if they are treated 667 // as equal. Therefore, we just compare the identity of the tasks of the task 668 // instances 669 if (list.get(i + j).getTask() != subList.get(j).getTask()) { 670 matchFound = false; 671 break; 672 } 673 } 674 675 if (matchFound) { 676 result = i; 677 break; 678 } 679 } 680 681 return result; 682 } 683 684 /** 685 * @param trie 686 * @param object 687 * @return 688 */ 689 private int getSubListIndex(List<ITaskInstance> list, 690 List<ITaskInstance> subList, 691 int startIndex) 692 { 693 boolean matchFound; 694 int result = -1; 695 696 for (int i = startIndex; i <= list.size() - subList.size(); i++) { 697 matchFound = true; 698 699 for (int j = 0; j < subList.size(); j++) { 700 // we prepared the task instances to refer to unique tasks, if they are treated 701 // as equal. Therefore, we just compare the identity of the tasks of the task 702 // instances 703 if (list.get(i + j) != subList.get(j)) { 704 matchFound = false; 705 break; 706 } 707 } 708 709 if (matchFound) { 710 result = i; 711 break; 712 } 713 } 714 715 return result; 716 } 717 718 /** 719 * @author Patrick Harms 720 */ 721 private class MaxCountAndLongestTasksFinder implements TrieProcessor<ITaskInstance> { 722 723 /** 724 * 725 */ 726 private int currentCount; 727 728 /** 729 * 730 */ 731 private List<List<ITaskInstance>> foundTasks = new LinkedList<List<ITaskInstance>>(); 732 733 /** 734 * 735 */ 736 public MaxCountAndLongestTasksFinder() { 737 super(); 738 this.currentCount = 0; 739 } 740 741 /* (non-Javadoc) 742 * @see de.ugoe.cs.autoquest.usageprofiles.TrieProcessor#process(java.util.List, int) 743 */ 744 @Override 745 public TrieProcessor.Result process(List<ITaskInstance> foundTask, int count) { 746 if (foundTask.size() < 2) { 747 // ignore single tasks 748 return TrieProcessor.Result.CONTINUE; 749 } 750 751 if (count < 2) { 752 // ignore singular occurrences 753 return TrieProcessor.Result.SKIP_NODE; 754 } 755 756 if (this.currentCount > count) { 757 // ignore this children of this task, as they may have only smaller counts than 758 // the already found tasks 759 return TrieProcessor.Result.SKIP_NODE; 760 } 761 762 if (this.currentCount < count) { 763 // the provided task occurs more often that all tasks found so far. 764 // clear all found tasks and use the new count as the one searched for 765 foundTasks.clear(); 766 this.currentCount = count; 767 } 768 769 if (this.currentCount == count) { 770 // the task is of interest. Sort it into the other found tasks so that 771 // the longest come first 772 boolean added = false; 773 for (int i = 0; i < foundTasks.size(); i++) { 774 if (foundTasks.get(i).size() < foundTask.size()) { 775 // defensive copy 776 foundTasks.add(i, new LinkedList<ITaskInstance>(foundTask)); // defensive copy 777 added = true; 778 break; 779 } 780 } 781 782 if (!added) { 783 foundTasks.add(new LinkedList<ITaskInstance>(foundTask)); // defensive copy 784 } 785 } 786 787 return TrieProcessor.Result.CONTINUE; 788 } 789 790 /** 791 * @return 792 */ 793 public Tasks getFoundTasks() { 794 removePermutationsOfShorterTasks(); 795 return new Tasks(currentCount, foundTasks); 796 } 797 798 /** 799 * 800 */ 801 private void removePermutationsOfShorterTasks() { 802 // now iterate the sorted list and for each task remove all other tasks that are shorter 803 // (i.e. come later in the sorted list) and that represent a subpart of the task 804 for (int i = 0; i < foundTasks.size(); i++) { 805 for (int j = i + 1; j < foundTasks.size();) { 806 if (foundTasks.get(j).size() < foundTasks.get(i).size()) { 807 // found a task that is a potential subtask. Check for this and remove the 808 // subtask if needed 809 List<ITaskInstance> longTask = foundTasks.get(i); 810 List<ITaskInstance> shortTask = foundTasks.get(j); 811 812 if (getSubListIndex(longTask, shortTask, 0) > -1) { 813 foundTasks.remove(j); 814 } 815 else { 816 j++; 817 } 818 } 819 else { 820 j++; 821 } 822 } 823 } 824 } 825 826 } 827 828 // /** 829 // * @author Patrick Harms 830 // */ 831 // private class TrieStatisticsDumper implements TrieProcessor<ITaskInstance> { 832 // 833 // /** 834 // * 835 // */ 836 // private Map<Integer, Integer> counters = new HashMap<Integer, Integer>(); 837 // 838 // /* (non-Javadoc) 839 // * @see de.ugoe.cs.autoquest.usageprofiles.TrieProcessor#process(java.util.List, int) 840 // */ 841 // @Override 842 // public TrieProcessor.Result process(List<ITaskInstance> subsequence, int count) { 843 // if (subsequence.size() == 1) { 844 // Integer value = counters.get(count); 845 // 846 // if (value == null) { 847 // value = 0; 848 // } 849 // 850 // counters.put(count, value + 1); 851 // 852 // return TrieProcessor.Result.CONTINUE; 853 // } 854 // else { 855 // // ignore singular occurrences 856 // return TrieProcessor.Result.SKIP_NODE; 857 // } 858 // } 859 // 860 // /** 861 // * @return 862 // */ 863 // public void dumpCounters() { 864 // int dumpedCounters = 0; 865 // 866 // int count = 1; 867 // while (dumpedCounters < counters.size()) { 868 // Integer value = counters.get(count++); 869 // if (value != null) { 870 // System.out.println(value + " symbols occurred " + count + " times"); 871 // dumpedCounters++; 872 // } 873 // } 874 // } 875 // 876 // } 877 878 /** 879 * 880 */ 881 private static class RuleApplicationData { 882 883 /** 884 * 885 */ 886 private List<IUserSession> sessions; 887 888 /** 889 * 890 */ 891 private TaskInstanceTrie lastTrie; 892 893 /** 894 * default and minimum trained sequence length is 3 895 */ 896 private int trainedSequenceLength = 3; 897 898 /** 899 * 900 */ 901 private Tasks lastFoundTasks = new Tasks(Integer.MAX_VALUE, null); 902 903 /** 904 * 905 */ 906 private boolean detectedAndReplacedTasks; 907 908 /** 909 * 910 */ 911 private RuleApplicationResult result = new RuleApplicationResult(); 912 913 /** 914 * 915 */ 916 private StopWatch stopWatch = new StopWatch(); 917 918 /** 919 * 920 */ 921 private RuleApplicationData(List<IUserSession> sessions) { 922 this.sessions = sessions; 923 } 924 925 /** 926 * @return the tree 927 */ 928 private List<IUserSession> getSessions() { 929 return sessions; 930 } 931 932 /** 933 * @param lastTrie the lastTrie to set 934 */ 935 private void setLastTrie(TaskInstanceTrie lastTrie) { 936 this.lastTrie = lastTrie; 937 } 938 939 /** 940 * @return the lastTrie 941 */ 942 private TaskInstanceTrie getLastTrie() { 943 return lastTrie; 944 } 945 946 /** 947 * @param trainedSequenceLength the trainedSequenceLength to set 948 */ 949 private void setTrainedSequenceLength(int trainedSequenceLength) { 950 this.trainedSequenceLength = trainedSequenceLength; 951 } 952 953 /** 954 * @return the trainedSequenceLength 955 */ 956 private int getTrainedSequenceLength() { 957 return trainedSequenceLength; 958 } 959 960 /** 961 * @param lastFoundSequences the lastFoundSequences to set 962 */ 963 private void setLastFoundTasks(Tasks lastFoundSequences) { 964 this.lastFoundTasks = lastFoundSequences; 965 } 966 967 /** 968 * @return the lastFoundSequences 969 */ 970 private Tasks getLastFoundTasks() { 971 return lastFoundTasks; 972 } 973 974 /** 975 * 976 */ 977 private void detectedAndReplacedTasks(boolean detectedAndReplacedTasks) { 978 this.detectedAndReplacedTasks = detectedAndReplacedTasks; 979 } 980 981 /** 982 * 983 */ 984 private boolean detectedAndReplacedTasks() { 985 return detectedAndReplacedTasks; 986 } 987 988 /** 989 * @return the result 990 */ 991 private RuleApplicationResult getResult() { 992 return result; 993 } 994 995 /** 996 * @return the stopWatch 997 */ 998 private StopWatch getStopWatch() { 999 return stopWatch; 1000 } 1001 1002 } 1003 1004 1005 /** 1006 * @author Patrick Harms 1007 */ 1008 private static class Tasks implements Iterable<List<ITaskInstance>> { 1009 1010 /** 1011 * 1012 */ 1013 private int occurrenceCount; 1014 1015 /** 1016 * 1017 */ 1018 private List<List<ITaskInstance>> sequences; 1019 1020 /** 1021 * @param occurrenceCount 1022 * @param sequences 1023 */ 1024 private Tasks(int occurrenceCount, List<List<ITaskInstance>> sequences) { 1025 super(); 1026 this.occurrenceCount = occurrenceCount; 1027 this.sequences = sequences; 1028 } 1029 1030 /** 1031 * @return 1032 */ 1033 private int getOccurrenceCount() { 1034 return occurrenceCount; 1035 } 1036 1037 /** 1038 * @return 1039 */ 1040 private int size() { 1041 return this.sequences.size(); 1042 } 1043 1044 /** 1045 * 1046 */ 1047 1048 /* (non-Javadoc) 1049 * @see java.lang.Iterable#iterator() 1050 */ 1051 @Override 1052 public Iterator<List<ITaskInstance>> iterator() { 1053 return this.sequences.iterator(); 1054 } 1055 1056 /* (non-Javadoc) 1057 * @see java.lang.Object#toString() 1058 */ 1059 @Override 1060 public String toString() { 1061 StringBuffer result = new StringBuffer(); 1062 result.append(this.occurrenceCount); 1063 result.append(" occurrences:\n"); 1064 1065 for (List<ITaskInstance> task : sequences) { 1066 result.append(task); 1067 result.append("\n"); 1068 } 1069 1070 return result.toString(); 1071 } 1072 1073 } 1074 1075 // methods for internal testing 1076 // private void checkMatchingOfSessions(List<List<Event>> flattenedSessions, 1077 // List<IUserSession> sessions, 1078 // String when) 1079 // { 1080 // List<List<Event>> currentFlattenedSessions = flattenSessions(sessions); 1081 // if (flattenedSessions.size() != currentFlattenedSessions.size()) { 1082 // System.out.println("################## number of sessions changed after " + when); 1083 // } 1084 // else { 1085 // for (int i = 0; i < flattenedSessions.size(); i++) { 1086 // List<Event> expected = flattenedSessions.get(i); 1087 // List<Event> current = currentFlattenedSessions.get(i); 1088 // 1089 // if (expected.size() != current.size()) { 1090 // System.out.println 1091 // ("################## length of session " + i + " changed after " + when); 1092 // } 1093 // else { 1094 // for (int j = 0; j < expected.size(); j++) { 1095 // if (!expected.get(j).equals(current.get(j))) { 1096 // System.out.println("################## event " + j + " of session " + 1097 // i + " changed after " + when); 1098 // } 1099 // } 1100 // } 1101 // } 1102 // } 1103 // } 1104 // 1105 // private List<List<Event>> flattenSessions(List<IUserSession> sessions) { 1106 // List<List<Event>> flattenedSessions = new ArrayList<List<Event>>(); 1107 // for (IUserSession session : sessions) { 1108 // List<Event> flattenedUserSession = new ArrayList<Event>(); 1109 // flatten(session, flattenedUserSession); 1110 // flattenedSessions.add(flattenedUserSession); 1111 // } 1112 // 1113 // return flattenedSessions; 1114 // } 1115 // 1116 // private void flatten(IUserSession iUserSession, List<Event> flattenedUserSession) { 1117 // for (ITaskInstance instance : iUserSession) { 1118 // flatten(instance, flattenedUserSession); 1119 // } 1120 // } 1121 // 1122 // private void flatten(ITaskInstance instance, List<Event> flattenedUserSession) { 1123 // if (instance instanceof ITaskInstanceList) { 1124 // for (ITaskInstance child : (ITaskInstanceList) instance) { 1125 // flatten(child, flattenedUserSession); 1126 // } 1127 // } 1128 // else if (instance instanceof ISelectionInstance) { 1129 // flatten(((ISelectionInstance) instance).getChild(), flattenedUserSession); 1130 // } 1131 // else if (instance instanceof IOptionalInstance) { 1132 // flatten(((IOptionalInstance) instance).getChild(), flattenedUserSession); 1133 // } 1134 // else if (instance instanceof IEventTaskInstance) { 1135 // flattenedUserSession.add(((IEventTaskInstance) instance).getEvent()); 1136 // } 1137 // } 66 67 /** 68 * @author Patrick Harms 69 */ 70 private class MaxCountAndLongestTasksFinder implements 71 TrieProcessor<ITaskInstance> { 72 73 /** 74 * 75 */ 76 private int currentCount; 77 78 /** 79 * 80 */ 81 private final List<List<ITaskInstance>> foundTasks = new LinkedList<List<ITaskInstance>>(); 82 83 /** 84 * 85 */ 86 public MaxCountAndLongestTasksFinder() { 87 super(); 88 this.currentCount = 0; 89 } 90 91 /** 92 * @return 93 */ 94 public Tasks getFoundTasks() { 95 removePermutationsOfShorterTasks(); 96 return new Tasks(currentCount, foundTasks); 97 } 98 99 /* 100 * (non-Javadoc) 101 * 102 * @see 103 * de.ugoe.cs.autoquest.usageprofiles.TrieProcessor#process(java.util 104 * .List, int) 105 */ 106 @Override 107 public TrieProcessor.Result process(List<ITaskInstance> foundTask, 108 int count) { 109 if (foundTask.size() < 2) { 110 // ignore single tasks 111 return TrieProcessor.Result.CONTINUE; 112 } 113 114 if (count < 2) { 115 // ignore singular occurrences 116 return TrieProcessor.Result.SKIP_NODE; 117 } 118 119 if (this.currentCount > count) { 120 // ignore this children of this task, as they may have only 121 // smaller counts than 122 // the already found tasks 123 return TrieProcessor.Result.SKIP_NODE; 124 } 125 126 if (this.currentCount < count) { 127 // the provided task occurs more often that all tasks found so 128 // far. 129 // clear all found tasks and use the new count as the one 130 // searched for 131 foundTasks.clear(); 132 this.currentCount = count; 133 } 134 135 if (this.currentCount == count) { 136 // the task is of interest. Sort it into the other found tasks 137 // so that 138 // the longest come first 139 boolean added = false; 140 for (int i = 0; i < foundTasks.size(); i++) { 141 if (foundTasks.get(i).size() < foundTask.size()) { 142 // defensive copy 143 foundTasks.add(i, new LinkedList<ITaskInstance>( 144 foundTask)); // defensive copy 145 added = true; 146 break; 147 } 148 } 149 150 if (!added) { 151 foundTasks.add(new LinkedList<ITaskInstance>(foundTask)); // defensive 152 // copy 153 } 154 } 155 156 return TrieProcessor.Result.CONTINUE; 157 } 158 159 /** 160 * 161 */ 162 private void removePermutationsOfShorterTasks() { 163 // now iterate the sorted list and for each task remove all other 164 // tasks that are shorter 165 // (i.e. come later in the sorted list) and that represent a subpart 166 // of the task 167 for (int i = 0; i < foundTasks.size(); i++) { 168 for (int j = i + 1; j < foundTasks.size();) { 169 if (foundTasks.get(j).size() < foundTasks.get(i).size()) { 170 // found a task that is a potential subtask. Check for 171 // this and remove the 172 // subtask if needed 173 final List<ITaskInstance> longTask = foundTasks.get(i); 174 final List<ITaskInstance> shortTask = foundTasks.get(j); 175 176 if (getSubListIndex(longTask, shortTask, 0) > -1) { 177 foundTasks.remove(j); 178 } else { 179 j++; 180 } 181 } else { 182 j++; 183 } 184 } 185 } 186 } 187 188 } 189 190 /** 191 * 192 */ 193 private static class RuleApplicationData { 194 195 /** 196 * 197 */ 198 private final List<IUserSession> sessions; 199 200 /** 201 * 202 */ 203 private TaskInstanceTrie lastTrie; 204 205 /** 206 * default and minimum trained sequence length is 3 207 */ 208 private int trainedSequenceLength = 3; 209 210 /** 211 * 212 */ 213 private Tasks lastFoundTasks = new Tasks(Integer.MAX_VALUE, null); 214 215 /** 216 * 217 */ 218 private boolean detectedAndReplacedTasks; 219 220 /** 221 * 222 */ 223 private final RuleApplicationResult result = new RuleApplicationResult(); 224 225 /** 226 * 227 */ 228 private final StopWatch stopWatch = new StopWatch(); 229 230 /** 231 * 232 */ 233 private RuleApplicationData(List<IUserSession> sessions) { 234 this.sessions = sessions; 235 } 236 237 /** 238 * 239 */ 240 private boolean detectedAndReplacedTasks() { 241 return detectedAndReplacedTasks; 242 } 243 244 /** 245 * 246 */ 247 private void detectedAndReplacedTasks(boolean detectedAndReplacedTasks) { 248 this.detectedAndReplacedTasks = detectedAndReplacedTasks; 249 } 250 251 /** 252 * @return the lastFoundSequences 253 */ 254 private Tasks getLastFoundTasks() { 255 return lastFoundTasks; 256 } 257 258 /** 259 * @return the lastTrie 260 */ 261 private TaskInstanceTrie getLastTrie() { 262 return lastTrie; 263 } 264 265 /** 266 * @return the result 267 */ 268 private RuleApplicationResult getResult() { 269 return result; 270 } 271 272 /** 273 * @return the tree 274 */ 275 private List<IUserSession> getSessions() { 276 return sessions; 277 } 278 279 /** 280 * @return the stopWatch 281 */ 282 private StopWatch getStopWatch() { 283 return stopWatch; 284 } 285 286 /** 287 * @return the trainedSequenceLength 288 */ 289 private int getTrainedSequenceLength() { 290 return trainedSequenceLength; 291 } 292 293 /** 294 * @param lastFoundSequences 295 * the lastFoundSequences to set 296 */ 297 private void setLastFoundTasks(Tasks lastFoundSequences) { 298 this.lastFoundTasks = lastFoundSequences; 299 } 300 301 /** 302 * @param lastTrie 303 * the lastTrie to set 304 */ 305 private void setLastTrie(TaskInstanceTrie lastTrie) { 306 this.lastTrie = lastTrie; 307 } 308 309 /** 310 * @param trainedSequenceLength 311 * the trainedSequenceLength to set 312 */ 313 private void setTrainedSequenceLength(int trainedSequenceLength) { 314 this.trainedSequenceLength = trainedSequenceLength; 315 } 316 317 } 318 319 /** 320 * @author Patrick Harms 321 */ 322 private static class Tasks implements Iterable<List<ITaskInstance>> { 323 324 /** 325 * 326 */ 327 private final int occurrenceCount; 328 329 /** 330 * 331 */ 332 private final List<List<ITaskInstance>> sequences; 333 334 /** 335 * @param occurrenceCount 336 * @param sequences 337 */ 338 private Tasks(int occurrenceCount, List<List<ITaskInstance>> sequences) { 339 super(); 340 this.occurrenceCount = occurrenceCount; 341 this.sequences = sequences; 342 } 343 344 /** 345 * @return 346 */ 347 private int getOccurrenceCount() { 348 return occurrenceCount; 349 } 350 351 /** 352 * 353 */ 354 355 /* 356 * (non-Javadoc) 357 * 358 * @see java.lang.Iterable#iterator() 359 */ 360 @Override 361 public Iterator<List<ITaskInstance>> iterator() { 362 return this.sequences.iterator(); 363 } 364 365 /** 366 * @return 367 */ 368 private int size() { 369 return this.sequences.size(); 370 } 371 372 /* 373 * (non-Javadoc) 374 * 375 * @see java.lang.Object#toString() 376 */ 377 @Override 378 public String toString() { 379 final StringBuffer result = new StringBuffer(); 380 result.append(this.occurrenceCount); 381 result.append(" occurrences:\n"); 382 383 for (final List<ITaskInstance> task : sequences) { 384 result.append(task); 385 result.append("\n"); 386 } 387 388 return result.toString(); 389 } 390 391 } 392 393 /** 394 * <p> 395 * the task factory to be used for creating substructures for the temporal 396 * relationships identified during rul application 397 * </p> 398 */ 399 private final ITaskFactory taskFactory;; 400 401 /** 402 * <p> 403 * the task builder to be used for creating substructures for the temporal 404 * relationships identified during rule application 405 * </p> 406 */ 407 private final ITaskBuilder taskBuilder; 408 409 /** 410 * <p> 411 * the task handling strategy to be used for comparing tasks for 412 * preparation, i.e., before the tasks are harmonized 413 * </p> 414 */ 415 private final TaskHandlingStrategy preparationTaskHandlingStrategy; 416 417 /** 418 * <p> 419 * the task handling strategy to be used for comparing tasks during 420 * iteration detection an trie generation, i.e., after the tasks are 421 * harmonized 422 * </p> 423 */ 424 private final TaskHandlingStrategy identityTaskHandlingStrategy; 425 426 /** 427 * <p> 428 * instantiates the rule and initializes it with a task equality to be 429 * considered when comparing tasks as well as a task factory and builder to 430 * be used for creating task structures. 431 * </p> 432 * 433 * @param minimalTaskEquality 434 * the task equality to be considered when comparing tasks 435 * @param taskFactory 436 * the task factory to be used for creating substructures 437 * @param taskBuilder 438 * the task builder to be used for creating substructures 439 */ 440 SequenceForTaskDetectionRule(TaskEquality minimalTaskEquality, 441 ITaskFactory taskFactory, ITaskBuilder taskBuilder) { 442 this.taskFactory = taskFactory; 443 this.taskBuilder = taskBuilder; 444 445 this.preparationTaskHandlingStrategy = new TaskHandlingStrategy( 446 minimalTaskEquality); 447 this.identityTaskHandlingStrategy = new TaskHandlingStrategy( 448 TaskEquality.IDENTICAL); 449 } 450 451 /* 452 * (non-Javadoc) 453 * 454 * @see 455 * de.ugoe.cs.autoquest.tasktrees.temporalrelation.ISessionScopeRule#apply 456 * (java.util.List) 457 */ 458 @Override 459 public RuleApplicationResult apply(List<IUserSession> sessions) { 460 final RuleApplicationData appData = new RuleApplicationData(sessions); 461 462 // this is the real rule application. Loop while something is replaced. 463 harmonizeEventTaskInstancesModel(appData); 464 do { 465 System.out.println(); 466 467 appData.getStopWatch().start("whole loop"); 468 detectAndReplaceIterations(appData); 469 470 appData.getStopWatch().start("task replacement"); 471 detectAndReplaceTasks(appData); 472 appData.getStopWatch().stop("task replacement"); 473 appData.getStopWatch().stop("whole loop"); 474 475 // ((TaskTreeNodeComparator) 476 // taskComparator).getStopWatch().dumpStatistics(System.out); 477 // ((TaskTreeNodeComparator) taskComparator).getStopWatch().reset(); 478 479 appData.getStopWatch().dumpStatistics(System.out); 480 appData.getStopWatch().reset(); 481 482 } while (appData.detectedAndReplacedTasks()); 483 484 Console.println("created " 485 + appData.getResult().getNewlyCreatedTasks().size() 486 + " new tasks and " 487 + appData.getResult().getNewlyCreatedTaskInstances().size() 488 + " appropriate instances\n"); 489 490 if ((appData.getResult().getNewlyCreatedTasks().size() > 0) 491 || (appData.getResult().getNewlyCreatedTaskInstances().size() > 0)) { 492 appData.getResult().setRuleApplicationStatus( 493 RuleApplicationStatus.FINISHED); 494 } 495 496 return appData.getResult(); 497 } 498 499 /** 500 * @param appData 501 * the rule application data combining all data used for applying 502 * this rule 503 */ 504 private void createNewTrie(RuleApplicationData appData) { 505 Console.traceln( 506 Level.FINER, 507 "training trie with a maximum sequence length of " 508 + appData.getTrainedSequenceLength()); 509 510 appData.getStopWatch().start("training trie"); 511 512 // we prepared the task instances to refer to unique tasks, if they are 513 // treated 514 // as equal. Therefore, we just compare the identity of the tasks of the 515 // task 516 // instances 517 appData.setLastTrie(new TaskInstanceTrie(identityTaskHandlingStrategy)); 518 519 appData.getLastTrie().trainSessions(appData.getSessions(), 520 appData.getTrainedSequenceLength()); 521 522 appData.getStopWatch().stop("training trie"); 523 } 524 525 /** 526 * <p> 527 * searches for direct iterations of single tasks in all sequences and 528 * replaces them with {@link IIteration}s, respectively appropriate 529 * instances. Also all single occurrences of a task that is iterated 530 * somewhen are replaced with iterations to have again an efficient way for 531 * task comparisons. 532 * </p> 533 * 534 * @param appData 535 * the rule application data combining all data used for applying 536 * this rule 537 */ 538 private void detectAndReplaceIterations(RuleApplicationData appData) { 539 Console.traceln(Level.FINE, "detecting iterations"); 540 appData.getStopWatch().start("detecting iterations"); 541 542 final List<IUserSession> sessions = appData.getSessions(); 543 544 final Set<ITask> iteratedTasks = searchIteratedTasks(sessions); 545 546 if (iteratedTasks.size() > 0) { 547 replaceIterationsOf(iteratedTasks, sessions, appData); 548 } 549 550 appData.getStopWatch().stop("detecting iterations"); 551 Console.traceln(Level.INFO, "replaced " + iteratedTasks.size() 552 + " iterated tasks"); 553 } 554 555 /** 556 * TODO go on commenting 557 * 558 * @param appData 559 * the rule application data combining all data used for applying 560 * this rule 561 */ 562 private void detectAndReplaceTasks(RuleApplicationData appData) { 563 Console.traceln(Level.FINE, "detecting and replacing tasks"); 564 appData.getStopWatch().start("detecting tasks"); 565 566 getSequencesOccuringMostOften(appData); 567 568 appData.getStopWatch().stop("detecting tasks"); 569 appData.getStopWatch().start("replacing tasks"); 570 571 replaceSequencesOccurringMostOften(appData); 572 573 appData.getStopWatch().stop("replacing tasks"); 574 Console.traceln(Level.INFO, "detected and replaced " 575 + appData.getLastFoundTasks().size() + " tasks occuring " 576 + appData.getLastFoundTasks().getOccurrenceCount() + " times"); 577 } 578 579 /** 580 * @param appData 581 * the rule application data combining all data used for applying 582 * this rule 583 */ 584 private void getSequencesOccuringMostOften(RuleApplicationData appData) { 585 Console.traceln(Level.FINE, "determining most prominent tasks"); 586 587 Tasks tasks; 588 boolean createNewTrie = (appData.getLastTrie() == null) 589 || appData.detectedAndReplacedTasks(); // tree has changed 590 591 do { 592 if (createNewTrie) { 593 createNewTrie(appData); 594 } 595 596 final MaxCountAndLongestTasksFinder finder = new MaxCountAndLongestTasksFinder(); 597 appData.getLastTrie().process(finder); 598 599 tasks = finder.getFoundTasks(); 600 601 createNewTrie = false; 602 603 for (final List<ITaskInstance> task : tasks) { 604 if (task.size() >= appData.getTrainedSequenceLength()) { 605 // Trie must be recreated with a longer sequence length to 606 // be sure that 607 // the found sequences occurring most often are found in 608 // their whole length 609 appData.setTrainedSequenceLength(appData 610 .getTrainedSequenceLength() + 1); 611 createNewTrie = true; 612 break; 613 } 614 } 615 } while (createNewTrie); 616 617 // create a normal trie for comparison 618 /* 619 * System.out.println("creating test trie for comparison"); 620 * 621 * appData.getStopWatch().start("testtrie"); Trie<ITaskInstance> trie = 622 * new Trie<ITaskInstance>(identityTaskComparator); 623 * 624 * for (IUserSession session : appData.getSessions()) { 625 * trie.train(session.getExecutedTasks(), 626 * appData.getTrainedSequenceLength()); } 627 * 628 * appData.getStopWatch().stop("testtrie"); 629 * 630 * MaxCountAndLongestTasksFinder finder = new 631 * MaxCountAndLongestTasksFinder(); trie.process(finder); 632 * 633 * boolean allTasksEqual = finder.getFoundTasks().size() == 634 * tasks.size(); 635 * 636 * allTasksEqual &= finder.getFoundTasks().occurrenceCount == 637 * tasks.occurrenceCount; 638 * 639 * for (List<ITaskInstance> task1 : finder.getFoundTasks()) { boolean 640 * foundTask = false; for (List<ITaskInstance> task2 : tasks) { boolean 641 * tasksEqual = false; if (task1.size() == task2.size()) { tasksEqual = 642 * true; for (int i = 0; i < task1.size(); i++) { if 643 * (!identityTaskComparator.equals(task1.get(i).getTask(), 644 * task2.get(i).getTask())) { tasksEqual = false; } } } 645 * 646 * if (tasksEqual) { foundTask = true; break; } } 647 * 648 * if (!foundTask) { System.out.println("different is " + task1); 649 * allTasksEqual = false; break; } } 650 * 651 * if (!allTasksEqual) { System.out.println(finder.getFoundTasks()); 652 * System.out.println(tasks); 653 * 654 * throw new 655 * IllegalArgumentException("both tries calculated different subsequences" 656 * ); } 657 * 658 * /*TrieStatisticsDumper dumper = new TrieStatisticsDumper(); 659 * appData.getLastTrie().process(dumper); dumper.dumpCounters(); 660 */ 661 662 appData.setLastFoundTasks(tasks); 663 664 Console.traceln(Level.FINE, "found " 665 + appData.getLastFoundTasks().size() + " tasks " + "occurring " 666 + appData.getLastFoundTasks().getOccurrenceCount() + " times"); 667 } 668 669 /** 670 * @param trie 671 * @param object 672 * @return 673 */ 674 private int getSubListIndex(ITaskInstanceList list, 675 List<ITaskInstance> subList, int startIndex) { 676 boolean matchFound; 677 int result = -1; 678 679 for (int i = startIndex; i <= (list.size() - subList.size()); i++) { 680 matchFound = true; 681 682 for (int j = 0; j < subList.size(); j++) { 683 // we prepared the task instances to refer to unique tasks, if 684 // they are treated 685 // as equal. Therefore, we just compare the identity of the 686 // tasks of the task 687 // instances 688 if (list.get(i + j).getTask() != subList.get(j).getTask()) { 689 matchFound = false; 690 break; 691 } 692 } 693 694 if (matchFound) { 695 result = i; 696 break; 697 } 698 } 699 700 return result; 701 } 702 703 /** 704 * @param trie 705 * @param object 706 * @return 707 */ 708 private int getSubListIndex(List<ITaskInstance> list, 709 List<ITaskInstance> subList, int startIndex) { 710 boolean matchFound; 711 int result = -1; 712 713 for (int i = startIndex; i <= (list.size() - subList.size()); i++) { 714 matchFound = true; 715 716 for (int j = 0; j < subList.size(); j++) { 717 // we prepared the task instances to refer to unique tasks, if 718 // they are treated 719 // as equal. Therefore, we just compare the identity of the 720 // tasks of the task 721 // instances 722 if (list.get(i + j) != subList.get(j)) { 723 matchFound = false; 724 break; 725 } 726 } 727 728 if (matchFound) { 729 result = i; 730 break; 731 } 732 } 733 734 return result; 735 } 736 737 /** 738 * <p> 739 * harmonizes the event task instances by unifying tasks. This is done, as 740 * initially the event tasks being equal with respect to the considered task 741 * equality are distinct objects. The comparison of these distinct objects 742 * is more time consuming than comparing the object references. 743 * </p> 744 * 745 * @param appData 746 * the rule application data combining all data used for applying 747 * this rule 748 */ 749 private void harmonizeEventTaskInstancesModel(RuleApplicationData appData) { 750 Console.traceln(Level.INFO, 751 "harmonizing task model of event task instances"); 752 appData.getStopWatch().start("harmonizing event tasks"); 753 754 final SymbolMap<ITaskInstance, ITask> uniqueTasks = preparationTaskHandlingStrategy 755 .createSymbolMap(); 756 final TaskInstanceComparator comparator = preparationTaskHandlingStrategy 757 .getTaskComparator(); 758 759 int unifiedTasks = 0; 760 ITask task; 761 final List<IUserSession> sessions = appData.getSessions(); 762 int sessionNo = 0; 763 for (final IUserSession session : sessions) { 764 Console.traceln(Level.FINE, "handling " + (++sessionNo) + ". " 765 + session); 766 for (final ITaskInstance taskInstance : session) { 767 task = uniqueTasks.getValue(taskInstance); 768 769 if (task == null) { 770 uniqueTasks.addSymbol(taskInstance, taskInstance.getTask()); 771 } else { 772 taskBuilder.setTask(taskInstance, task); 773 unifiedTasks++; 774 } 775 } 776 777 comparator.clearBuffers(); 778 } 779 780 appData.getStopWatch().stop("harmonizing event tasks"); 781 Console.traceln(Level.INFO, "harmonized " + unifiedTasks 782 + " task occurrences (still " + uniqueTasks.size() 783 + " different tasks)"); 784 785 appData.getStopWatch().dumpStatistics(System.out); 786 appData.getStopWatch().reset(); 787 } 788 789 /** 790 * <p> 791 * TODO clarify why this is done 792 * </p> 793 */ 794 private void harmonizeIterationInstancesModel(IIteration iteration, 795 List<IIterationInstance> iterationInstances) { 796 final List<ITask> iteratedTaskVariants = new LinkedList<ITask>(); 797 final TaskInstanceComparator comparator = preparationTaskHandlingStrategy 798 .getTaskComparator(); 799 800 // merge the lexically different variants of iterated task to a unique 801 // list 802 for (final IIterationInstance iterationInstance : iterationInstances) { 803 for (final ITaskInstance executionVariant : iterationInstance) { 804 final ITask candidate = executionVariant.getTask(); 805 806 boolean found = false; 807 for (final ITask taskVariant : iteratedTaskVariants) { 808 if (comparator.areLexicallyEqual(taskVariant, candidate)) { 809 taskBuilder.setTask(executionVariant, taskVariant); 810 found = true; 811 break; 812 } 813 } 814 815 if (!found) { 816 iteratedTaskVariants.add(candidate); 817 } 818 } 819 } 820 821 // if there are more than one lexically different variant of iterated 822 // tasks, adapt the 823 // iteration model to be a selection of different variants. In this case 824 // also adapt 825 // the generated iteration instances to correctly contain selection 826 // instances. If there 827 // is only one variant of an iterated task, simply set this as the 828 // marked task of the 829 // iteration. In this case, the instances can be preserved as is 830 if (iteratedTaskVariants.size() > 1) { 831 final ISelection selection = taskFactory.createNewSelection(); 832 833 for (final ITask variant : iteratedTaskVariants) { 834 taskBuilder.addChild(selection, variant); 835 } 836 837 taskBuilder.setMarkedTask(iteration, selection); 838 839 for (final IIterationInstance instance : iterationInstances) { 840 for (int i = 0; i < instance.size(); i++) { 841 final ISelectionInstance selectionInstance = taskFactory 842 .createNewTaskInstance(selection); 843 taskBuilder.setChild(selectionInstance, instance.get(i)); 844 taskBuilder.setTaskInstance(instance, i, selectionInstance); 845 } 846 } 847 } else { 848 taskBuilder.setMarkedTask(iteration, iteratedTaskVariants.get(0)); 849 } 850 } 851 852 /** 853 * 854 */ 855 private void harmonizeSequenceInstancesModel(ISequence sequence, 856 List<ISequenceInstance> sequenceInstances, int sequenceLength) { 857 final TaskInstanceComparator comparator = preparationTaskHandlingStrategy 858 .getTaskComparator(); 859 860 // ensure for each subtask that lexically different variants are 861 // preserved 862 for (int subTaskIndex = 0; subTaskIndex < sequenceLength; subTaskIndex++) { 863 final List<ITask> subTaskVariants = new LinkedList<ITask>(); 864 865 for (final ISequenceInstance sequenceInstance : sequenceInstances) { 866 final ITask candidate = sequenceInstance.get(subTaskIndex) 867 .getTask(); 868 869 boolean found = false; 870 871 for (int i = 0; i < subTaskVariants.size(); i++) { 872 if (comparator.areLexicallyEqual(subTaskVariants.get(i), 873 candidate)) { 874 taskBuilder.setTask(sequenceInstance.get(subTaskIndex), 875 subTaskVariants.get(i)); 876 877 found = true; 878 break; 879 } 880 } 881 882 if (!found) { 883 subTaskVariants.add(candidate); 884 } 885 } 886 887 // if there are more than one lexically different variant of the sub 888 // task at 889 // the considered position, adapt the sequence model at that 890 // position to have 891 // a selection of the different variants. In this case also adapt 892 // the 893 // generated sequence instances to correctly contain selection 894 // instances. If 895 // there is only one variant of sub tasks at the given position, 896 // simply set 897 // this variant as the sub task of the selection. In this case, the 898 // instances 899 // can be preserved as is 900 if (subTaskVariants.size() > 1) { 901 final ISelection selection = taskFactory.createNewSelection(); 902 903 for (final ITask variant : subTaskVariants) { 904 taskBuilder.addChild(selection, variant); 905 } 906 907 taskBuilder.addChild(sequence, selection); 908 909 for (final ISequenceInstance instance : sequenceInstances) { 910 final ISelectionInstance selectionInstance = taskFactory 911 .createNewTaskInstance(selection); 912 taskBuilder.setChild(selectionInstance, 913 instance.get(subTaskIndex)); 914 taskBuilder.setTaskInstance(instance, subTaskIndex, 915 selectionInstance); 916 } 917 } else if (subTaskVariants.size() == 1) { 918 taskBuilder.addChild(sequence, subTaskVariants.get(0)); 919 } 920 } 921 } 922 923 /** 924 * <p> 925 * replaces all occurrences of all tasks provided in the set with iterations 926 * </p> 927 * 928 * @param iteratedTasks 929 * the tasks to be replaced with iterations 930 * @param sessions 931 * the sessions in which the tasks are to be replaced 932 * @param appData 933 * the rule application data combining all data used for applying 934 * this rule 935 */ 936 private void replaceIterationsOf(Set<ITask> iteratedTasks, 937 List<IUserSession> sessions, RuleApplicationData appData) { 938 final Map<ITask, IIteration> iterations = new HashMap<ITask, IIteration>(); 939 final Map<IIteration, List<IIterationInstance>> iterationInstances = new HashMap<IIteration, List<IIterationInstance>>(); 940 941 for (final ITask iteratedTask : iteratedTasks) { 942 final IIteration iteration = taskFactory.createNewIteration(); 943 iterations.put(iteratedTask, iteration); 944 iterationInstances.put(iteration, 945 new LinkedList<IIterationInstance>()); 946 } 947 948 IIterationInstance iterationInstance; 949 950 for (final IUserSession session : sessions) { 951 int index = 0; 952 iterationInstance = null; 953 954 while (index < session.size()) { 955 // we prepared the task instances to refer to unique tasks, if 956 // they are treated 957 // as equal. Therefore, we just compare the identity of the 958 // tasks of the task 959 // instances 960 final ITask currentTask = session.get(index).getTask(); 961 final IIteration iteration = iterations.get(currentTask); 962 if (iteration != null) { 963 if ((iterationInstance == null) 964 || (iterationInstance.getTask() != iteration)) { 965 iterationInstance = taskFactory 966 .createNewTaskInstance(iteration); 967 iterationInstances.get(iteration) 968 .add(iterationInstance); 969 taskBuilder.addTaskInstance(session, index, 970 iterationInstance); 971 index++; 972 } 973 974 taskBuilder.addChild(iterationInstance, session.get(index)); 975 taskBuilder.removeTaskInstance(session, index); 976 } else { 977 if (iterationInstance != null) { 978 iterationInstance = null; 979 } 980 index++; 981 } 982 } 983 } 984 985 for (final Map.Entry<IIteration, List<IIterationInstance>> entry : iterationInstances 986 .entrySet()) { 987 harmonizeIterationInstancesModel(entry.getKey(), entry.getValue()); 988 } 989 } 990 991 /** 992 * @param appData 993 * the rule application data combining all data used for applying 994 * this rule 995 */ 996 private void replaceSequencesOccurringMostOften(RuleApplicationData appData) { 997 appData.detectedAndReplacedTasks(false); 998 999 if ((appData.getLastFoundTasks().size() > 0) 1000 && (appData.getLastFoundTasks().getOccurrenceCount() > 1)) { 1001 Console.traceln(Level.FINER, "replacing tasks occurrences"); 1002 1003 for (final List<ITaskInstance> task : appData.getLastFoundTasks()) { 1004 final ISequence sequence = taskFactory.createNewSequence(); 1005 1006 Console.traceln(Level.FINEST, "replacing " + sequence.getId() 1007 + ": " + task); 1008 1009 final List<ISequenceInstance> sequenceInstances = replaceTaskOccurrences( 1010 task, appData.getSessions(), sequence); 1011 1012 harmonizeSequenceInstancesModel(sequence, sequenceInstances, 1013 task.size()); 1014 appData.detectedAndReplacedTasks(appData 1015 .detectedAndReplacedTasks() 1016 || (sequenceInstances.size() > 0)); 1017 1018 if (sequenceInstances.size() < appData.getLastFoundTasks() 1019 .getOccurrenceCount()) { 1020 Console.traceln(Level.FINE, 1021 sequence.getId() 1022 + ": replaced task only " 1023 + sequenceInstances.size() 1024 + " times instead of expected " 1025 + appData.getLastFoundTasks() 1026 .getOccurrenceCount()); 1027 } 1028 } 1029 } 1030 1031 } 1032 1033 /** 1034 * @param tree 1035 */ 1036 private List<ISequenceInstance> replaceTaskOccurrences( 1037 List<ITaskInstance> task, List<IUserSession> sessions, 1038 ISequence temporalTaskModel) { 1039 final List<ISequenceInstance> sequenceInstances = new LinkedList<ISequenceInstance>(); 1040 1041 for (final IUserSession session : sessions) { 1042 int index = -1; 1043 1044 do { 1045 index = getSubListIndex(session, task, ++index); 1046 1047 if (index > -1) { 1048 sequenceInstances 1049 .add(RuleUtils.createNewSubSequenceInRange(session, 1050 index, (index + task.size()) - 1, 1051 temporalTaskModel, taskFactory, taskBuilder)); 1052 } 1053 } while (index > -1); 1054 } 1055 1056 return sequenceInstances; 1057 } 1058 1059 // /** 1060 // * @author Patrick Harms 1061 // */ 1062 // private class TrieStatisticsDumper implements 1063 // TrieProcessor<ITaskInstance> { 1064 // 1065 // /** 1066 // * 1067 // */ 1068 // private Map<Integer, Integer> counters = new HashMap<Integer, Integer>(); 1069 // 1070 // /* (non-Javadoc) 1071 // * @see 1072 // de.ugoe.cs.autoquest.usageprofiles.TrieProcessor#process(java.util.List, 1073 // int) 1074 // */ 1075 // @Override 1076 // public TrieProcessor.Result process(List<ITaskInstance> subsequence, int 1077 // count) { 1078 // if (subsequence.size() == 1) { 1079 // Integer value = counters.get(count); 1080 // 1081 // if (value == null) { 1082 // value = 0; 1083 // } 1084 // 1085 // counters.put(count, value + 1); 1086 // 1087 // return TrieProcessor.Result.CONTINUE; 1088 // } 1089 // else { 1090 // // ignore singular occurrences 1091 // return TrieProcessor.Result.SKIP_NODE; 1092 // } 1093 // } 1094 // 1095 // /** 1096 // * @return 1097 // */ 1098 // public void dumpCounters() { 1099 // int dumpedCounters = 0; 1100 // 1101 // int count = 1; 1102 // while (dumpedCounters < counters.size()) { 1103 // Integer value = counters.get(count++); 1104 // if (value != null) { 1105 // System.out.println(value + " symbols occurred " + count + " times"); 1106 // dumpedCounters++; 1107 // } 1108 // } 1109 // } 1110 // 1111 // } 1112 1113 /** 1114 * <p> 1115 * searches the provided sessions for task iterations. If a task is 1116 * iterated, it is added to the returned set. 1117 * </p> 1118 * 1119 * @param the 1120 * session to search for iterations in 1121 * 1122 * @return a set of tasks being iterated somewhere 1123 */ 1124 private Set<ITask> searchIteratedTasks(List<IUserSession> sessions) { 1125 final Set<ITask> iteratedTasks = new HashSet<ITask>(); 1126 for (final IUserSession session : sessions) { 1127 for (int i = 0; i < (session.size() - 1); i++) { 1128 // we prepared the task instances to refer to unique tasks, if 1129 // they are treated 1130 // as equal. Therefore, we just compare the identity of the 1131 // tasks of the task 1132 // instances 1133 if (session.get(i).getTask() == session.get(i + 1).getTask()) { 1134 iteratedTasks.add(session.get(i).getTask()); 1135 } 1136 } 1137 } 1138 1139 return iteratedTasks; 1140 } 1141 1142 /* 1143 * (non-Javadoc) 1144 * 1145 * @see java.lang.Object#toString() 1146 */ 1147 @Override 1148 public String toString() { 1149 return "SequenceForTaskDetectionRule"; 1150 } 1151 1152 // methods for internal testing 1153 // private void checkMatchingOfSessions(List<List<Event>> flattenedSessions, 1154 // List<IUserSession> sessions, 1155 // String when) 1156 // { 1157 // List<List<Event>> currentFlattenedSessions = flattenSessions(sessions); 1158 // if (flattenedSessions.size() != currentFlattenedSessions.size()) { 1159 // System.out.println("################## number of sessions changed after " 1160 // + when); 1161 // } 1162 // else { 1163 // for (int i = 0; i < flattenedSessions.size(); i++) { 1164 // List<Event> expected = flattenedSessions.get(i); 1165 // List<Event> current = currentFlattenedSessions.get(i); 1166 // 1167 // if (expected.size() != current.size()) { 1168 // System.out.println 1169 // ("################## length of session " + i + " changed after " + when); 1170 // } 1171 // else { 1172 // for (int j = 0; j < expected.size(); j++) { 1173 // if (!expected.get(j).equals(current.get(j))) { 1174 // System.out.println("################## event " + j + " of session " + 1175 // i + " changed after " + when); 1176 // } 1177 // } 1178 // } 1179 // } 1180 // } 1181 // } 1182 // 1183 // private List<List<Event>> flattenSessions(List<IUserSession> sessions) { 1184 // List<List<Event>> flattenedSessions = new ArrayList<List<Event>>(); 1185 // for (IUserSession session : sessions) { 1186 // List<Event> flattenedUserSession = new ArrayList<Event>(); 1187 // flatten(session, flattenedUserSession); 1188 // flattenedSessions.add(flattenedUserSession); 1189 // } 1190 // 1191 // return flattenedSessions; 1192 // } 1193 // 1194 // private void flatten(IUserSession iUserSession, List<Event> 1195 // flattenedUserSession) { 1196 // for (ITaskInstance instance : iUserSession) { 1197 // flatten(instance, flattenedUserSession); 1198 // } 1199 // } 1200 // 1201 // private void flatten(ITaskInstance instance, List<Event> 1202 // flattenedUserSession) { 1203 // if (instance instanceof ITaskInstanceList) { 1204 // for (ITaskInstance child : (ITaskInstanceList) instance) { 1205 // flatten(child, flattenedUserSession); 1206 // } 1207 // } 1208 // else if (instance instanceof ISelectionInstance) { 1209 // flatten(((ISelectionInstance) instance).getChild(), 1210 // flattenedUserSession); 1211 // } 1212 // else if (instance instanceof IOptionalInstance) { 1213 // flatten(((IOptionalInstance) instance).getChild(), flattenedUserSession); 1214 // } 1215 // else if (instance instanceof IEventTaskInstance) { 1216 // flattenedUserSession.add(((IEventTaskInstance) instance).getEvent()); 1217 // } 1218 // } 1138 1219 1139 1220 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/SequenceForTaskDetectionRuleAlignment.java
r1732 r1733 15 15 package de.ugoe.cs.autoquest.tasktrees.temporalrelation; 16 16 17 import java.io.File;18 17 import java.io.FileInputStream; 19 18 import java.io.FileOutputStream; … … 80 79 public class SequenceForTaskDetectionRuleAlignment implements ISessionScopeRule { 81 80 81 private class ParallelMatchOcurrencesFinder implements Runnable { 82 private final RuleApplicationData appData; 83 private final int from; 84 private final int to; 85 86 ParallelMatchOcurrencesFinder(RuleApplicationData appData, int from, 87 int to) { 88 this.appData = appData; 89 this.from = from; 90 this.to = to; 91 } 92 93 @Override 94 public void run() { 95 int count = 0; 96 final int size = to - from; 97 98 for (int i = from; i < to; i++) { 99 final Match pattern = appData.getMatchseqs().get(i); 100 count++; 101 RuleUtils.printProgressPercentage("Match finding progress", 102 count, size); 103 // Skip sequences with more 0 events (scrolls) than other 104 // events. 105 // Both of the pattern sequences are equally long, so the zero 106 // counts just need to be smaller than the length of one 107 // sequence 108 if ((pattern.getFirstSequence().eventCount(0) 109 + pattern.getSecondSequence().eventCount(0) + 1) > pattern 110 .getFirstSequence().size()) { 111 continue; 112 } 113 114 for (int j = 0; j < appData.getNumberSequences().size(); j++) { 115 final LinkedList<Integer> startpositions = appData 116 .getNumberSequences().get(j) 117 .containsPattern(pattern); 118 if (startpositions.size() > 0) { 119 for (final Iterator<Integer> jt = startpositions 120 .iterator(); jt.hasNext();) { 121 final int start = jt.next(); 122 pattern.addOccurence(new MatchOccurence(start, 123 start + pattern.size(), j)); 124 } 125 } 126 } 127 } 128 } 129 } 130 131 private class ParallelMatchReplacer implements Runnable { 132 133 private final RuleApplicationData appData; 134 private final int from; 135 private final int to; 136 137 ParallelMatchReplacer(RuleApplicationData appData, int from, int to) { 138 this.appData = appData; 139 this.from = from; 140 this.to = to; 141 } 142 143 @Override 144 public void run() { 145 // TODO Cleanup 146 // int count = 0; 147 // int size = to - from; 148 for (int i = from; i < to; i++) { 149 // count++; 150 // Every pattern consists of 2 sequences, therefore the minimum 151 // occurrences here is 2. 152 // We just need the sequences also occurring in other sequences 153 // as well 154 if (appData.getMatchseqs().get(i).occurenceCount() > 2) { 155 156 final ISequence task = matchAsSequence(appData, appData 157 .getMatchseqs().get(i)); 158 invalidOccurence: for (final Iterator<MatchOccurence> it = appData 159 .getMatchseqs().get(i).getOccurences().iterator(); it 160 .hasNext();) { 161 final MatchOccurence oc = it.next(); 162 163 // Check if nothing has been replaced in the sequence we 164 // want to replace now 165 166 synchronized (appData.getReplacedOccurences()) { 167 if (appData.getReplacedOccurences().get( 168 oc.getSequenceId()) == null) { 169 appData.getReplacedOccurences().put( 170 oc.getSequenceId(), 171 new LinkedList<MatchOccurence>()); 172 } else { 173 // check if we have any replaced occurence with 174 // indexes 175 // smaller than ours. If so, we need to adjust 176 // our start 177 // and endpoints 178 // of the replacement. 179 // Also do a check if we have replaced this 180 // specific 181 // MatchOccurence in this sequence already. Jump 182 // to the 183 // next occurence if this is the case. 184 // This is no more neccessary once the matches 185 // are 186 // harmonized. 187 for (final Iterator<MatchOccurence> jt = appData 188 .getReplacedOccurences() 189 .get(oc.getSequenceId()).iterator(); jt 190 .hasNext();) { 191 final MatchOccurence tmpOC = jt.next(); 192 193 if ((oc.getStartindex() >= tmpOC 194 .getStartindex()) 195 && (oc.getStartindex() <= tmpOC 196 .getEndindex())) { 197 continue invalidOccurence; 198 } 199 if (oc.getEndindex() >= tmpOC 200 .getStartindex()) { 201 continue invalidOccurence; 202 203 } else if (oc.getStartindex() > tmpOC 204 .getEndindex()) { 205 final int diff = tmpOC.getEndindex() 206 - tmpOC.getStartindex(); 207 // Just to be sure. 208 if (diff > 0) { 209 oc.setStartindex((oc 210 .getStartindex() - diff) + 1); 211 oc.setEndindex((oc.getEndindex() - diff) + 1); 212 } else { 213 Console.traceln(Level.WARNING, 214 "End index of a Match before start. This should never happen"); 215 } 216 } 217 } 218 } 219 System.out.println("Replacing in sequence" 220 + oc.getSequenceId()); 221 synchronized (appData) { 222 appData.detectedAndReplacedTasks = true; 223 } 224 synchronized (appData.getSessions().get( 225 oc.getSequenceId())) { 226 final ISequenceInstance sequenceInstances = RuleUtils 227 .createNewSubSequenceInRange( 228 appData.getSessions().get( 229 oc.getSequenceId()), 230 oc.getStartindex(), 231 oc.getEndindex(), task, 232 taskFactory, taskBuilder); 233 oc.setEndindex((oc.getStartindex() + sequenceInstances 234 .size()) - RuleUtils.missedOptionals); 235 } 236 } 237 // Adjust the length of the match regarding to the 238 // length of 239 // instance. (OptionalInstances may be shorter) 240 241 synchronized (appData.getReplacedOccurences().get( 242 oc.getSequenceId())) { 243 appData.getReplacedOccurences() 244 .get(oc.getSequenceId()).add(oc); 245 } 246 } 247 } 248 } 249 } 250 } 251 252 private class ParallelPairwiseAligner implements Runnable { 253 private final RuleApplicationData appData; 254 private final int from; 255 private final int to; 256 257 ParallelPairwiseAligner(RuleApplicationData appData, int from, int to) { 258 this.appData = appData; 259 this.from = from; 260 this.to = to; 261 } 262 263 @Override 264 public void run() { 265 int count = 0; 266 final int size = to - from; 267 268 for (int i = from; i < to; i++) { 269 final NumberSequence ns1 = appData.getNumberSequences().get(i); 270 count++; 271 RuleUtils.printProgressPercentage("Aligning Progress", count, 272 size); 273 for (int j = 0; j < appData.getNumberSequences().size(); j++) { 274 final NumberSequence ns2 = appData.getNumberSequences() 275 .get(j); 276 if (i != j) { 277 final AlignmentAlgorithm aa = AlignmentAlgorithmFactory 278 .create(); 279 aa.align(ns1, ns2, appData.getSubmat(), 9); 280 synchronized (appData.getMatchseqs()) { 281 appData.getMatchseqs().addAll(aa.getMatches()); 282 } 283 } 284 } 285 } 286 } 287 } 288 289 /** 290 * 291 */ 292 private static class RuleApplicationData implements Serializable { 293 294 /** 295 * 296 */ 297 private static final long serialVersionUID = -7559657686755522960L; 298 299 private final HashMap<Integer, ITask> number2task; 300 301 // TODO: We Actually just need number2task here, this structure can be 302 // removed in the future. 303 private final HashSet<ITask> uniqueTasks; 304 305 private final ObjectDistanceSubstitionMatrix submat; 306 307 public HashMap<Integer, List<MatchOccurence>> replacedOccurences; 308 309 public LinkedList<Match> matchseqs; 310 311 private ArrayList<NumberSequence> numberseqs; 312 313 private final LinkedList<ITask> newTasks; 314 315 /** 316 * 317 */ 318 private final List<IUserSession> sessions; 319 320 /** 321 * 322 */ 323 private boolean detectedAndReplacedTasks; 324 325 /** 326 * 327 */ 328 private final RuleApplicationResult result; 329 330 /** 331 * 332 */ 333 private final StopWatch stopWatch; 334 335 /** 336 * 337 */ 338 private RuleApplicationData(List<IUserSession> sessions) { 339 this.sessions = sessions; 340 numberseqs = new ArrayList<NumberSequence>(); 341 uniqueTasks = new HashSet<ITask>(); 342 number2task = new HashMap<Integer, ITask>(); 343 stopWatch = new StopWatch(); 344 result = new RuleApplicationResult(); 345 submat = new ObjectDistanceSubstitionMatrix(6, -3, false); 346 newTasks = new LinkedList<ITask>(); 347 this.detectedAndReplacedTasks = true; 348 } 349 350 /** 351 * 352 */ 353 private boolean detectedAndReplacedTasks() { 354 return detectedAndReplacedTasks; 355 } 356 357 public LinkedList<Match> getMatchseqs() { 358 return matchseqs; 359 } 360 361 public LinkedList<ITask> getNewTasks() { 362 return newTasks; 363 } 364 365 private HashMap<Integer, ITask> getNumber2Task() { 366 return number2task; 367 } 368 369 private ArrayList<NumberSequence> getNumberSequences() { 370 return numberseqs; 371 } 372 373 public HashMap<Integer, List<MatchOccurence>> getReplacedOccurences() { 374 return replacedOccurences; 375 } 376 377 /** 378 * @return the result 379 */ 380 private RuleApplicationResult getResult() { 381 return result; 382 } 383 384 /** 385 * @return the UserSessions as List. 386 */ 387 private List<IUserSession> getSessions() { 388 return sessions; 389 } 390 391 /** 392 * @return the stopWatch 393 */ 394 private StopWatch getStopWatch() { 395 return stopWatch; 396 } 397 398 private ObjectDistanceSubstitionMatrix getSubmat() { 399 return submat; 400 } 401 402 private HashSet<ITask> getUniqueTasks() { 403 return uniqueTasks; 404 } 405 406 private void newTaskCreated(ITask task) { 407 number2task.put(task.getId(), task); 408 newTasks.add(task); 409 } 410 411 synchronized private void resetNewlyCreatedTasks() { 412 uniqueTasks.addAll(newTasks); 413 newTasks.clear(); 414 } 415 416 private void setNumberSequences(ArrayList<NumberSequence> numberseqs) { 417 this.numberseqs = numberseqs; 418 } 419 420 public void setReplacedOccurences( 421 HashMap<Integer, List<MatchOccurence>> replacedOccurences) { 422 this.replacedOccurences = replacedOccurences; 423 } 424 425 private void updateSubstitutionMatrix() { 426 submat.update(getNewTasks()); 427 resetNewlyCreatedTasks(); 428 } 429 430 } 431 82 432 public static int nThreads = Runtime.getRuntime().availableProcessors() - 1; 83 433 84 434 private int iteration = 0; 435 85 436 /** 86 437 * <p> … … 89 440 * </p> 90 441 */ 91 private ITaskFactory taskFactory; 442 private final ITaskFactory taskFactory; 443 92 444 /** 93 445 * <p> … … 96 448 * </p> 97 449 */ 98 private ITaskBuilder taskBuilder;450 private final ITaskBuilder taskBuilder; 99 451 100 452 /** … … 104 456 * </p> 105 457 */ 106 private TaskHandlingStrategy preparationTaskHandlingStrategy;458 private final TaskHandlingStrategy preparationTaskHandlingStrategy; 107 459 108 460 /** … … 133 485 * (non-Javadoc) 134 486 * 135 * @see java.lang.Object#toString()136 */137 @Override138 public String toString() {139 return "SequenceForTaskDetectionRuleAlignment";140 }141 142 public void saveAppData(String name) {143 String objectName = name;144 String filename = name + ".dat";145 Object dataObject = GlobalDataContainer.getInstance().getData(146 objectName);147 if (dataObject == null) {148 CommandHelpers.objectNotFoundMessage(objectName);149 }150 FileOutputStream fos = null;151 ObjectOutputStream out = null;152 try {153 fos = new FileOutputStream(filename);154 out = new ObjectOutputStream(fos);155 out.writeObject(dataObject);156 out.close();157 } catch (IOException ex) {158 Console.logException(ex);159 }160 }161 162 public RuleApplicationData loadAppData(String name) {163 String objectName = name;164 String filename = name + ".dat";165 166 Object data = null;167 FileInputStream fis = null;168 ObjectInputStream in = null;169 try {170 fis = new FileInputStream(filename);171 in = new ObjectInputStream(fis);172 data = in.readObject();173 in.close();174 } catch (IOException ex) {175 Console.logException(ex);176 } catch (ClassNotFoundException ex) {177 Console.logException(ex);178 }179 if (GlobalDataContainer.getInstance().addData(objectName, data)) {180 CommandHelpers.dataOverwritten(objectName);181 }182 return (RuleApplicationData) GlobalDataContainer.getInstance().getData(183 name);184 }185 186 /*187 * (non-Javadoc)188 *189 487 * @see 190 488 * de.ugoe.cs.autoquest.tasktrees.temporalrelation.ISessionScopeRule#apply … … 193 491 @Override 194 492 public RuleApplicationResult apply(List<IUserSession> sessions) { 195 RuleApplicationData appData = new RuleApplicationData(sessions);493 final RuleApplicationData appData = new RuleApplicationData(sessions); 196 494 // File harmonized = new File("harmonized.dat"); 197 495 // if(harmonized.exists() && !harmonized.isDirectory()) { … … 232 530 detectAndReplaceIterations(appData); 233 531 appData.getStopWatch().start("task replacement"); 234 // appData.updateSubstitutionMatrix();532 // appData.updateSubstitutionMatrix(); 235 533 detectAndReplaceTasks(appData); // 236 534 appData.getStopWatch().stop("task replacement"); … … 258 556 private ArrayList<NumberSequence> createNumberSequences( 259 557 RuleApplicationData appData) { 260 ArrayList<NumberSequence> result = new ArrayList<NumberSequence>();558 final ArrayList<NumberSequence> result = new ArrayList<NumberSequence>(); 261 559 for (int i = 0; i < appData.getSessions().size(); i++) { 262 IUserSession session = appData.getSessions().get(i);263 NumberSequence templist = new NumberSequence(session.size());560 final IUserSession session = appData.getSessions().get(i); 561 final NumberSequence templist = new NumberSequence(session.size()); 264 562 for (int j = 0; j < session.size(); j++) { 265 ITaskInstance taskInstance = session.get(j);563 final ITaskInstance taskInstance = session.get(j); 266 564 templist.getSequence()[j] = taskInstance.getTask().getId(); 267 565 } … … 272 570 } 273 571 return result; 572 } 573 574 /** 575 * <p> 576 * searches for direct iterations of single tasks in all sequences and 577 * replaces them with {@link IIteration}s, respectively appropriate 578 * instances. Also all single occurrences of a task that is iterated 579 * somewhen are replaced with iterations to have again an efficient way for 580 * task comparisons. 581 * </p> 582 * 583 * @param appData 584 * the rule application data combining all data used for applying 585 * this rule 586 */ 587 private void detectAndReplaceIterations(RuleApplicationData appData) { 588 Console.traceln(Level.FINE, "detecting iterations"); 589 appData.getStopWatch().start("detecting iterations"); 590 591 final List<IUserSession> sessions = appData.getSessions(); 592 593 final Set<ITask> iteratedTasks = searchIteratedTasks(sessions); 594 595 if (iteratedTasks.size() > 0) { 596 replaceIterationsOf(iteratedTasks, sessions, appData); 597 } 598 599 appData.getStopWatch().stop("detecting iterations"); 600 Console.traceln(Level.INFO, "replaced " + iteratedTasks.size() 601 + " iterated tasks"); 602 } 603 604 /** 605 * 606 * @param appData 607 * the rule application data combining all data used for applying 608 * this rule 609 */ 610 private void detectAndReplaceTasks(RuleApplicationData appData) { 611 Console.traceln(Level.FINE, "detecting and replacing tasks"); 612 appData.getStopWatch().start("detecting tasks"); 613 614 // Create NumberSequences 615 appData.setNumberSequences(this.createNumberSequences(appData)); 616 617 // Generate pairwise alignments 618 // appData.setMatchseqs(generatePairwiseAlignments(appData)); 619 generatePairwiseAlignments(appData); 620 621 // Searching each match in all other sessions, counting its occurences 622 searchMatchesInAllSessions(appData); 623 624 // Sort results to get the most occurring results 625 Console.traceln(Level.INFO, "sorting " + appData.getMatchseqs().size() 626 + " results"); 627 final Comparator<Match> comparator = new Comparator<Match>() { 628 @Override 629 public int compare(Match m1, Match m2) { 630 return m2.occurenceCount() - m1.occurenceCount(); 631 632 } 633 }; 634 635 Collections.sort(appData.getMatchseqs(), comparator); 636 appData.getStopWatch().stop("detecting tasks"); 637 638 // Replace matches in the sessions 639 Console.traceln(Level.INFO, "Replacing matches in sessions"); 640 replaceMatches(appData); 641 appData.getStopWatch().start("replacing tasks"); 642 643 // appData.setMatchseqs(null); 644 appData.getStopWatch().stop("replacing tasks"); 645 } 646 647 // private LinkedList<Match> generatePairwiseAlignments(RuleApplicationData 648 // appData) { 649 private void generatePairwiseAlignments(RuleApplicationData appData) { 650 final int numberSeqSize = appData.getNumberSequences().size(); 651 appData.matchseqs = new LinkedList<Match>(); 652 Console.traceln(Level.INFO, "generating pairwise alignments from " 653 + numberSeqSize + " sessions with " + nThreads + " threads"); 654 655 int newThreads = nThreads; 656 if (numberSeqSize < nThreads) { 657 newThreads = numberSeqSize; 658 } 659 660 final ExecutorService executor = Executors 661 .newFixedThreadPool(newThreads); 662 final int interval = numberSeqSize / newThreads; 663 int rest = numberSeqSize % newThreads; 664 665 for (int i = 0; i < (numberSeqSize - interval); i += interval) { 666 int offset = 0; 667 if (rest != 0) { 668 offset = 1; 669 rest--; 670 } 671 final int from = i; 672 final int to = i + interval + offset; 673 System.out.println("Creating thread for sessions " + from 674 + " till " + to); 675 final ParallelPairwiseAligner aligner = new ParallelPairwiseAligner( 676 appData, from, to); 677 executor.execute(aligner); 678 } 679 executor.shutdown(); 680 try { 681 executor.awaitTermination(2, TimeUnit.HOURS); 682 } catch (final InterruptedException e) { 683 // TODO Auto-generated catch block 684 e.printStackTrace(); 685 } 274 686 } 275 687 … … 291 703 "harmonizing task model of event task instances"); 292 704 appData.getStopWatch().start("harmonizing event tasks"); 293 SymbolMap<ITaskInstance, ITask> uniqueTasks = preparationTaskHandlingStrategy705 final SymbolMap<ITaskInstance, ITask> uniqueTasks = preparationTaskHandlingStrategy 294 706 .createSymbolMap(); 295 707 296 TaskInstanceComparator comparator = preparationTaskHandlingStrategy708 final TaskInstanceComparator comparator = preparationTaskHandlingStrategy 297 709 .getTaskComparator(); 298 710 299 711 int unifiedTasks = 0; 300 712 ITask task; 301 List<IUserSession> sessions = appData.getSessions();713 final List<IUserSession> sessions = appData.getSessions(); 302 714 for (int j = 0; j < sessions.size(); j++) { 303 IUserSession session = sessions.get(j);715 final IUserSession session = sessions.get(j); 304 716 305 717 for (int i = 0; i < session.size(); i++) { 306 ITaskInstance taskInstance = session.get(i);718 final ITaskInstance taskInstance = session.get(i); 307 719 task = uniqueTasks.getValue(taskInstance); 308 720 … … 332 744 /** 333 745 * <p> 334 * searches for direct iterations of single tasks in all sequences and 335 * replaces them with {@link IIteration}s, respectively appropriate 336 * instances. Also all single occurrences of a task that is iterated 337 * somewhen are replaced with iterations to have again an efficient way for 338 * task comparisons. 746 * TODO clarify why this is done 339 747 * </p> 340 * 748 */ 749 private void harmonizeIterationInstancesModel(IIteration iteration, 750 List<IIterationInstance> iterationInstances) { 751 final List<ITask> iteratedTaskVariants = new LinkedList<ITask>(); 752 final TaskInstanceComparator comparator = preparationTaskHandlingStrategy 753 .getTaskComparator(); 754 755 // merge the lexically different variants of iterated task to a unique 756 // list 757 for (final IIterationInstance iterationInstance : iterationInstances) { 758 for (final ITaskInstance executionVariant : iterationInstance) { 759 final ITask candidate = executionVariant.getTask(); 760 761 boolean found = false; 762 for (final ITask taskVariant : iteratedTaskVariants) { 763 if (comparator.areLexicallyEqual(taskVariant, candidate)) { 764 taskBuilder.setTask(executionVariant, taskVariant); 765 found = true; 766 break; 767 } 768 } 769 770 if (!found) { 771 iteratedTaskVariants.add(candidate); 772 } 773 } 774 } 775 776 // if there are more than one lexically different variant of iterated 777 // tasks, adapt the 778 // iteration model to be a selection of different variants. In this case 779 // also adapt 780 // the generated iteration instances to correctly contain selection 781 // instances. If there 782 // is only one variant of an iterated task, simply set this as the 783 // marked task of the 784 // iteration. In this case, the instances can be preserved as is 785 if (iteratedTaskVariants.size() > 1) { 786 final ISelection selection = taskFactory.createNewSelection(); 787 788 for (final ITask variant : iteratedTaskVariants) { 789 taskBuilder.addChild(selection, variant); 790 } 791 792 taskBuilder.setMarkedTask(iteration, selection); 793 794 for (final IIterationInstance instance : iterationInstances) { 795 for (int i = 0; i < instance.size(); i++) { 796 final ISelectionInstance selectionInstance = taskFactory 797 .createNewTaskInstance(selection); 798 taskBuilder.setChild(selectionInstance, instance.get(i)); 799 taskBuilder.setTaskInstance(instance, i, selectionInstance); 800 } 801 } 802 } else { 803 taskBuilder.setMarkedTask(iteration, iteratedTaskVariants.get(0)); 804 } 805 } 806 807 public RuleApplicationData loadAppData(String name) { 808 final String objectName = name; 809 final String filename = name + ".dat"; 810 811 Object data = null; 812 FileInputStream fis = null; 813 ObjectInputStream in = null; 814 try { 815 fis = new FileInputStream(filename); 816 in = new ObjectInputStream(fis); 817 data = in.readObject(); 818 in.close(); 819 } catch (final IOException ex) { 820 Console.logException(ex); 821 } catch (final ClassNotFoundException ex) { 822 Console.logException(ex); 823 } 824 if (GlobalDataContainer.getInstance().addData(objectName, data)) { 825 CommandHelpers.dataOverwritten(objectName); 826 } 827 return (RuleApplicationData) GlobalDataContainer.getInstance().getData( 828 name); 829 } 830 831 /** 341 832 * @param appData 342 * the rule application data combining all data used for applying 343 * this rule 344 */ 345 private void detectAndReplaceIterations(RuleApplicationData appData) { 346 Console.traceln(Level.FINE, "detecting iterations"); 347 appData.getStopWatch().start("detecting iterations"); 348 349 List<IUserSession> sessions = appData.getSessions(); 350 351 Set<ITask> iteratedTasks = searchIteratedTasks(sessions); 352 353 if (iteratedTasks.size() > 0) { 354 replaceIterationsOf(iteratedTasks, sessions, appData); 355 } 356 357 appData.getStopWatch().stop("detecting iterations"); 358 Console.traceln(Level.INFO, "replaced " + iteratedTasks.size() 359 + " iterated tasks"); 360 } 361 362 /** 363 * <p> 364 * searches the provided sessions for task iterations. If a task is 365 * iterated, it is added to the returned set. 366 * </p> 367 * 368 * @param the 369 * session to search for iterations in 370 * 371 * @return a set of tasks being iterated somewhere 372 */ 373 private Set<ITask> searchIteratedTasks(List<IUserSession> sessions) { 374 Set<ITask> iteratedTasks = new HashSet<ITask>(); 375 for (IUserSession session : sessions) { 376 for (int i = 0; i < (session.size() - 1); i++) { 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 if (session.get(i).getTask() == session.get(i + 1).getTask()) { 383 iteratedTasks.add(session.get(i).getTask()); 833 * , Ruleapplication Data needed to keep track of all created 834 * tasks 835 * @param m 836 * The match to be converted into a Task 837 * @return The task of the match with an ISequence as it's root 838 */ 839 synchronized public ISequence matchAsSequence(RuleApplicationData appData, 840 Match m) { 841 final ISequence sequence = taskFactory.createNewSequence(); 842 appData.newTaskCreated(sequence); 843 844 final int[] first = m.getFirstSequence().getSequence(); 845 final int[] second = m.getSecondSequence().getSequence(); 846 847 // Both sequences of a match are equally long 848 for (int i = 0; i < m.getFirstSequence().size(); i++) { 849 850 // Two gaps aligned to each other: Have not seen it happening so 851 // far, just to handle it 852 if ((first[i] == -1) && (second[i] == -1)) { 853 // Do nothing here. 854 } 855 // Both events are equal, we can simply add the task referring to 856 // the number 857 else if (first[i] == second[i]) { 858 taskBuilder.addChild(sequence, 859 appData.getNumber2Task().get(first[i])); 860 } 861 // We have a gap in the first sequence, we need to add the task of 862 // the second sequence as optional 863 else if ((first[i] == -1) && (second[i] != -1)) { 864 final IOptional optional = taskFactory.createNewOptional(); 865 appData.newTaskCreated(optional); 866 taskBuilder.setMarkedTask(optional, appData.getNumber2Task() 867 .get(second[i])); 868 taskBuilder.addChild(sequence, optional); 869 } 870 // We have a gap in the second sequence, we need to add the task of 871 // the first sequence as optional 872 else if ((first[i] != -1) && (second[i] == -1)) { 873 final IOptional optional = taskFactory.createNewOptional(); 874 appData.newTaskCreated(optional); 875 taskBuilder.setMarkedTask(optional, appData.getNumber2Task() 876 .get(first[i])); 877 taskBuilder.addChild(sequence, optional); 878 } 879 // Both tasks are not equal, we need to insert a selection here. 880 // Check if the next position is not a selection 881 else if (i < (first.length - 1)) { 882 883 if ((first[i] != second[i]) 884 && (((first[i + 1] == second[i + 1]) 885 || (first[i + 1] == -1) || (second[i + 1] == -1)))) { 886 887 final ISelection selection = taskFactory 888 .createNewSelection(); 889 appData.newTaskCreated(selection); 890 taskBuilder.addChild(selection, appData.getNumber2Task() 891 .get(first[i])); 892 taskBuilder.addChild(selection, appData.getNumber2Task() 893 .get(second[i])); 894 taskBuilder.addChild(sequence, selection); 895 } else { 896 boolean selectionfound = true; 897 final ISelection selection = taskFactory 898 .createNewSelection(); 899 appData.newTaskCreated(selection); 900 901 final ISequence subsequence1 = taskFactory 902 .createNewSequence(); 903 appData.newTaskCreated(subsequence1); 904 905 final ISequence subsequence2 = taskFactory 906 .createNewSequence(); 907 appData.newTaskCreated(subsequence2); 908 909 taskBuilder.addChild(selection, subsequence1); 910 taskBuilder.addChild(selection, subsequence2); 911 taskBuilder.addChild(sequence, selection); 912 while ((i < (first.length - 1)) && selectionfound) { 913 selectionfound = false; 914 taskBuilder.addChild(subsequence1, appData 915 .getNumber2Task().get(first[i])); 916 taskBuilder.addChild(subsequence2, appData 917 .getNumber2Task().get(second[i])); 918 if ((first[i + 1] != second[i + 1]) 919 && (first[i + 1] != -1) 920 && (second[i + 1] != -1)) { 921 selectionfound = true; 922 } else { 923 continue; 924 } 925 i++; 926 } 927 if ((i == (first.length - 1)) && selectionfound) { 928 taskBuilder.addChild(subsequence1, appData 929 .getNumber2Task().get(first[i])); 930 taskBuilder.addChild(subsequence2, appData 931 .getNumber2Task().get(second[i])); 932 } 384 933 } 385 } 386 } 387 return iteratedTasks; 934 } else { 935 if ((first[i] != second[i])) { 936 937 final ISelection selection = taskFactory 938 .createNewSelection(); 939 appData.newTaskCreated(selection); 940 taskBuilder.addChild(selection, appData.getNumber2Task() 941 .get(first[i])); 942 taskBuilder.addChild(selection, appData.getNumber2Task() 943 .get(second[i])); 944 taskBuilder.addChild(sequence, selection); 945 } 946 } 947 948 } 949 return sequence; 388 950 } 389 951 … … 403 965 private void replaceIterationsOf(Set<ITask> iteratedTasks, 404 966 List<IUserSession> sessions, RuleApplicationData appData) { 405 Map<ITask, IIteration> iterations = new HashMap<ITask, IIteration>();406 Map<IIteration, List<IIterationInstance>> iterationInstances = new HashMap<IIteration, List<IIterationInstance>>();407 408 for ( ITask iteratedTask : iteratedTasks) {409 410 IIteration iteration = taskFactory.createNewIteration();967 final Map<ITask, IIteration> iterations = new HashMap<ITask, IIteration>(); 968 final Map<IIteration, List<IIterationInstance>> iterationInstances = new HashMap<IIteration, List<IIterationInstance>>(); 969 970 for (final ITask iteratedTask : iteratedTasks) { 971 972 final IIteration iteration = taskFactory.createNewIteration(); 411 973 appData.newTaskCreated(iteration); 412 974 iterations.put(iteratedTask, iteration); … … 417 979 IIterationInstance iterationInstance; 418 980 419 for ( IUserSession session : sessions) {981 for (final IUserSession session : sessions) { 420 982 int index = 0; 421 983 iterationInstance = null; … … 427 989 // tasks of the task 428 990 // instances 429 ITask currentTask = session.get(index).getTask();430 IIteration iteration = iterations.get(currentTask);991 final ITask currentTask = session.get(index).getTask(); 992 final IIteration iteration = iterations.get(currentTask); 431 993 if (iteration != null) { 432 994 if ((iterationInstance == null) … … 436 998 iterationInstances.get(iteration) 437 999 .add(iterationInstance);// TODO:: Don't create 438 439 440 1000 // TaskInstances here, 1001 // use a set of tasks 1002 // instead 441 1003 taskBuilder.addTaskInstance(session, index, 442 1004 iterationInstance); … … 455 1017 } 456 1018 457 for ( Map.Entry<IIteration, List<IIterationInstance>> entry : iterationInstances1019 for (final Map.Entry<IIteration, List<IIterationInstance>> entry : iterationInstances 458 1020 .entrySet()) { 459 1021 harmonizeIterationInstancesModel(entry.getKey(), entry.getValue()); … … 461 1023 } 462 1024 463 /**464 * <p>465 * TODO clarify why this is done466 * </p>467 */468 private void harmonizeIterationInstancesModel(IIteration iteration,469 List<IIterationInstance> iterationInstances) {470 List<ITask> iteratedTaskVariants = new LinkedList<ITask>();471 TaskInstanceComparator comparator = preparationTaskHandlingStrategy472 .getTaskComparator();473 474 // merge the lexically different variants of iterated task to a unique475 // list476 for (IIterationInstance iterationInstance : iterationInstances) {477 for (ITaskInstance executionVariant : iterationInstance) {478 ITask candidate = executionVariant.getTask();479 480 boolean found = false;481 for (ITask taskVariant : iteratedTaskVariants) {482 if (comparator.areLexicallyEqual(taskVariant, candidate)) {483 taskBuilder.setTask(executionVariant, taskVariant);484 found = true;485 break;486 }487 }488 489 if (!found) {490 iteratedTaskVariants.add(candidate);491 }492 }493 }494 495 // if there are more than one lexically different variant of iterated496 // tasks, adapt the497 // iteration model to be a selection of different variants. In this case498 // also adapt499 // the generated iteration instances to correctly contain selection500 // instances. If there501 // is only one variant of an iterated task, simply set this as the502 // marked task of the503 // iteration. In this case, the instances can be preserved as is504 if (iteratedTaskVariants.size() > 1) {505 ISelection selection = taskFactory.createNewSelection();506 507 for (ITask variant : iteratedTaskVariants) {508 taskBuilder.addChild(selection, variant);509 }510 511 taskBuilder.setMarkedTask(iteration, selection);512 513 for (IIterationInstance instance : iterationInstances) {514 for (int i = 0; i < instance.size(); i++) {515 ISelectionInstance selectionInstance = taskFactory516 .createNewTaskInstance(selection);517 taskBuilder.setChild(selectionInstance, instance.get(i));518 taskBuilder.setTaskInstance(instance, i, selectionInstance);519 }520 }521 } else {522 taskBuilder.setMarkedTask(iteration, iteratedTaskVariants.get(0));523 }524 }525 526 /**527 * @param appData528 * @param m529 * @return530 */531 synchronized public ISequence matchAsSequence(RuleApplicationData appData, Match m) {532 ISequence sequence = taskFactory.createNewSequence();533 appData.newTaskCreated(sequence);534 535 int[] first = m.getFirstSequence().getSequence();536 int[] second = m.getSecondSequence().getSequence();537 538 // Both sequences of a match are equally long539 for (int i = 0; i < m.getFirstSequence().size(); i++) {540 541 // Two gaps aligned to each other: Have not seen it happening so542 // far, just to handle it543 if (first[i] == -1 && second[i] == -1) {544 // Do nothing here.545 }546 // Both events are equal, we can simply add the task referring to547 // the number548 else if (first[i] == second[i]) {549 taskBuilder.addChild(sequence,550 appData.getNumber2Task().get(first[i]));551 }552 // We have a gap in the first sequence, we need to add the task of553 // the second sequence as optional554 else if (first[i] == -1 && second[i] != -1) {555 IOptional optional = taskFactory.createNewOptional();556 appData.newTaskCreated(optional);557 taskBuilder.setMarkedTask(optional, appData.getNumber2Task()558 .get(second[i]));559 taskBuilder.addChild(sequence, optional);560 }561 // We have a gap in the second sequence, we need to add the task of562 // the first sequence as optional563 else if (first[i] != -1 && second[i] == -1) {564 IOptional optional = taskFactory.createNewOptional();565 appData.newTaskCreated(optional);566 taskBuilder.setMarkedTask(optional, appData.getNumber2Task()567 .get(first[i]));568 taskBuilder.addChild(sequence, optional);569 }570 // Both tasks are not equal, we need to insert a selection here.571 // Check if the next position is not a selection572 else if (i < first.length - 1) {573 574 if ((first[i] != second[i])575 && ((first[i + 1] == second[i + 1]576 || first[i + 1] == -1 || second[i + 1] == -1))) {577 578 ISelection selection = taskFactory.createNewSelection();579 appData.newTaskCreated(selection);580 taskBuilder.addChild(selection, appData.getNumber2Task()581 .get(first[i]));582 taskBuilder.addChild(selection, appData.getNumber2Task()583 .get(second[i]));584 taskBuilder.addChild(sequence, selection);585 } else {586 boolean selectionfound = true;587 ISelection selection = taskFactory.createNewSelection();588 appData.newTaskCreated(selection);589 590 ISequence subsequence1 = taskFactory.createNewSequence();591 appData.newTaskCreated(subsequence1);592 593 ISequence subsequence2 = taskFactory.createNewSequence();594 appData.newTaskCreated(subsequence2);595 596 taskBuilder.addChild(selection, subsequence1);597 taskBuilder.addChild(selection, subsequence2);598 taskBuilder.addChild(sequence, selection);599 while (i < first.length - 1 && selectionfound) {600 selectionfound = false;601 taskBuilder.addChild(subsequence1, appData602 .getNumber2Task().get(first[i]));603 taskBuilder.addChild(subsequence2, appData604 .getNumber2Task().get(second[i]));605 if (first[i + 1] != second[i + 1] && first[i + 1] != -1606 && second[i + 1] != -1) {607 selectionfound = true;608 } else {609 continue;610 }611 i++;612 }613 if (i == first.length - 1 && selectionfound) {614 taskBuilder.addChild(subsequence1, appData615 .getNumber2Task().get(first[i]));616 taskBuilder.addChild(subsequence2, appData617 .getNumber2Task().get(second[i]));618 }619 }620 } else {621 if ((first[i] != second[i])) {622 623 ISelection selection = taskFactory.createNewSelection();624 appData.newTaskCreated(selection);625 taskBuilder.addChild(selection, appData.getNumber2Task()626 .get(first[i]));627 taskBuilder.addChild(selection, appData.getNumber2Task()628 .get(second[i]));629 taskBuilder.addChild(sequence, selection);630 }631 }632 633 }634 return sequence;635 }636 637 /**638 *639 * @param appData640 * the rule application data combining all data used for applying641 * this rule642 */643 private void detectAndReplaceTasks(RuleApplicationData appData) {644 Console.traceln(Level.FINE, "detecting and replacing tasks");645 appData.getStopWatch().start("detecting tasks");646 647 // Create NumberSequences648 appData.setNumberSequences(this.createNumberSequences(appData));649 650 // Generate pairwise alignments651 // appData.setMatchseqs(generatePairwiseAlignments(appData));652 generatePairwiseAlignments(appData);653 654 // Searching each match in all other sessions, counting its occurences655 searchMatchesInAllSessions(appData);656 657 // Sort results to get the most occurring results658 Console.traceln(Level.INFO, "sorting " + appData.getMatchseqs().size()659 + " results");660 Comparator<Match> comparator = new Comparator<Match>() {661 public int compare(Match m1, Match m2) {662 return m2.occurenceCount() - m1.occurenceCount();663 664 }665 };666 667 Collections.sort(appData.getMatchseqs(), comparator);668 appData.getStopWatch().stop("detecting tasks");669 670 // Replace matches in the sessions671 Console.traceln(Level.INFO, "Replacing matches in sessions");672 replaceMatches(appData);673 appData.getStopWatch().start("replacing tasks");674 675 // appData.setMatchseqs(null);676 appData.getStopWatch().stop("replacing tasks");677 }678 679 1025 private void replaceMatches(RuleApplicationData appData) { 680 1026 appData.replacedOccurences = new HashMap<Integer, List<MatchOccurence>>(); 681 682 int matchSeqSize = appData.getMatchseqs().size();1027 1028 final int matchSeqSize = appData.getMatchseqs().size(); 683 1029 int newThreads = nThreads; 684 1030 if (matchSeqSize < nThreads) { 685 newThreads = matchSeqSize; 686 } 687 ExecutorService executor = Executors.newFixedThreadPool(newThreads); 688 int interval = matchSeqSize / newThreads; 1031 newThreads = matchSeqSize; 1032 } 1033 final ExecutorService executor = Executors 1034 .newFixedThreadPool(newThreads); 1035 final int interval = matchSeqSize / newThreads; 689 1036 int rest = matchSeqSize % newThreads; 690 691 for (int i = 0; i < matchSeqSize - interval; i += interval) {1037 1038 for (int i = 0; i < (matchSeqSize - interval); i += interval) { 692 1039 int offset = 0; 693 1040 if (rest != 0) { … … 695 1042 rest--; 696 1043 } 697 int from = i; 698 int to = i + interval + offset; 699 System.out.println("Replacement: Creating thread with matches from " + from 700 + " to " + to); 1044 final int from = i; 1045 final int to = i + interval + offset; 1046 System.out 1047 .println("Replacement: Creating thread with matches from " 1048 + from + " to " + to); 701 1049 // search each match in every other sequence 702 ParallelMatchReplacer replacer = new ParallelMatchReplacer(1050 final ParallelMatchReplacer replacer = new ParallelMatchReplacer( 703 1051 appData, from, to); 704 1052 executor.execute(replacer); … … 707 1055 try { 708 1056 executor.awaitTermination(2, TimeUnit.HOURS); 709 } catch ( InterruptedException e) {1057 } catch (final InterruptedException e) { 710 1058 // TODO Auto-generated catch block 711 1059 e.printStackTrace(); 712 1060 } 1061 } 1062 1063 public void saveAppData(String name) { 1064 final String objectName = name; 1065 final String filename = name + ".dat"; 1066 final Object dataObject = GlobalDataContainer.getInstance().getData( 1067 objectName); 1068 if (dataObject == null) { 1069 CommandHelpers.objectNotFoundMessage(objectName); 1070 } 1071 FileOutputStream fos = null; 1072 ObjectOutputStream out = null; 1073 try { 1074 fos = new FileOutputStream(filename); 1075 out = new ObjectOutputStream(fos); 1076 out.writeObject(dataObject); 1077 out.close(); 1078 } catch (final IOException ex) { 1079 Console.logException(ex); 1080 } 1081 } 1082 1083 /** 1084 * <p> 1085 * searches the provided sessions for task iterations. If a task is 1086 * iterated, it is added to the returned set. 1087 * </p> 1088 * 1089 * @param the 1090 * session to search for iterations in 1091 * 1092 * @return a set of tasks being iterated somewhere 1093 */ 1094 private Set<ITask> searchIteratedTasks(List<IUserSession> sessions) { 1095 final Set<ITask> iteratedTasks = new HashSet<ITask>(); 1096 for (final IUserSession session : sessions) { 1097 for (int i = 0; i < (session.size() - 1); i++) { 1098 // we prepared the task instances to refer to unique tasks, if 1099 // they are treated 1100 // as equal. Therefore, we just compare the identity of the 1101 // tasks of the task 1102 // instances 1103 if (session.get(i).getTask() == session.get(i + 1).getTask()) { 1104 iteratedTasks.add(session.get(i).getTask()); 1105 } 1106 } 1107 } 1108 return iteratedTasks; 713 1109 } 714 1110 … … 718 1114 + " threads"); 719 1115 // Prepare parallel search of matchseqs 720 721 int matchSeqSize = appData.getMatchseqs().size();1116 1117 final int matchSeqSize = appData.getMatchseqs().size(); 722 1118 int newThreads = nThreads; 723 1119 if (matchSeqSize < nThreads) { 724 newThreads = matchSeqSize; 725 } 726 int interval = matchSeqSize / newThreads;1120 newThreads = matchSeqSize; 1121 } 1122 final int interval = matchSeqSize / newThreads; 727 1123 int rest = matchSeqSize % newThreads; 728 ExecutorService executor = Executors.newFixedThreadPool(nThreads);729 730 for (int i = 0; i < matchSeqSize - interval; i += interval) {1124 final ExecutorService executor = Executors.newFixedThreadPool(nThreads); 1125 1126 for (int i = 0; i < (matchSeqSize - interval); i += interval) { 731 1127 int offset = 0; 732 1128 if (rest != 0) { … … 734 1130 rest--; 735 1131 } 736 int from = i; 737 int to = i + interval + offset; 738 System.out.println("Match finding: Creating thread with matches from " + from 739 + " to " + to); 1132 final int from = i; 1133 final int to = i + interval + offset; 1134 System.out 1135 .println("Match finding: Creating thread with matches from " 1136 + from + " to " + to); 740 1137 // search each match in every other sequence 741 ParallelMatchOcurrencesFinder finder = new ParallelMatchOcurrencesFinder(1138 final ParallelMatchOcurrencesFinder finder = new ParallelMatchOcurrencesFinder( 742 1139 appData, from, to); 743 1140 executor.execute(finder); … … 746 1143 try { 747 1144 executor.awaitTermination(2, TimeUnit.HOURS); 748 } catch ( InterruptedException e) {1145 } catch (final InterruptedException e) { 749 1146 // TODO Auto-generated catch block 750 1147 e.printStackTrace(); … … 753 1150 } 754 1151 755 756 private class ParallelMatchReplacer implements Runnable { 757 758 private final RuleApplicationData appData; 759 private final int from; 760 private final int to; 761 762 ParallelMatchReplacer(RuleApplicationData appData, int from, 763 int to) { 764 this.appData = appData; 765 this.from = from; 766 this.to = to; 767 } 768 @Override 769 public void run() { 770 int count = 0; 771 int size = to - from; 772 for (int i = from; i < to; i++) { 773 count++; 774 // Every pattern consists of 2 sequences, therefore the minimum 775 // occurrences here is 2. 776 // We just need the sequences also occurring in other sequences as well 777 if (appData.getMatchseqs().get(i).occurenceCount() > 2) { 778 779 ISequence task = matchAsSequence(appData, appData.getMatchseqs().get(i)); 780 invalidOccurence: for (Iterator<MatchOccurence> it = appData 781 .getMatchseqs().get(i).getOccurences().iterator(); it 782 .hasNext();) { 783 MatchOccurence oc = it.next(); 784 785 // Check if nothing has been replaced in the sequence we 786 // want to replace now 787 788 synchronized (appData.getReplacedOccurences()) { 789 if (appData.getReplacedOccurences().get(oc.getSequenceId()) == null) { 790 appData.getReplacedOccurences().put(oc.getSequenceId(), 791 new LinkedList<MatchOccurence>()); 792 } else { 793 // check if we have any replaced occurence with indexes 794 // smaller than ours. If so, we need to adjust our start 795 // and endpoints 796 // of the replacement. 797 // Also do a check if we have replaced this specific 798 // MatchOccurence in this sequence already. Jump to the 799 // next occurence if this is the case. 800 // This is no more neccessary once the matches are 801 // harmonized. 802 for (Iterator<MatchOccurence> jt = appData.getReplacedOccurences() 803 .get(oc.getSequenceId()).iterator(); jt 804 .hasNext();) { 805 MatchOccurence tmpOC = jt.next(); 806 807 if (oc.getStartindex() >= tmpOC.getStartindex() 808 && oc.getStartindex() <= tmpOC 809 .getEndindex()) { 810 continue invalidOccurence; 811 } 812 if (oc.getEndindex() >= tmpOC.getStartindex()) { 813 continue invalidOccurence; 814 815 } else if (oc.getStartindex() > tmpOC.getEndindex()) { 816 int diff = tmpOC.getEndindex() 817 - tmpOC.getStartindex(); 818 // Just to be sure. 819 if (diff > 0) { 820 oc.setStartindex(oc.getStartindex() - diff 821 + 1); 822 oc.setEndindex(oc.getEndindex() - diff + 1); 823 } else { 824 Console.traceln(Level.WARNING, 825 "End index of a Match before start. This should never happen"); 826 } 827 } 828 } 829 } 830 System.out.println("Replacing in sequence" 831 + oc.getSequenceId()); 832 synchronized(appData) { 833 appData.detectedAndReplacedTasks = true; 834 } 835 synchronized (appData.getSessions().get(oc.getSequenceId())) { 836 ISequenceInstance sequenceInstances = RuleUtils 837 .createNewSubSequenceInRange(appData.getSessions() 838 .get(oc.getSequenceId()), oc 839 .getStartindex(), oc.getEndindex(), task, 840 taskFactory, taskBuilder); 841 oc.setEndindex(oc.getStartindex() 842 + sequenceInstances.size() 843 - RuleUtils.missedOptionals); 844 } 845 } 846 // Adjust the length of the match regarding to the length of 847 // instance. (OptionalInstances may be shorter) 848 849 synchronized(appData.getReplacedOccurences().get(oc.getSequenceId())) { 850 appData.getReplacedOccurences().get(oc.getSequenceId()).add(oc); 851 } 852 } 853 } 854 } 855 } 856 } 857 858 859 860 private class ParallelMatchOcurrencesFinder implements Runnable { 861 private final RuleApplicationData appData; 862 private final int from; 863 private final int to; 864 865 ParallelMatchOcurrencesFinder(RuleApplicationData appData, int from, 866 int to) { 867 this.appData = appData; 868 this.from = from; 869 this.to = to; 870 } 871 872 @Override 873 public void run() { 874 int count = 0; 875 int size = to - from; 876 877 for (int i = from; i < to; i++) { 878 Match pattern = appData.getMatchseqs().get(i); 879 count++; 880 RuleUtils.printProgressPercentage("Match finding progress",count, size); 881 // Skip sequences with more 0 events (scrolls) than other 882 // events. 883 // Both of the pattern sequences are equally long, so the zero 884 // counts just need to be smaller than the length of one 885 // sequence 886 if (pattern.getFirstSequence().eventCount(0) 887 + pattern.getSecondSequence().eventCount(0) + 1 > pattern 888 .getFirstSequence().size()) 889 continue; 890 891 for (int j = 0; j < appData.getNumberSequences().size(); j++) { 892 LinkedList<Integer> startpositions = appData 893 .getNumberSequences().get(j) 894 .containsPattern(pattern); 895 if (startpositions.size() > 0) { 896 for (Iterator<Integer> jt = startpositions.iterator(); jt 897 .hasNext();) { 898 int start = jt.next(); 899 pattern.addOccurence(new MatchOccurence(start, 900 start + pattern.size(), j)); 901 } 902 } 903 } 904 } 905 } 906 } 907 908 private class ParallelPairwiseAligner implements Runnable { 909 private final RuleApplicationData appData; 910 private final int from; 911 private final int to; 912 913 ParallelPairwiseAligner(RuleApplicationData appData, int from, int to) { 914 this.appData = appData; 915 this.from = from; 916 this.to = to; 917 } 918 919 @Override 920 public void run() { 921 int count = 0; 922 int size = to - from; 923 924 for (int i = from; i < to; i++) { 925 NumberSequence ns1 = appData.getNumberSequences().get(i); 926 count++; 927 RuleUtils.printProgressPercentage("Aligning Progress",count, size); 928 for (int j = 0; j < appData.getNumberSequences().size(); j++) { 929 NumberSequence ns2 = appData.getNumberSequences().get(j); 930 if (i != j) { 931 AlignmentAlgorithm aa = AlignmentAlgorithmFactory 932 .create(); 933 aa.align(ns1, ns2, appData.getSubmat(), 9); 934 synchronized (appData.getMatchseqs()) { 935 appData.getMatchseqs().addAll(aa.getMatches()); 936 } 937 } 938 } 939 } 940 } 941 } 942 943 // private LinkedList<Match> generatePairwiseAlignments(RuleApplicationData 944 // appData) { 945 private void generatePairwiseAlignments(RuleApplicationData appData) { 946 int numberSeqSize = appData.getNumberSequences().size(); 947 appData.matchseqs = new LinkedList<Match>(); 948 Console.traceln(Level.INFO, "generating pairwise alignments from " 949 + numberSeqSize + " sessions with " + nThreads + " threads"); 950 951 int newThreads = nThreads; 952 if (numberSeqSize < nThreads) { 953 newThreads = numberSeqSize; 954 } 955 956 ExecutorService executor = Executors.newFixedThreadPool(newThreads); 957 int interval = numberSeqSize / newThreads; 958 int rest = numberSeqSize % newThreads; 959 960 for (int i = 0; i < numberSeqSize - interval; i += interval) { 961 int offset = 0; 962 if (rest != 0) { 963 offset = 1; 964 rest--; 965 } 966 int from = i; 967 int to = i + interval + offset; 968 System.out.println("Creating thread for sessions " + from 969 + " till " + to); 970 ParallelPairwiseAligner aligner = new ParallelPairwiseAligner( 971 appData, from, to); 972 executor.execute(aligner); 973 } 974 executor.shutdown(); 975 try { 976 executor.awaitTermination(2, TimeUnit.HOURS); 977 } catch (InterruptedException e) { 978 // TODO Auto-generated catch block 979 e.printStackTrace(); 980 } 981 } 982 983 /** 984 * 985 */ 986 private static class RuleApplicationData implements Serializable { 987 988 /** 989 * 990 */ 991 private static final long serialVersionUID = -7559657686755522960L; 992 993 private HashMap<Integer, ITask> number2task; 994 995 // TODO: We Actually just need number2task here, this structure can be 996 // removed in the future. 997 private HashSet<ITask> uniqueTasks; 998 999 private ObjectDistanceSubstitionMatrix submat; 1000 1001 public HashMap<Integer, List<MatchOccurence>> replacedOccurences; 1002 1003 1004 public LinkedList<Match> matchseqs; 1005 1006 private ArrayList<NumberSequence> numberseqs; 1007 1008 private LinkedList<ITask> newTasks; 1009 1010 /** 1011 * 1012 */ 1013 private List<IUserSession> sessions; 1014 1015 /** 1016 * 1017 */ 1018 private boolean detectedAndReplacedTasks; 1019 1020 /** 1021 * 1022 */ 1023 private RuleApplicationResult result; 1024 1025 /** 1026 * 1027 */ 1028 private StopWatch stopWatch; 1029 1030 /** 1031 * 1032 */ 1033 private RuleApplicationData(List<IUserSession> sessions) { 1034 this.sessions = sessions; 1035 numberseqs = new ArrayList<NumberSequence>(); 1036 uniqueTasks = new HashSet<ITask>(); 1037 number2task = new HashMap<Integer, ITask>(); 1038 stopWatch = new StopWatch(); 1039 result = new RuleApplicationResult(); 1040 submat = new ObjectDistanceSubstitionMatrix(6, -3, false); 1041 newTasks = new LinkedList<ITask>(); 1042 this.detectedAndReplacedTasks = true; 1043 } 1044 1045 public LinkedList<Match> getMatchseqs() { 1046 return matchseqs; 1047 } 1048 1049 private ObjectDistanceSubstitionMatrix getSubmat() { 1050 return submat; 1051 } 1052 1053 synchronized private void resetNewlyCreatedTasks() { 1054 uniqueTasks.addAll(newTasks); 1055 newTasks.clear(); 1056 } 1057 1058 private void newTaskCreated(ITask task) { 1059 number2task.put(task.getId(), task); 1060 newTasks.add(task); 1061 } 1062 1063 /** 1064 * @return the UserSessions as List. 1065 */ 1066 private List<IUserSession> getSessions() { 1067 return sessions; 1068 } 1069 1070 1071 public HashMap<Integer, List<MatchOccurence>> getReplacedOccurences() { 1072 return replacedOccurences; 1073 } 1074 1075 public void setReplacedOccurences( 1076 HashMap<Integer, List<MatchOccurence>> replacedOccurences) { 1077 this.replacedOccurences = replacedOccurences; 1078 } 1079 1080 1081 private HashSet<ITask> getUniqueTasks() { 1082 return uniqueTasks; 1083 } 1084 1085 private void setNumberSequences(ArrayList<NumberSequence> numberseqs) { 1086 this.numberseqs = numberseqs; 1087 } 1088 1089 private ArrayList<NumberSequence> getNumberSequences() { 1090 return numberseqs; 1091 } 1092 1093 private void updateSubstitutionMatrix() { 1094 submat.update(getNewTasks()); 1095 resetNewlyCreatedTasks(); 1096 } 1097 1098 /** 1099 * 1100 */ 1101 private boolean detectedAndReplacedTasks() { 1102 return detectedAndReplacedTasks; 1103 } 1104 1105 /** 1106 * @return the result 1107 */ 1108 private RuleApplicationResult getResult() { 1109 return result; 1110 } 1111 1112 public LinkedList<ITask> getNewTasks() { 1113 return newTasks; 1114 } 1115 1116 /** 1117 * @return the stopWatch 1118 */ 1119 private StopWatch getStopWatch() { 1120 return stopWatch; 1121 } 1122 1123 private HashMap<Integer, ITask> getNumber2Task() { 1124 return number2task; 1125 } 1126 1152 /* 1153 * (non-Javadoc) 1154 * 1155 * @see java.lang.Object#toString() 1156 */ 1157 @Override 1158 public String toString() { 1159 return "SequenceForTaskDetectionRuleAlignment"; 1127 1160 } 1128 1161 -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TaskHandlingStrategy.java
r1551 r1733 24 24 * <p> 25 25 * concrete implementation of a symbol strategy required in the creation of a 26 * {@link de.ugoe.cs.autoquest.usageprofiles.Trie}. The strategy can be parameterized with a 27 * considered task equality. It uses task instance comparators to perform task comparison. 28 * It creates task specific symbol maps, which are {@link TaskSymbolIdentityMap} and 29 * {@link TaskSymbolBucketedMap} depending on the level of considered task equality. 26 * {@link de.ugoe.cs.autoquest.usageprofiles.Trie}. The strategy can be 27 * parameterized with a considered task equality. It uses task instance 28 * comparators to perform task comparison. It creates task specific symbol maps, 29 * which are {@link TaskSymbolIdentityMap} and {@link TaskSymbolBucketedMap} 30 * depending on the level of considered task equality. 30 31 * </p> 31 32 * … … 33 34 */ 34 35 public class TaskHandlingStrategy implements SymbolStrategy<ITaskInstance> { 35 36 /** */37 private static final long serialVersionUID = 1L;38 36 39 /** 40 * <p> 41 * the level of task equality considered in this task handling strategy 42 * </p> 43 */ 44 private TaskEquality consideredEquality; 37 /** */ 38 private static final long serialVersionUID = 1L; 45 39 46 47 48 * the comparator used for task comparisons 49 50 51 private TaskInstanceComparator comparator;40 /** 41 * <p> 42 * the level of task equality considered in this task handling strategy 43 * </p> 44 */ 45 private final TaskEquality consideredEquality; 52 46 53 /** 54 * <p> 55 * initializes this strategy with a task equality to be considered for task comparisons 56 * g</p> 57 * 58 * @param consideredEquality the task equality to be considered for task comparisons 59 */ 60 public TaskHandlingStrategy(TaskEquality consideredEquality) { 61 this.consideredEquality = consideredEquality; 62 63 if (this.consideredEquality == TaskEquality.IDENTICAL) { 64 comparator = new TaskIdentityComparator(); 65 } 66 else { 67 comparator = new TaskInstanceComparator(this.consideredEquality); 68 } 69 } 47 /** 48 * <p> 49 * the comparator used for task comparisons 50 * </p> 51 */ 52 private TaskInstanceComparator comparator; 70 53 71 /* (non-Javadoc) 72 * @see de.ugoe.cs.autoquest.usageprofiles.SymbolStrategy#getSymbolComparator() 73 */ 74 @Override 75 public SymbolComparator<ITaskInstance> getSymbolComparator() { 76 return comparator; 77 } 54 /** 55 * <p> 56 * initializes this strategy with a task equality to be considered for task 57 * comparisons g 58 * </p> 59 * 60 * @param consideredEquality 61 * the task equality to be considered for task comparisons 62 */ 63 public TaskHandlingStrategy(TaskEquality consideredEquality) { 64 this.consideredEquality = consideredEquality; 78 65 79 /** 80 * <p> 81 * convenience method to have a correctly typed return value as alternative to 82 * {@link #getSymbolComparator()}; 83 * </p> 84 */ 85 public TaskInstanceComparator getTaskComparator() { 86 return comparator; 87 } 66 if (this.consideredEquality == TaskEquality.IDENTICAL) { 67 comparator = new TaskIdentityComparator(); 68 } else { 69 comparator = new TaskInstanceComparator(this.consideredEquality); 70 } 71 } 88 72 89 /* (non-Javadoc) 90 * @see de.ugoe.cs.autoquest.usageprofiles.SymbolStrategy#createSymbolMap() 91 */ 92 @Override 93 public <V> SymbolMap<ITaskInstance, V> createSymbolMap() { 94 if (consideredEquality == TaskEquality.IDENTICAL) { 95 return new TaskSymbolIdentityMap<V>(); 96 } 97 else { 98 return new TaskSymbolBucketedMap<V>(comparator); 99 } 100 } 73 /* 74 * (non-Javadoc) 75 * 76 * @see 77 * de.ugoe.cs.autoquest.usageprofiles.SymbolStrategy#copySymbolMap(SymbolMap 78 * ) 79 */ 80 @Override 81 public <V> SymbolMap<ITaskInstance, V> copySymbolMap( 82 SymbolMap<ITaskInstance, V> other) { 83 if (consideredEquality == TaskEquality.IDENTICAL) { 84 return new TaskSymbolIdentityMap<V>(other); 85 } else { 86 return new TaskSymbolBucketedMap<V>(comparator); 87 } 88 } 101 89 102 /* (non-Javadoc) 103 * @see de.ugoe.cs.autoquest.usageprofiles.SymbolStrategy#copySymbolMap(SymbolMap) 104 */ 105 @Override 106 public <V> SymbolMap<ITaskInstance, V> copySymbolMap(SymbolMap<ITaskInstance, V> other) { 107 if (consideredEquality == TaskEquality.IDENTICAL) { 108 return new TaskSymbolIdentityMap<V>(other); 109 } 110 else { 111 return new TaskSymbolBucketedMap<V>(comparator); 112 } 113 } 90 /* 91 * (non-Javadoc) 92 * 93 * @see de.ugoe.cs.autoquest.usageprofiles.SymbolStrategy#createSymbolMap() 94 */ 95 @Override 96 public <V> SymbolMap<ITaskInstance, V> createSymbolMap() { 97 if (consideredEquality == TaskEquality.IDENTICAL) { 98 return new TaskSymbolIdentityMap<V>(); 99 } else { 100 return new TaskSymbolBucketedMap<V>(comparator); 101 } 102 } 103 104 /* 105 * (non-Javadoc) 106 * 107 * @see 108 * de.ugoe.cs.autoquest.usageprofiles.SymbolStrategy#getSymbolComparator() 109 */ 110 @Override 111 public SymbolComparator<ITaskInstance> getSymbolComparator() { 112 return comparator; 113 } 114 115 /** 116 * <p> 117 * convenience method to have a correctly typed return value as alternative 118 * to {@link #getSymbolComparator()}; 119 * </p> 120 */ 121 public TaskInstanceComparator getTaskComparator() { 122 return comparator; 123 } 114 124 115 125 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TaskIdentityComparator.java
r1401 r1733 20 20 /** 21 21 * <p> 22 * symbol comparator implementation for task instances considering to task instances as equal if 23 * they refer to the identical task object (comparison of object references). 22 * symbol comparator implementation for task instances considering to task 23 * instances as equal if they refer to the identical task object (comparison of 24 * object references). 24 25 * </p> 25 26 */ 26 27 class TaskIdentityComparator extends TaskInstanceComparator { 27 28 28 /** */ 29 private static final long serialVersionUID = 1L; 30 31 /** 32 * <p> 33 * initializes the parent class with the task equality {@link TaskEquality#IDENTICAL}. 34 * </p> 35 */ 36 public TaskIdentityComparator() { 37 super(TaskEquality.IDENTICAL); 38 } 39 40 /* (non-Javadoc) 41 * @see SymbolComparator#equals(Object, Object) 42 */ 43 @Override 44 public boolean equals(ITaskInstance taskInstance1, ITaskInstance taskInstance2) { 45 return taskInstance1.getTask() == taskInstance2.getTask(); 46 } 29 /** */ 30 private static final long serialVersionUID = 1L; 31 32 /** 33 * <p> 34 * initializes the parent class with the task equality 35 * {@link TaskEquality#IDENTICAL}. 36 * </p> 37 */ 38 public TaskIdentityComparator() { 39 super(TaskEquality.IDENTICAL); 40 } 41 42 /* 43 * (non-Javadoc) 44 * 45 * @see SymbolComparator#equals(Object, Object) 46 */ 47 @Override 48 public boolean equals(ITaskInstance taskInstance1, 49 ITaskInstance taskInstance2) { 50 return taskInstance1.getTask() == taskInstance2.getTask(); 51 } 47 52 48 53 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TaskInstanceComparator.java
r1401 r1733 27 27 /** 28 28 * <p> 29 * implementation of a symbol comparator for task instances. Internally, it uses comparison buffers 30 * to prevent comparing two tasks or task instances several times. It internally instantiates 31 * comparers being the implementation strategy of the comparisons required for a specific level 32 * of task equality. The comparers internally use the {@link TaskEqualityRuleManager} for 33 * performing comparisons. 29 * implementation of a symbol comparator for task instances. Internally, it uses 30 * comparison buffers to prevent comparing two tasks or task instances several 31 * times. It internally instantiates comparers being the implementation strategy 32 * of the comparisons required for a specific level of task equality. The 33 * comparers internally use the {@link TaskEqualityRuleManager} for performing 34 * comparisons. 34 35 * </p> 35 36 */ 36 37 public class TaskInstanceComparator implements SymbolComparator<ITaskInstance> { 37 38 /** */ 39 private static final long serialVersionUID = 1L; 40 41 /** 42 * the maximum size of the internal buffer used for storing comparison results 43 */ 44 private static final int MAX_BUFFER_SIZE = 2 * 1024 * 1024; 45 46 /** 47 * the considered level of task equality 48 */ 49 private TaskEquality minimalTaskEquality; 50 51 /** 52 * the comparer used internally for comparing two tasks 53 */ 54 private transient Comparer comparer; 55 56 /** 57 * the comparer used for comparing two tasks on the lexical level 58 */ 59 private transient Comparer lexicalComparer; 60 61 /** 62 * internal buffer used for storing comparison results 63 */ 64 private transient HashMap<Long, Boolean> equalityBuffer = new HashMap<Long, Boolean>(); 65 66 /** 67 * internal buffer used for storing comparison results only for lexical comparisons 68 */ 69 private transient HashMap<Long, Boolean> lexicalEqualityBuffer; 70 71 /** 72 * <p> 73 * initializes the comparator with a considered task equality level 74 * </p> 75 * 76 * @param minimalTaskEquality the considered task equality level 77 */ 78 public TaskInstanceComparator(TaskEquality minimalTaskEquality) { 79 this.minimalTaskEquality = minimalTaskEquality; 80 init(); 81 } 82 83 /* (non-Javadoc) 84 * @see SymbolComparator#equals(Object, Object) 85 */ 86 @Override 87 public boolean equals(ITaskInstance taskInstance1, ITaskInstance taskInstance2) { 88 return equals(taskInstance1.getTask(), taskInstance2.getTask()); 89 } 90 91 /** 92 * <p> 93 * returns true, if this comparator considers the provided tasks as equal, false else 94 * </p> 95 * 96 * @param task1 the first task to compare 97 * @param task2 the second task to compare 98 * 99 * @return as described 100 */ 101 public boolean equals(ITask task1, ITask task2) { 102 Boolean result; 103 104 if (task1 != task2) { 105 //if ((task1 instanceof IEventTask) && (task2 instanceof IEventTask)) { 106 long key = ((long) System.identityHashCode(task1)) << 32; 107 key += System.identityHashCode(task2); 108 109 result = equalityBuffer.get(key); 110 111 if (result == null) { 112 result = comparer.compare(task1, task2); 113 114 if (equalityBuffer.size() < MAX_BUFFER_SIZE) { 115 equalityBuffer.put(key, result); 116 } 117 } 118 /*} 119 else { 120 result = false; 121 }*/ 122 } 123 else { 124 result = true; 125 } 126 127 return result; 128 } 129 130 /** 131 * <p> 132 * returns true, if this comparator considers the provided tasks as lexically equal, false else 133 * </p> 134 * 135 * @param task1 the first task to compare 136 * @param task2 the second task to compare 137 * 138 * @return as described 139 */ 140 public boolean areLexicallyEqual(ITask task1, ITask task2) { 141 Boolean result; 142 143 if (task1 != task2) { 144 long key = ((long) System.identityHashCode(task1)) << 32; 145 key += System.identityHashCode(task2); 146 147 result = lexicalEqualityBuffer.get(key); 148 149 if (result == null) { 150 result = lexicalComparer.compare(task1, task2); 151 if (equalityBuffer.size() < MAX_BUFFER_SIZE) { 152 lexicalEqualityBuffer.put(key, result); 153 } 154 } 155 } 156 else { 157 result = true; 158 } 159 160 return result; 161 } 162 163 /** 164 * <p> 165 * can be called externally to clear the internal comparison buffers 166 * </p> 167 */ 168 public void clearBuffers() { 169 equalityBuffer.clear(); 170 init(); 171 } 172 173 /** 174 * <p> 175 * initializes the comparator with comparers depending on the different comparison levels as 176 * well as with the required comparison buffers. Comparers and buffers for lexical comparison 177 * may be reused if the considered equality level is also lexical. 178 * </p> 179 */ 180 private void init() { 181 if (minimalTaskEquality == TaskEquality.LEXICALLY_EQUAL) { 182 comparer = new LexicalComparer(); 183 } 184 else if (minimalTaskEquality == TaskEquality.SYNTACTICALLY_EQUAL) { 185 comparer = new SyntacticalComparer(); 186 } 187 else if (minimalTaskEquality == TaskEquality.SEMANTICALLY_EQUAL) { 188 comparer = new SemanticalComparer(); 189 } 190 else { 191 comparer = new DefaultComparer(this.minimalTaskEquality); 192 } 193 194 if (minimalTaskEquality == TaskEquality.LEXICALLY_EQUAL) { 195 lexicalComparer = comparer; 196 lexicalEqualityBuffer = equalityBuffer; 197 } 198 else { 199 lexicalComparer = new LexicalComparer(); 200 lexicalEqualityBuffer = new HashMap<Long, Boolean>(); 201 } 202 } 203 204 /** 205 * <p> 206 * deserialize this object and reinitialize the buffers 207 * </p> 208 */ 209 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 210 in.defaultReadObject(); 211 init(); 212 } 213 214 215 /** 216 * <p> 217 * interface for internally used comparers containing only a compare method 218 * </p> 219 */ 220 private static interface Comparer { 221 222 /** 223 * <p> 224 * returns true, if this comparator considers the provided tasks as equal, false else 225 * </p> 226 * 227 * @param task1 the first task to compare 228 * @param task2 the second task to compare 229 * 230 * @return as described 231 */ 232 boolean compare(ITask task1, ITask task2); 233 } 234 235 /** 236 * <p> 237 * comparer that performs comparisons only on the lexical level 238 * </p> 239 */ 240 private static class LexicalComparer implements Comparer { 241 242 /* (non-Javadoc) 243 * @see Comparer#compare(ITask, ITask) 244 */ 245 public boolean compare(ITask task1, ITask task2) { 246 return TaskEqualityRuleManager.getInstance().areLexicallyEqual(task1, task2); 247 } 248 } 249 250 /** 251 * <p> 252 * comparer that performs comparisons only on the syntactical level 253 * </p> 254 * 255 */ 256 private static class SyntacticalComparer implements Comparer { 257 258 /* (non-Javadoc) 259 * @see Comparer#compare(ITask, ITask) 260 */ 261 public boolean compare(ITask task1, ITask task2) { 262 return TaskEqualityRuleManager.getInstance().areSyntacticallyEqual(task1, task2); 263 } 264 } 265 266 /** 267 * <p> 268 * comparer that performs comparisons only on the semantical level 269 * </p> 270 */ 271 private static class SemanticalComparer implements Comparer { 272 273 /* (non-Javadoc) 274 * @see Comparer#compare(ITask, ITask) 275 */ 276 public boolean compare(ITask task1, ITask task2) { 277 return TaskEqualityRuleManager.getInstance().areSemanticallyEqual(task1, task2); 278 } 279 } 280 281 /** 282 * <p> 283 * comparer that performs comparisons only on the provided level 284 * </p> 285 */ 286 private static class DefaultComparer implements Comparer { 287 288 /** 289 * <p> 290 * the minimal task equality considered by this comparer 291 * </p> 292 */ 293 private TaskEquality minimalTaskEquality; 294 295 /** 296 * <p> 297 * initializes this comparer with the task equality to be considered 298 * </p> 299 */ 300 public DefaultComparer(TaskEquality minimalTaskEquality) { 301 this.minimalTaskEquality = minimalTaskEquality; 302 } 303 304 /* (non-Javadoc) 305 * @see Comparer#compare(ITask, ITask) 306 */ 307 public boolean compare(ITask task1, ITask task2) { 308 return TaskEqualityRuleManager.getInstance().areAtLeastEqual 309 (task1, task2, minimalTaskEquality); 310 } 311 } 38 39 /** 40 * <p> 41 * interface for internally used comparers containing only a compare method 42 * </p> 43 */ 44 private static interface Comparer { 45 46 /** 47 * <p> 48 * returns true, if this comparator considers the provided tasks as 49 * equal, false else 50 * </p> 51 * 52 * @param task1 53 * the first task to compare 54 * @param task2 55 * the second task to compare 56 * 57 * @return as described 58 */ 59 boolean compare(ITask task1, ITask task2); 60 } 61 62 /** 63 * <p> 64 * comparer that performs comparisons only on the provided level 65 * </p> 66 */ 67 private static class DefaultComparer implements Comparer { 68 69 /** 70 * <p> 71 * the minimal task equality considered by this comparer 72 * </p> 73 */ 74 private final TaskEquality minimalTaskEquality; 75 76 /** 77 * <p> 78 * initializes this comparer with the task equality to be considered 79 * </p> 80 */ 81 public DefaultComparer(TaskEquality minimalTaskEquality) { 82 this.minimalTaskEquality = minimalTaskEquality; 83 } 84 85 /* 86 * (non-Javadoc) 87 * 88 * @see Comparer#compare(ITask, ITask) 89 */ 90 @Override 91 public boolean compare(ITask task1, ITask task2) { 92 return TaskEqualityRuleManager.getInstance().areAtLeastEqual(task1, 93 task2, minimalTaskEquality); 94 } 95 } 96 97 /** 98 * <p> 99 * comparer that performs comparisons only on the lexical level 100 * </p> 101 */ 102 private static class LexicalComparer implements Comparer { 103 104 /* 105 * (non-Javadoc) 106 * 107 * @see Comparer#compare(ITask, ITask) 108 */ 109 @Override 110 public boolean compare(ITask task1, ITask task2) { 111 return TaskEqualityRuleManager.getInstance().areLexicallyEqual( 112 task1, task2); 113 } 114 } 115 116 /** 117 * <p> 118 * comparer that performs comparisons only on the semantical level 119 * </p> 120 */ 121 private static class SemanticalComparer implements Comparer { 122 123 /* 124 * (non-Javadoc) 125 * 126 * @see Comparer#compare(ITask, ITask) 127 */ 128 @Override 129 public boolean compare(ITask task1, ITask task2) { 130 return TaskEqualityRuleManager.getInstance().areSemanticallyEqual( 131 task1, task2); 132 } 133 } 134 135 /** 136 * <p> 137 * comparer that performs comparisons only on the syntactical level 138 * </p> 139 * 140 */ 141 private static class SyntacticalComparer implements Comparer { 142 143 /* 144 * (non-Javadoc) 145 * 146 * @see Comparer#compare(ITask, ITask) 147 */ 148 @Override 149 public boolean compare(ITask task1, ITask task2) { 150 return TaskEqualityRuleManager.getInstance().areSyntacticallyEqual( 151 task1, task2); 152 } 153 } 154 155 /** */ 156 private static final long serialVersionUID = 1L; 157 158 /** 159 * the maximum size of the internal buffer used for storing comparison 160 * results 161 */ 162 private static final int MAX_BUFFER_SIZE = 2 * 1024 * 1024; 163 164 /** 165 * the considered level of task equality 166 */ 167 private final TaskEquality minimalTaskEquality; 168 169 /** 170 * the comparer used internally for comparing two tasks 171 */ 172 private transient Comparer comparer; 173 174 /** 175 * the comparer used for comparing two tasks on the lexical level 176 */ 177 private transient Comparer lexicalComparer; 178 179 /** 180 * internal buffer used for storing comparison results 181 */ 182 private transient HashMap<Long, Boolean> equalityBuffer = new HashMap<Long, Boolean>(); 183 184 /** 185 * internal buffer used for storing comparison results only for lexical 186 * comparisons 187 */ 188 private transient HashMap<Long, Boolean> lexicalEqualityBuffer; 189 190 /** 191 * <p> 192 * initializes the comparator with a considered task equality level 193 * </p> 194 * 195 * @param minimalTaskEquality 196 * the considered task equality level 197 */ 198 public TaskInstanceComparator(TaskEquality minimalTaskEquality) { 199 this.minimalTaskEquality = minimalTaskEquality; 200 init(); 201 } 202 203 /** 204 * <p> 205 * returns true, if this comparator considers the provided tasks as 206 * lexically equal, false else 207 * </p> 208 * 209 * @param task1 210 * the first task to compare 211 * @param task2 212 * the second task to compare 213 * 214 * @return as described 215 */ 216 public boolean areLexicallyEqual(ITask task1, ITask task2) { 217 Boolean result; 218 219 if (task1 != task2) { 220 long key = ((long) System.identityHashCode(task1)) << 32; 221 key += System.identityHashCode(task2); 222 223 result = lexicalEqualityBuffer.get(key); 224 225 if (result == null) { 226 result = lexicalComparer.compare(task1, task2); 227 if (equalityBuffer.size() < MAX_BUFFER_SIZE) { 228 lexicalEqualityBuffer.put(key, result); 229 } 230 } 231 } else { 232 result = true; 233 } 234 235 return result; 236 } 237 238 /** 239 * <p> 240 * can be called externally to clear the internal comparison buffers 241 * </p> 242 */ 243 public void clearBuffers() { 244 equalityBuffer.clear(); 245 init(); 246 } 247 248 /** 249 * <p> 250 * returns true, if this comparator considers the provided tasks as equal, 251 * false else 252 * </p> 253 * 254 * @param task1 255 * the first task to compare 256 * @param task2 257 * the second task to compare 258 * 259 * @return as described 260 */ 261 public boolean equals(ITask task1, ITask task2) { 262 Boolean result; 263 264 if (task1 != task2) { 265 // if ((task1 instanceof IEventTask) && (task2 instanceof 266 // IEventTask)) { 267 long key = ((long) System.identityHashCode(task1)) << 32; 268 key += System.identityHashCode(task2); 269 270 result = equalityBuffer.get(key); 271 272 if (result == null) { 273 result = comparer.compare(task1, task2); 274 275 if (equalityBuffer.size() < MAX_BUFFER_SIZE) { 276 equalityBuffer.put(key, result); 277 } 278 } 279 /* 280 * } else { result = false; } 281 */ 282 } else { 283 result = true; 284 } 285 286 return result; 287 } 288 289 /* 290 * (non-Javadoc) 291 * 292 * @see SymbolComparator#equals(Object, Object) 293 */ 294 @Override 295 public boolean equals(ITaskInstance taskInstance1, 296 ITaskInstance taskInstance2) { 297 return equals(taskInstance1.getTask(), taskInstance2.getTask()); 298 } 299 300 /** 301 * <p> 302 * initializes the comparator with comparers depending on the different 303 * comparison levels as well as with the required comparison buffers. 304 * Comparers and buffers for lexical comparison may be reused if the 305 * considered equality level is also lexical. 306 * </p> 307 */ 308 private void init() { 309 if (minimalTaskEquality == TaskEquality.LEXICALLY_EQUAL) { 310 comparer = new LexicalComparer(); 311 } else if (minimalTaskEquality == TaskEquality.SYNTACTICALLY_EQUAL) { 312 comparer = new SyntacticalComparer(); 313 } else if (minimalTaskEquality == TaskEquality.SEMANTICALLY_EQUAL) { 314 comparer = new SemanticalComparer(); 315 } else { 316 comparer = new DefaultComparer(this.minimalTaskEquality); 317 } 318 319 if (minimalTaskEquality == TaskEquality.LEXICALLY_EQUAL) { 320 lexicalComparer = comparer; 321 lexicalEqualityBuffer = equalityBuffer; 322 } else { 323 lexicalComparer = new LexicalComparer(); 324 lexicalEqualityBuffer = new HashMap<Long, Boolean>(); 325 } 326 } 327 328 /** 329 * <p> 330 * deserialize this object and reinitialize the buffers 331 * </p> 332 */ 333 private void readObject(ObjectInputStream in) throws IOException, 334 ClassNotFoundException { 335 in.defaultReadObject(); 336 init(); 337 } 312 338 313 339 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TaskInstanceTrie.java
r1401 r1733 29 29 /** 30 30 * <p> 31 * This trie implementation is a performance optimization for generating task trees. It does not 32 * create a full trie but adds only those subsequences having a chance of occurring most often. 33 * For this, it initially counts the number of occurrences of each task instance. Then, during 34 * training, it regularly determines the number of the currently most often occurring sequence. If 35 * this number is higher than the count of a task instance to be trained, the task instance is 36 * skipped the not added to the trie. 31 * This trie implementation is a performance optimization for generating task 32 * trees. It does not create a full trie but adds only those subsequences having 33 * a chance of occurring most often. For this, it initially counts the number of 34 * occurrences of each task instance. Then, during training, it regularly 35 * determines the number of the currently most often occurring sequence. If this 36 * number is higher than the count of a task instance to be trained, the task 37 * instance is skipped the not added to the trie. 37 38 * </p> 38 39 * … … 41 42 class TaskInstanceTrie extends Trie<ITaskInstance> { 42 43 43 /** */ 44 private static final long serialVersionUID = 1L; 45 46 /** 47 * <p> 48 * the task handling strategy to be used for comparing tasks 49 * </p> 50 */ 51 private TaskHandlingStrategy taskStrategy; 52 53 /** 54 * <p> 55 * instantiated the trie with the task handling strategy to be used 56 * </p> 57 * 58 * @param taskStrategy the task handling strategy to be used for comparing tasks 59 */ 60 public TaskInstanceTrie(TaskHandlingStrategy taskStrategy) { 61 super(taskStrategy); 62 this.taskStrategy = taskStrategy; 63 } 64 65 /** 66 * <p> 67 * trains this trie with the provided user sessions up to the provided maximum depth using 68 * the optimization described in the description of this class. 69 * </p> 70 * 71 * @param userSessions the sessions for which this trie is to be trained 72 * @param maxOrder the depth of the trie 73 */ 74 public void trainSessions(List<IUserSession> userSessions, int maxOrder) { 75 if (maxOrder < 1) { 76 return; 77 } 78 79 SymbolMap<ITaskInstance, Counter> equalTaskInstancesMap = 80 taskStrategy.createSymbolMap(); 81 82 Map<ITask, Counter> instanceCountMap = new HashMap<ITask, Counter>(); 83 84 System.out.println("preparing training"); 85 int noOfTaskInstances = 0; 86 for (IUserSession session : userSessions) { 87 for (ITaskInstance taskInstance : session) { 88 Counter counter = equalTaskInstancesMap.getValue(taskInstance); 89 90 if (counter == null) { 91 counter = new Counter(); 92 equalTaskInstancesMap.addSymbol(taskInstance, counter); 93 } 94 95 counter.count++; 96 instanceCountMap.put(taskInstance.getTask(), counter); 97 98 noOfTaskInstances++; 99 } 100 } 101 102 System.out.println("performing training of " + noOfTaskInstances + " task instances"); 103 Counter processedTaskInstances = new Counter(); 104 int counterRecheckAt = noOfTaskInstances / 10; // recheck the maximum count after each 105 // 10% of processed task instances 106 for (IUserSession session : userSessions) { 107 train(session, maxOrder, instanceCountMap, processedTaskInstances, counterRecheckAt); 108 } 109 110 updateKnownSymbols(); 111 } 112 113 /* (non-Javadoc) 114 * @see de.ugoe.cs.autoquest.usageprofiles.Trie#equals(java.lang.Object) 115 */ 116 @Override 117 public boolean equals(Object other) { 118 if (this == other) { 119 return true; 120 } 121 else if (other instanceof TaskInstanceTrie) { 122 return super.equals(other); 123 } 124 else { 125 return false; 126 } 127 } 128 129 /* (non-Javadoc) 130 * @see de.ugoe.cs.autoquest.usageprofiles.Trie#hashCode() 131 */ 132 @Override 133 public int hashCode() { 134 return super.hashCode(); 135 } 136 137 /** 138 * <p> 139 * internally used convenience method for implementing the training optimization 140 * </p> 141 */ 142 private void train(IUserSession userSession, 143 int maxOrder, 144 Map<ITask, Counter> taskInstanceCountMap, 145 Counter processedTaskInstances, 146 int counterRecheckAt) 147 { 148 List<ITaskInstance> subsequence = new LinkedList<ITaskInstance>(); 149 150 int sequenceMaxCount = 0; 151 152 for (ITaskInstance currentTaskInstance : userSession) { 153 154 int occurrenceCount = taskInstanceCountMap.get(currentTaskInstance.getTask()).count; 155 156 if (processedTaskInstances.count >= counterRecheckAt) { 157 sequenceMaxCount = getCurrentSequenceMaxCount(); 158 processedTaskInstances.count = 0; 159 } 160 161 if (occurrenceCount < sequenceMaxCount) { 162 // this task instance does not need to be considered, as it occurs not often enough 163 // to be part of a sequence, that occurs most often. Therefore train all remaining 164 // sequences so far and go on, until the next useful sequence is found. 165 166 while (subsequence.size() > 1) { 167 add(subsequence); 168 subsequence.remove(0); 169 } 170 171 subsequence.clear(); 172 } 173 else { 174 subsequence.add(currentTaskInstance); 175 176 if (subsequence.size() == maxOrder) { 177 add(subsequence); 178 subsequence.remove(0); 179 } 180 } 181 182 processedTaskInstances.count++; 183 } 184 185 // add shorter remaining subsequences, if any 186 while (subsequence.size() > 1) { 187 add(subsequence); 188 subsequence.remove(0); 189 } 190 } 191 192 /** 193 * <p> 194 * determines the current maximum count of sequences of a minimal length of two. Task instances 195 * occuring more seldom do not have to be considered anymore 196 * </p> 197 * 198 * @return the current maximum count of sequences of a minimal length of two 199 */ 200 private int getCurrentSequenceMaxCount() { 201 MaxSequenceCountFinder processor = new MaxSequenceCountFinder(); 202 super.process(processor); 203 return processor.getMaxCount(); 204 } 205 206 /** 207 * <p> 208 * trie processor identifying the current maximum count of sequences of a minimal length of two 209 * </p> 210 * 211 * @author Patrick Harms 212 */ 213 private static class MaxSequenceCountFinder implements TrieProcessor<ITaskInstance> { 214 215 /** 216 * <p> 217 * the current maximum count 218 * </p> 219 */ 220 private int currentCount = 0; 221 222 /* (non-Javadoc) 223 * @see de.ugoe.cs.autoquest.usageprofiles.TrieProcessor#process(java.util.List, int) 224 */ 225 @Override 226 public TrieProcessor.Result process(List<ITaskInstance> foundTask, int count) { 227 if (foundTask.size() == 2) { 228 this.currentCount = Math.max(this.currentCount, count); 229 230 // do not consider children 231 return TrieProcessor.Result.SKIP_NODE; 232 } 233 else { 234 return TrieProcessor.Result.CONTINUE; 235 } 236 } 237 238 /** 239 * <p> 240 * returns the current maximum count 241 * </p> 242 */ 243 private int getMaxCount() { 244 return currentCount; 245 } 246 247 } 248 249 /** 250 * <p> 251 * counter object to be able to call something by the counters reference 252 * </p> 253 * 254 * @author Patrick Harms 255 */ 256 private static class Counter { 257 int count = 0; 258 } 259 44 /** 45 * <p> 46 * counter object to be able to call something by the counters reference 47 * </p> 48 * 49 * @author Patrick Harms 50 */ 51 private static class Counter { 52 int count = 0; 53 } 54 55 /** 56 * <p> 57 * trie processor identifying the current maximum count of sequences of a 58 * minimal length of two 59 * </p> 60 * 61 * @author Patrick Harms 62 */ 63 private static class MaxSequenceCountFinder implements 64 TrieProcessor<ITaskInstance> { 65 66 /** 67 * <p> 68 * the current maximum count 69 * </p> 70 */ 71 private int currentCount = 0; 72 73 /** 74 * <p> 75 * returns the current maximum count 76 * </p> 77 */ 78 private int getMaxCount() { 79 return currentCount; 80 } 81 82 /* 83 * (non-Javadoc) 84 * 85 * @see 86 * de.ugoe.cs.autoquest.usageprofiles.TrieProcessor#process(java.util 87 * .List, int) 88 */ 89 @Override 90 public TrieProcessor.Result process(List<ITaskInstance> foundTask, 91 int count) { 92 if (foundTask.size() == 2) { 93 this.currentCount = Math.max(this.currentCount, count); 94 95 // do not consider children 96 return TrieProcessor.Result.SKIP_NODE; 97 } else { 98 return TrieProcessor.Result.CONTINUE; 99 } 100 } 101 102 } 103 104 /** */ 105 private static final long serialVersionUID = 1L; 106 107 /** 108 * <p> 109 * the task handling strategy to be used for comparing tasks 110 * </p> 111 */ 112 private final TaskHandlingStrategy taskStrategy; 113 114 /** 115 * <p> 116 * instantiated the trie with the task handling strategy to be used 117 * </p> 118 * 119 * @param taskStrategy 120 * the task handling strategy to be used for comparing tasks 121 */ 122 public TaskInstanceTrie(TaskHandlingStrategy taskStrategy) { 123 super(taskStrategy); 124 this.taskStrategy = taskStrategy; 125 } 126 127 /* 128 * (non-Javadoc) 129 * 130 * @see de.ugoe.cs.autoquest.usageprofiles.Trie#equals(java.lang.Object) 131 */ 132 @Override 133 public boolean equals(Object other) { 134 if (this == other) { 135 return true; 136 } else if (other instanceof TaskInstanceTrie) { 137 return super.equals(other); 138 } else { 139 return false; 140 } 141 } 142 143 /** 144 * <p> 145 * determines the current maximum count of sequences of a minimal length of 146 * two. Task instances occuring more seldom do not have to be considered 147 * anymore 148 * </p> 149 * 150 * @return the current maximum count of sequences of a minimal length of two 151 */ 152 private int getCurrentSequenceMaxCount() { 153 final MaxSequenceCountFinder processor = new MaxSequenceCountFinder(); 154 super.process(processor); 155 return processor.getMaxCount(); 156 } 157 158 /* 159 * (non-Javadoc) 160 * 161 * @see de.ugoe.cs.autoquest.usageprofiles.Trie#hashCode() 162 */ 163 @Override 164 public int hashCode() { 165 return super.hashCode(); 166 } 167 168 /** 169 * <p> 170 * internally used convenience method for implementing the training 171 * optimization 172 * </p> 173 */ 174 private void train(IUserSession userSession, int maxOrder, 175 Map<ITask, Counter> taskInstanceCountMap, 176 Counter processedTaskInstances, int counterRecheckAt) { 177 final List<ITaskInstance> subsequence = new LinkedList<ITaskInstance>(); 178 179 int sequenceMaxCount = 0; 180 181 for (final ITaskInstance currentTaskInstance : userSession) { 182 183 final int occurrenceCount = taskInstanceCountMap 184 .get(currentTaskInstance.getTask()).count; 185 186 if (processedTaskInstances.count >= counterRecheckAt) { 187 sequenceMaxCount = getCurrentSequenceMaxCount(); 188 processedTaskInstances.count = 0; 189 } 190 191 if (occurrenceCount < sequenceMaxCount) { 192 // this task instance does not need to be considered, as it 193 // occurs not often enough 194 // to be part of a sequence, that occurs most often. Therefore 195 // train all remaining 196 // sequences so far and go on, until the next useful sequence is 197 // found. 198 199 while (subsequence.size() > 1) { 200 add(subsequence); 201 subsequence.remove(0); 202 } 203 204 subsequence.clear(); 205 } else { 206 subsequence.add(currentTaskInstance); 207 208 if (subsequence.size() == maxOrder) { 209 add(subsequence); 210 subsequence.remove(0); 211 } 212 } 213 214 processedTaskInstances.count++; 215 } 216 217 // add shorter remaining subsequences, if any 218 while (subsequence.size() > 1) { 219 add(subsequence); 220 subsequence.remove(0); 221 } 222 } 223 224 /** 225 * <p> 226 * trains this trie with the provided user sessions up to the provided 227 * maximum depth using the optimization described in the description of this 228 * class. 229 * </p> 230 * 231 * @param userSessions 232 * the sessions for which this trie is to be trained 233 * @param maxOrder 234 * the depth of the trie 235 */ 236 public void trainSessions(List<IUserSession> userSessions, int maxOrder) { 237 if (maxOrder < 1) { 238 return; 239 } 240 241 final SymbolMap<ITaskInstance, Counter> equalTaskInstancesMap = taskStrategy 242 .createSymbolMap(); 243 244 final Map<ITask, Counter> instanceCountMap = new HashMap<ITask, Counter>(); 245 246 System.out.println("preparing training"); 247 int noOfTaskInstances = 0; 248 for (final IUserSession session : userSessions) { 249 for (final ITaskInstance taskInstance : session) { 250 Counter counter = equalTaskInstancesMap.getValue(taskInstance); 251 252 if (counter == null) { 253 counter = new Counter(); 254 equalTaskInstancesMap.addSymbol(taskInstance, counter); 255 } 256 257 counter.count++; 258 instanceCountMap.put(taskInstance.getTask(), counter); 259 260 noOfTaskInstances++; 261 } 262 } 263 264 System.out.println("performing training of " + noOfTaskInstances 265 + " task instances"); 266 final Counter processedTaskInstances = new Counter(); 267 final int counterRecheckAt = noOfTaskInstances / 10; // recheck the 268 // maximum count 269 // after each 270 // 10% of processed task instances 271 for (final IUserSession session : userSessions) { 272 train(session, maxOrder, instanceCountMap, processedTaskInstances, 273 counterRecheckAt); 274 } 275 276 updateKnownSymbols(); 277 } 278 260 279 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TaskSymbolBucketedMap.java
r1408 r1733 36 36 /** 37 37 * <p> 38 * This class is a data structure for holding task instances in form of a symbol map. It is more 39 * efficient than a simple list. This data structure can be used with a comparator to adapt the 40 * effective list behavior and to define the equals strategy for comparing task instances. After a 41 * certain size ({@link #MAX_LIST_SIZE}), the map creates an index consisting of buckets of similar 42 * task instances. This allows searching for task instances in a more efficient order as the search 43 * can start in the most appropriate of the internal buckets. 38 * This class is a data structure for holding task instances in form of a symbol 39 * map. It is more efficient than a simple list. This data structure can be used 40 * with a comparator to adapt the effective list behavior and to define the 41 * equals strategy for comparing task instances. After a certain size ( 42 * {@link #MAX_LIST_SIZE}), the map creates an index consisting of buckets of 43 * similar task instances. This allows searching for task instances in a more 44 * efficient order as the search can start in the most appropriate of the 45 * internal buckets. 44 46 * </p> 45 47 * <p> 46 * The class is called a map, although it is not. It may contain the same task instances as 47 * separate keys. This implementation is done for performance improvements. If it is required to 48 * really assure, that a key exists only once, then each call to the 49 * {@link #addSymbol(Object, Object)} method should be done only, if the 50 * {@link #containsSymbol(Object)} method for the same symbol returns false. 48 * The class is called a map, although it is not. It may contain the same task 49 * instances as separate keys. This implementation is done for performance 50 * improvements. If it is required to really assure, that a key exists only 51 * once, then each call to the {@link #addSymbol(Object, Object)} method should 52 * be done only, if the {@link #containsSymbol(Object)} method for the same 53 * symbol returns false. 51 54 * </p> 52 55 * … … 56 59 * @param <V> 57 60 */ 58 class TaskSymbolBucketedMap<V> implements SymbolMap<ITaskInstance, V>, Serializable { 59 60 /** 61 * <p> 62 * default serial version UID 63 * </p> 64 */ 65 private static final long serialVersionUID = 1L; 66 67 /** 68 * <p> 69 * the maximum number of task instances in this map which is still only treated as list 70 * instead of using buckets. 71 * </p> 72 */ 73 private static final int MAX_LIST_SIZE = 15; 74 75 /** 76 * <p> 77 * Comparator to be used for comparing the task instances with each other 78 * </p> 79 */ 80 private TaskInstanceComparator comparator; 81 82 /** 83 * <p> 84 * Internally maintained plain list of task instances and associated values 85 * </p> 86 */ 87 private List<Map.Entry<ITaskInstance, V>> symbolList; 88 89 /** 90 * <p> 91 * If the size of the map exceeds {@link #MAX_LIST_SIZE}, this is the index using buckets 92 * for optimizing the search order. 93 * </p> 94 */ 95 private Map<Integer, List<Map.Entry<ITaskInstance, V>>> symbolBuckets; 96 97 /** 98 * <p> 99 * When using buckets, not any task instance may be associated a correct bucket. Therefore, we 100 * set a default bucket for all such task instances. This may change if the same bucket for a 101 * specific symbol is selected. 102 * </p> 103 */ 104 private int defaultBucket = 0; 105 106 /** 107 * <p> 108 * Instantiates a task instance map with a comparator 109 * </p> 110 * 111 * @param comparator the comparator to use for comparing task instances 112 * 113 * @throws IllegalArgumentException if the provided comparator is null 114 */ 115 public TaskSymbolBucketedMap(TaskInstanceComparator comparator) { 116 if (comparator == null) { 117 throw new IllegalArgumentException("comparator must not be null"); 118 } 119 120 this.comparator = comparator; 121 this.symbolList = new ArrayList<Map.Entry<ITaskInstance, V>>(); 122 } 123 124 /** 125 * <p> 126 * Copy constructor 127 * </p> 128 * 129 * @param otherMap the other map to be copied including its comparator 130 * 131 * @throws IllegalArgumentException if the provided other map is null 132 */ 133 public TaskSymbolBucketedMap(TaskSymbolBucketedMap<V> otherMap) { 134 if (otherMap == null) { 135 throw new IllegalArgumentException("otherMap must not be null"); 136 } 137 138 this.comparator = otherMap.comparator; 139 this.symbolList = new ArrayList<Map.Entry<ITaskInstance, V>>(otherMap.symbolList); 140 141 if (this.symbolList.size() > MAX_LIST_SIZE) { 142 createSymbolBuckets(); 143 } 144 } 145 146 /** 147 * <p> 148 * Returns the size of the map, i.e. the number of task instance entries 149 * </p> 150 * 151 * @return as described 152 */ 153 public int size() { 154 return symbolList.size(); 155 } 156 157 /** 158 * <p> 159 * Returns true if this map is empty, i.e. if {@link #size()} returns 0 160 * </p> 161 * 162 * @return as described 163 */ 164 public boolean isEmpty() { 165 return symbolList.isEmpty(); 166 } 167 168 /** 169 * <p> 170 * Returns true if the provided task instance was stored in this map. 171 * </p> 172 * 173 * @param symbol the task instance to check if it was stored in this map 174 * 175 * @return as described 176 * 177 * @throws IllegalArgumentException if the provided task instance is null 178 */ 179 public boolean containsSymbol(ITaskInstance symbol) { 180 if (symbol == null) { 181 throw new IllegalArgumentException("symbol must not be null"); 182 } 183 184 return getEntry(symbol) != null; 185 } 186 187 /** 188 * <p> 189 * Returns the value associated to the provided task instance in this map. If there is no value 190 * associated to the given task instance or if the task instance is not stored in this map, 191 * the method returns null. 192 * </p> 193 * 194 * @param symbol the task instance to return the value for 195 * 196 * @return as described 197 * 198 * @throws IllegalArgumentException if the provided task instance is null 199 */ 200 public V getValue(ITaskInstance symbol) { 201 if (symbol == null) { 202 throw new IllegalArgumentException("symbol must not be null"); 203 } 204 205 Map.Entry<ITaskInstance, V> entry = getEntry(symbol); 206 207 if (entry != null) { 208 return entry.getValue(); 209 } 210 else { 211 return null; 212 } 213 } 214 215 /** 216 * <p> 217 * Adds a task instance and an associated value to the map. If the value is null, the task 218 * instance is added, anyway and {@link #containsSymbol(Object)} will return true for that 219 * task instance. Adding the same task instance twice will produce two entries. This is 220 * contradictory to typical map implementations. To prevent this, the 221 * {@link #containsSymbol(Object)} and {@link #removeSymbol(Object)} methods should be used to 222 * ensure map behavior. 223 * </p> 224 * 225 * @param symbol the task instance to add to the map 226 * @param value the value to associate to the task instance in this map 227 * 228 * @return as described 229 * 230 * @throws IllegalArgumentException if the provided task instance is null 231 */ 232 public void addSymbol(ITaskInstance symbol, V value) { 233 if (symbol == null) { 234 throw new IllegalArgumentException("symbol must not be null"); 235 } 236 237 Map.Entry<ITaskInstance, V> entry = new SymbolMapEntry(symbol, value); 238 239 symbolList.add(entry); 240 241 if (symbolList.size() > MAX_LIST_SIZE) { 242 if (symbolBuckets == null) { 243 createSymbolBuckets(); 244 } 245 else { 246 addToSymbolBucket(entry); 247 } 248 } 249 } 250 251 /** 252 * <p> 253 * Removes a task instance and its associated value from the map. If the task instance is 254 * stored several times, only the first of its occurrences is removed. 255 * </p> 256 * 257 * @param symbol the task instance to be removed from the map 258 * 259 * @return as described 260 * 261 * @throws IllegalArgumentException if the provided task instance is null 262 */ 263 public V removeSymbol(ITaskInstance symbol) { 264 if (symbol == null) { 265 throw new IllegalArgumentException("symbol must not be null"); 266 } 267 268 for (int i = 0; i < symbolList.size(); i++) { 269 if (comparator.equals(symbolList.get(i).getKey(), symbol)) { 270 // found the symbol. Remove it from the list, and if required, also from the map. 271 V value = symbolList.remove(i).getValue(); 272 273 if (symbolList.size() > MAX_LIST_SIZE) { 274 removeFromSymbolBuckets(symbol); 275 } 276 277 return value; 278 } 279 } 280 281 return null; 282 } 283 284 /** 285 * <p> 286 * Returns a collection of all task instances in this map. 287 * </p> 288 * 289 * @return as described 290 */ 291 public Collection<ITaskInstance> getSymbols() { 292 return new ReadOnlyCollectionFacade<ITaskInstance>(symbolList, new SymbolFacade()); 293 } 294 295 /** 296 * <p> 297 * Returns a collection of all values associated to task instances in this map. May contain 298 * null values, if some of the task instances are mapped to null. The length of the returned 299 * collection is in any case the same as the size of the map. 300 * </p> 301 * 302 * @return as described 303 */ 304 public Collection<V> getValues() { 305 return new ReadOnlyCollectionFacade<V>(symbolList, new ValueFacade()); 306 } 307 308 /** 309 * <p> 310 * Removes all task instances and associated values from the map. 311 * </p> 312 */ 313 public void clear() { 314 symbolList.clear(); 315 symbolBuckets = null; 316 } 317 318 /* (non-Javadoc) 319 * @see java.lang.Object#hashCode() 320 */ 321 @Override 322 public int hashCode() { 323 return symbolList.size(); 324 } 325 326 /* (non-Javadoc) 327 * @see java.lang.Object#equals(java.lang.Object) 328 */ 329 @SuppressWarnings("unchecked") 330 @Override 331 public boolean equals(Object obj) { 332 if (this == obj) { 333 return true; 334 } 335 else if (this.getClass().isInstance(obj)) { 336 TaskSymbolBucketedMap<V> other = (TaskSymbolBucketedMap<V>) obj; 337 338 return (symbolList.size() == other.symbolList.size()) && 339 (symbolList.containsAll(other.symbolList)); 340 } 341 else { 342 return false; 343 } 344 } 345 346 /** 347 * <p> 348 * Internally used to create task instance buckets in case the number of stored task instances 349 * increased above {@link #MAX_LIST_SIZE}. 350 * </p> 351 */ 352 private void createSymbolBuckets() { 353 //System.out.println("creating symbol buckets"); 354 symbolBuckets = new HashMap<Integer, List<Map.Entry<ITaskInstance, V>>>(); 355 356 for (Map.Entry<ITaskInstance, V> symbol : symbolList) { 357 addToSymbolBucket(symbol); 358 } 359 } 360 361 /** 362 * <p> 363 * Adds a task instance and its value to its corresponding bucket. The corresponding bucket is 364 * the first element of the array returned by the method 365 * {@link #getBucketSearchOrder(ITaskInstance)}. If no search order for a task instance is 366 * defined, the entry is added to the default bucket. If the bucket id identical to the default 367 * bucket id, the default bucket id is shifted to another value. 368 * </p> 369 */ 370 private void addToSymbolBucket(Map.Entry<ITaskInstance, V> symbolEntry) { 371 int bucketId = defaultBucket; 372 int[] bucketSearchOrder = getBucketSearchOrder(symbolEntry.getKey()); 373 374 if ((bucketSearchOrder != null) && (bucketSearchOrder.length > 0)) { 375 bucketId = bucketSearchOrder[0]; 376 377 if (bucketId == defaultBucket) { 378 setNewDefaultBucketId(); 379 } 380 } 381 382 List<Map.Entry<ITaskInstance, V>> list = symbolBuckets.get(bucketId); 383 384 if (list == null) { 385 list = new LinkedList<Map.Entry<ITaskInstance, V>>(); 386 symbolBuckets.put(bucketId, list); 387 } 388 389 list.add(symbolEntry); 390 } 391 392 /** 393 * <p> 394 * returns the search order for a task instance which is different for event task instances, 395 * sequence instances, selection instances, and iteration instances 396 * </p> 397 */ 398 private int[] getBucketSearchOrder(ITaskInstance taskInstance) { 399 // 0 = sequence; 1 = selection; 2 = iteration; 3 = optional; 4 = event task in general; 400 // other = hashCode of name of event type 401 402 if (taskInstance instanceof IEventTaskInstance) { 403 // event tasks are most likely equal to those of the same type happening on the same 404 // target. Afterwards, they should be equal to those of the event type with the same 405 // name. Afterwards, they may be equal to iterations, optionals, other event tasks, 406 // selections, and finally the rest. 407 Event event = ((IEventTaskInstance) taskInstance).getEvent(); 408 return new int[] { event.getTarget().hashCode() + event.getType().getName().hashCode(), 409 event.getType().getName().hashCode(), 2, 3, 4, 1 }; 410 } 411 else if (taskInstance instanceof ISequenceInstance) { 412 return new int[] { 0, 2, 3, 1 }; 413 } 414 else if (taskInstance instanceof ISelectionInstance) { 415 return new int[] { 1, 4, 2, 3 }; 416 } 417 else if (taskInstance instanceof IIterationInstance) { 418 return new int[] { 2, 1, 4 }; 419 } 420 421 return null; 422 } 423 424 /** 425 * <p> 426 * Removes the entry for a given task instance from the buckets. It uses the bucket search order 427 * defined to find the task instance as fast as possible. 428 * </p> 429 */ 430 private Map.Entry<ITaskInstance, V> removeFromSymbolBuckets(ITaskInstance symbol) { 431 int bucketId = defaultBucket; 432 int[] bucketSearchOrder = getBucketSearchOrder(symbol); 433 434 if ((bucketSearchOrder != null) && (bucketSearchOrder.length > 0)) { 435 bucketId = bucketSearchOrder[0]; 436 } 437 438 List<Map.Entry<ITaskInstance, V>> list = symbolBuckets.get(bucketId); 439 Map.Entry<ITaskInstance, V> result = null; 440 441 if (list != null) { 442 for (int i = 0; i < list.size(); i++) { 443 if (comparator.equals(list.get(i).getKey(), symbol)) { 444 result = list.remove(i); 445 break; 446 } 447 } 448 449 if (list.isEmpty()) { 450 symbolBuckets.remove(bucketId); 451 } 452 } 453 454 return result; 455 } 456 457 /** 458 * <p> 459 * Updates the default bucket id to a new one 460 * </p> 461 */ 462 private void setNewDefaultBucketId() { 463 int oldDefaultBucket = defaultBucket; 464 do { 465 defaultBucket += 1; 466 } 467 while (symbolBuckets.containsKey(defaultBucket)); 468 469 symbolBuckets.put(defaultBucket, symbolBuckets.remove(oldDefaultBucket)); 470 } 471 472 /** 473 * <p> 474 * searches for the entry belonging to the given task instance. The method either uses the 475 * list if buckets are not used yet, or it uses the buckets and searches them in the order 476 * defined by the method {@link #getBucketSearchOrder(ITaskInstance)}. If the task instances 477 * isn't found and the bucket search order does not refer all buckets, then also the other 478 * buckets are searched for the task instance. 479 * </p> 480 */ 481 private Map.Entry<ITaskInstance, V> getEntry(ITaskInstance symbol) { 482 Map.Entry<ITaskInstance, V> entry = null; 483 if (symbolBuckets == null) { 484 entry = lookup(symbol, symbolList); 485 } 486 else { 487 int[] bucketSearchOrder = getBucketSearchOrder(symbol); 488 for (int bucketId : bucketSearchOrder) { 489 List<Map.Entry<ITaskInstance, V>> list = symbolBuckets.get(bucketId); 490 if (list != null) { 491 entry = lookup(symbol, list); 492 if (entry != null) { 493 break; 494 } 495 } 496 } 497 498 // try to search the other buckets 499 if (entry == null) { 500 Arrays.sort(bucketSearchOrder); 501 for (Map.Entry<Integer, List<Map.Entry<ITaskInstance, V>>> bucket : symbolBuckets.entrySet()) { 502 if (Arrays.binarySearch(bucketSearchOrder, bucket.getKey()) < 0) { 503 List<Map.Entry<ITaskInstance, V>> list = bucket.getValue(); 504 if (list != null) { 505 entry = lookup(symbol, list); 506 if (entry != null) { 507 break; 508 } 509 } 510 } 511 } 512 } 513 } 514 515 return entry; 516 } 517 518 /** 519 * <p> 520 * Convenience method to look up a symbol in a list of entries using the comparator. 521 * </p> 522 */ 523 private Map.Entry<ITaskInstance, V> lookup(ITaskInstance symbol, List<Map.Entry<ITaskInstance, V>> list) { 524 for (Map.Entry<ITaskInstance, V> candidate : list) { 525 if (comparator.equals(candidate.getKey(), symbol)) { 526 return candidate; 527 } 528 } 529 530 return null; 531 } 532 533 /** 534 * <p> 535 * Internally used data structure for storing task instance - value pairs 536 * </p> 537 * 538 * @author Patrick Harms 539 */ 540 private class SymbolMapEntry implements Map.Entry<ITaskInstance, V> { 541 542 /** 543 * the task instance to map to a value 544 */ 545 private ITaskInstance symbol; 546 547 /** 548 * the value associated with the symbol 549 */ 550 private V value; 551 552 /** 553 * <p> 554 * Simple constructor for initializing the entry with a task instance and its associated 555 * value. 556 * </p> 557 */ 558 private SymbolMapEntry(ITaskInstance symbol, V value) { 559 super(); 560 this.symbol = symbol; 561 this.value = value; 562 } 563 564 /* (non-Javadoc) 565 * @see java.util.Map.Entry#getKey() 566 */ 567 @Override 568 public ITaskInstance getKey() { 569 return symbol; 570 } 571 572 /* (non-Javadoc) 573 * @see java.util.Map.Entry#getValue() 574 */ 575 @Override 576 public V getValue() { 577 return value; 578 } 579 580 /* (non-Javadoc) 581 * @see java.util.Map.Entry#setValue(java.lang.Object) 582 */ 583 @Override 584 public V setValue(V value) { 585 V oldValue = this.value; 586 this.value = value; 587 return oldValue; 588 } 589 590 /* (non-Javadoc) 591 * @see java.lang.Object#hashCode() 592 */ 593 @Override 594 public int hashCode() { 595 return symbol.hashCode(); 596 } 597 598 /* (non-Javadoc) 599 * @see java.lang.Object#equals(java.lang.Object) 600 */ 601 @SuppressWarnings("unchecked") 602 @Override 603 public boolean equals(Object obj) { 604 if (this == obj) { 605 return true; 606 } 607 else if (this.getClass().isInstance(obj)) { 608 SymbolMapEntry other = (SymbolMapEntry) obj; 609 return (symbol.equals(other.symbol) && 610 (value == null ? other.value == null : value.equals(other.value))); 611 } 612 else { 613 return false; 614 } 615 } 616 617 /* (non-Javadoc) 618 * @see java.lang.Object#toString() 619 */ 620 @Override 621 public String toString() { 622 return symbol + "=" + value; 623 } 624 625 } 626 627 /** 628 * <p> 629 * Used to create an efficient facade for accessing the internal list of entries either only 630 * for the task instances or only for the values. It is a default implementation of the 631 * collection interface. The entry facade provided to the constructor decides, if either the 632 * list accesses only the task instances or only the values. 633 * </p> 634 * 635 * @author Patrick Harms 636 */ 637 private class ReadOnlyCollectionFacade<TYPE> implements Collection<TYPE> { 638 639 /** 640 * the list facaded by this facade 641 */ 642 private List<Map.Entry<ITaskInstance, V>> list; 643 644 /** 645 * the facade to be used for the entries 646 */ 647 private EntryFacade<TYPE> entryFacade; 648 649 /** 650 * <p> 651 * Initializes the facade with the facaded list and the facade to be used for the entries 652 * </p> 653 */ 654 private ReadOnlyCollectionFacade(List<Map.Entry<ITaskInstance, V>> list, 655 EntryFacade<TYPE> entryFacade) 656 { 657 this.list = list; 658 this.entryFacade = entryFacade; 659 } 660 661 /* (non-Javadoc) 662 * @see java.util.Collection#size() 663 */ 664 @Override 665 public int size() { 666 return list.size(); 667 } 668 669 /* (non-Javadoc) 670 * @see java.util.Collection#isEmpty() 671 */ 672 @Override 673 public boolean isEmpty() { 674 return list.isEmpty(); 675 } 676 677 /* (non-Javadoc) 678 * @see java.util.Collection#contains(java.lang.Object) 679 */ 680 @Override 681 public boolean contains(Object o) { 682 if (o == null) { 683 for (Map.Entry<ITaskInstance, V> entry : list) { 684 if (entryFacade.getFacadedElement(entry) == null) { 685 return true; 686 } 687 } 688 } 689 else { 690 for (Map.Entry<ITaskInstance, V> entry : list) { 691 if (o.equals(entryFacade.getFacadedElement(entry))) { 692 return true; 693 } 694 } 695 } 696 697 return false; 698 } 699 700 /* (non-Javadoc) 701 * @see java.util.Collection#toArray() 702 */ 703 @Override 704 public Object[] toArray() { 705 Object[] result = new Object[list.size()]; 706 707 for (int i = 0; i < list.size(); i++) { 708 result[i] = entryFacade.getFacadedElement(list.get(i)); 709 } 710 711 return result; 712 } 713 714 /* (non-Javadoc) 715 * @see java.util.Collection#toArray(T[]) 716 */ 717 @SuppressWarnings("unchecked") 718 @Override 719 public <T> T[] toArray(T[] a) { 720 T[] result = a; 721 722 for (int i = 0; i < list.size(); i++) { 723 result[i] = (T) entryFacade.getFacadedElement(list.get(i)); 724 } 725 726 return result; 727 } 728 729 /* (non-Javadoc) 730 * @see java.util.Collection#add(java.lang.Object) 731 */ 732 @Override 733 public boolean add(TYPE e) { 734 throw new UnsupportedOperationException("this collection is read only"); 735 } 736 737 /* (non-Javadoc) 738 * @see java.util.Collection#remove(java.lang.Object) 739 */ 740 @Override 741 public boolean remove(Object o) { 742 throw new UnsupportedOperationException("this collection is read only"); 743 } 744 745 /* (non-Javadoc) 746 * @see java.util.Collection#containsAll(java.util.Collection) 747 */ 748 @Override 749 public boolean containsAll(Collection<?> c) { 750 for (Object candidate : c) { 751 if (!contains(candidate)) { 752 return false; 753 } 754 } 755 756 return true; 757 } 758 759 /* (non-Javadoc) 760 * @see java.util.Collection#addAll(java.util.Collection) 761 */ 762 @Override 763 public boolean addAll(Collection<? extends TYPE> c) { 764 throw new UnsupportedOperationException("this collection is read only"); 765 } 766 767 /* (non-Javadoc) 768 * @see java.util.Collection#removeAll(java.util.Collection) 769 */ 770 @Override 771 public boolean removeAll(Collection<?> c) { 772 throw new UnsupportedOperationException("this collection is read only"); 773 } 774 775 /* (non-Javadoc) 776 * @see java.util.Collection#retainAll(java.util.Collection) 777 */ 778 @Override 779 public boolean retainAll(Collection<?> c) { 780 throw new UnsupportedOperationException("this collection is read only"); 781 } 782 783 /* (non-Javadoc) 784 * @see java.util.Collection#clear() 785 */ 786 @Override 787 public void clear() { 788 throw new UnsupportedOperationException("this collection is read only"); 789 } 790 791 /* (non-Javadoc) 792 * @see java.util.Collection#iterator() 793 */ 794 @Override 795 public Iterator<TYPE> iterator() { 796 return new ReadOnlyCollectionIteratorFacade<TYPE>(list.iterator(), entryFacade); 797 } 798 799 } 800 801 /** 802 * <p> 803 * Implementation of an iterator to facade an iterator on the internal list of task instance 804 * entries. 805 * </p> 806 * 807 * @author Patrick Harms 808 */ 809 private class ReadOnlyCollectionIteratorFacade<TYPE> implements Iterator<TYPE> { 810 811 /** 812 * the facaded iterator 813 */ 814 private Iterator<Map.Entry<ITaskInstance, V>> iterator; 815 816 /** 817 * the facade for the entries provided by the facaded iterator 818 */ 819 private EntryFacade<TYPE> entryFacade; 820 821 /** 822 * <p> 823 * initialized this facade with the facaded iterator and the entry facade to be used for 824 * the entries. 825 * </p> 826 */ 827 private ReadOnlyCollectionIteratorFacade(Iterator<Map.Entry<ITaskInstance, V>> iterator, 828 EntryFacade<TYPE> entryFacade) 829 { 830 this.iterator = iterator; 831 this.entryFacade = entryFacade; 832 } 833 834 /* (non-Javadoc) 835 * @see java.util.Iterator#hasNext() 836 */ 837 @Override 838 public boolean hasNext() { 839 return iterator.hasNext(); 840 } 841 842 /* (non-Javadoc) 843 * @see java.util.Iterator#next() 844 */ 845 @Override 846 public TYPE next() { 847 return entryFacade.getFacadedElement(iterator.next()); 848 } 849 850 /* (non-Javadoc) 851 * @see java.util.Iterator#remove() 852 */ 853 @Override 854 public void remove() { 855 throw new UnsupportedOperationException("this iterator is read only"); 856 } 857 858 } 859 860 /** 861 * <p> 862 * Used to facade task instance entries and to return only this part of an entry, that is 863 * relevant. 864 * </p> 865 * 866 * @author Patrick Harms 867 */ 868 private abstract class EntryFacade<T> { 869 870 /** 871 * <p> 872 * Returns only the part of an entry that is relevant or required. 873 * </p> 874 * 875 * @param entry of which the part shall be returned 876 * 877 * @return the part of the entry to be returned 878 */ 879 protected abstract T getFacadedElement(Entry<ITaskInstance, V> entry); 880 881 } 882 883 /** 884 * <p> 885 * Implementation of the entry facade returning the entries key, i.e. the symbol. 886 * </p> 887 * 888 * @author Patrick Harms 889 */ 890 private class SymbolFacade extends EntryFacade<ITaskInstance> { 891 892 /* (non-Javadoc) 893 * @see ReadOnlyCollectionIteratorFacade#getFacadedElement(Entry) 894 */ 895 @Override 896 protected ITaskInstance getFacadedElement(Entry<ITaskInstance, V> entry) { 897 return entry.getKey(); 898 } 899 } 900 901 /** 902 * <p> 903 * Implementation of the entry facade returning the entries value, i.e. the value associated to 904 * the symbol. 905 * </p> 906 * 907 * @author Patrick Harms 908 */ 909 private class ValueFacade extends EntryFacade<V> { 910 911 /* (non-Javadoc) 912 * @see ReadOnlyCollectionIteratorFacade#getFacadedElement(Entry) 913 */ 914 @Override 915 protected V getFacadedElement(Entry<ITaskInstance, V> entry) { 916 return entry.getValue(); 917 } 918 } 61 class TaskSymbolBucketedMap<V> implements SymbolMap<ITaskInstance, V>, 62 Serializable { 63 64 /** 65 * <p> 66 * Used to facade task instance entries and to return only this part of an 67 * entry, that is relevant. 68 * </p> 69 * 70 * @author Patrick Harms 71 */ 72 private abstract class EntryFacade<T> { 73 74 /** 75 * <p> 76 * Returns only the part of an entry that is relevant or required. 77 * </p> 78 * 79 * @param entry 80 * of which the part shall be returned 81 * 82 * @return the part of the entry to be returned 83 */ 84 protected abstract T getFacadedElement(Entry<ITaskInstance, V> entry); 85 86 } 87 88 /** 89 * <p> 90 * Used to create an efficient facade for accessing the internal list of 91 * entries either only for the task instances or only for the values. It is 92 * a default implementation of the collection interface. The entry facade 93 * provided to the constructor decides, if either the list accesses only the 94 * task instances or only the values. 95 * </p> 96 * 97 * @author Patrick Harms 98 */ 99 private class ReadOnlyCollectionFacade<TYPE> implements Collection<TYPE> { 100 101 /** 102 * the list facaded by this facade 103 */ 104 private final List<Map.Entry<ITaskInstance, V>> list; 105 106 /** 107 * the facade to be used for the entries 108 */ 109 private final EntryFacade<TYPE> entryFacade; 110 111 /** 112 * <p> 113 * Initializes the facade with the facaded list and the facade to be 114 * used for the entries 115 * </p> 116 */ 117 private ReadOnlyCollectionFacade( 118 List<Map.Entry<ITaskInstance, V>> list, 119 EntryFacade<TYPE> entryFacade) { 120 this.list = list; 121 this.entryFacade = entryFacade; 122 } 123 124 /* 125 * (non-Javadoc) 126 * 127 * @see java.util.Collection#add(java.lang.Object) 128 */ 129 @Override 130 public boolean add(TYPE e) { 131 throw new UnsupportedOperationException( 132 "this collection is read only"); 133 } 134 135 /* 136 * (non-Javadoc) 137 * 138 * @see java.util.Collection#addAll(java.util.Collection) 139 */ 140 @Override 141 public boolean addAll(Collection<? extends TYPE> c) { 142 throw new UnsupportedOperationException( 143 "this collection is read only"); 144 } 145 146 /* 147 * (non-Javadoc) 148 * 149 * @see java.util.Collection#clear() 150 */ 151 @Override 152 public void clear() { 153 throw new UnsupportedOperationException( 154 "this collection is read only"); 155 } 156 157 /* 158 * (non-Javadoc) 159 * 160 * @see java.util.Collection#contains(java.lang.Object) 161 */ 162 @Override 163 public boolean contains(Object o) { 164 if (o == null) { 165 for (final Map.Entry<ITaskInstance, V> entry : list) { 166 if (entryFacade.getFacadedElement(entry) == null) { 167 return true; 168 } 169 } 170 } else { 171 for (final Map.Entry<ITaskInstance, V> entry : list) { 172 if (o.equals(entryFacade.getFacadedElement(entry))) { 173 return true; 174 } 175 } 176 } 177 178 return false; 179 } 180 181 /* 182 * (non-Javadoc) 183 * 184 * @see java.util.Collection#containsAll(java.util.Collection) 185 */ 186 @Override 187 public boolean containsAll(Collection<?> c) { 188 for (final Object candidate : c) { 189 if (!contains(candidate)) { 190 return false; 191 } 192 } 193 194 return true; 195 } 196 197 /* 198 * (non-Javadoc) 199 * 200 * @see java.util.Collection#isEmpty() 201 */ 202 @Override 203 public boolean isEmpty() { 204 return list.isEmpty(); 205 } 206 207 /* 208 * (non-Javadoc) 209 * 210 * @see java.util.Collection#iterator() 211 */ 212 @Override 213 public Iterator<TYPE> iterator() { 214 return new ReadOnlyCollectionIteratorFacade<TYPE>(list.iterator(), 215 entryFacade); 216 } 217 218 /* 219 * (non-Javadoc) 220 * 221 * @see java.util.Collection#remove(java.lang.Object) 222 */ 223 @Override 224 public boolean remove(Object o) { 225 throw new UnsupportedOperationException( 226 "this collection is read only"); 227 } 228 229 /* 230 * (non-Javadoc) 231 * 232 * @see java.util.Collection#removeAll(java.util.Collection) 233 */ 234 @Override 235 public boolean removeAll(Collection<?> c) { 236 throw new UnsupportedOperationException( 237 "this collection is read only"); 238 } 239 240 /* 241 * (non-Javadoc) 242 * 243 * @see java.util.Collection#retainAll(java.util.Collection) 244 */ 245 @Override 246 public boolean retainAll(Collection<?> c) { 247 throw new UnsupportedOperationException( 248 "this collection is read only"); 249 } 250 251 /* 252 * (non-Javadoc) 253 * 254 * @see java.util.Collection#size() 255 */ 256 @Override 257 public int size() { 258 return list.size(); 259 } 260 261 /* 262 * (non-Javadoc) 263 * 264 * @see java.util.Collection#toArray() 265 */ 266 @Override 267 public Object[] toArray() { 268 final Object[] result = new Object[list.size()]; 269 270 for (int i = 0; i < list.size(); i++) { 271 result[i] = entryFacade.getFacadedElement(list.get(i)); 272 } 273 274 return result; 275 } 276 277 /* 278 * (non-Javadoc) 279 * 280 * @see java.util.Collection#toArray(T[]) 281 */ 282 @SuppressWarnings("unchecked") 283 @Override 284 public <T> T[] toArray(T[] a) { 285 final T[] result = a; 286 287 for (int i = 0; i < list.size(); i++) { 288 result[i] = (T) entryFacade.getFacadedElement(list.get(i)); 289 } 290 291 return result; 292 } 293 294 } 295 296 /** 297 * <p> 298 * Implementation of an iterator to facade an iterator on the internal list 299 * of task instance entries. 300 * </p> 301 * 302 * @author Patrick Harms 303 */ 304 private class ReadOnlyCollectionIteratorFacade<TYPE> implements 305 Iterator<TYPE> { 306 307 /** 308 * the facaded iterator 309 */ 310 private final Iterator<Map.Entry<ITaskInstance, V>> iterator; 311 312 /** 313 * the facade for the entries provided by the facaded iterator 314 */ 315 private final EntryFacade<TYPE> entryFacade; 316 317 /** 318 * <p> 319 * initialized this facade with the facaded iterator and the entry 320 * facade to be used for the entries. 321 * </p> 322 */ 323 private ReadOnlyCollectionIteratorFacade( 324 Iterator<Map.Entry<ITaskInstance, V>> iterator, 325 EntryFacade<TYPE> entryFacade) { 326 this.iterator = iterator; 327 this.entryFacade = entryFacade; 328 } 329 330 /* 331 * (non-Javadoc) 332 * 333 * @see java.util.Iterator#hasNext() 334 */ 335 @Override 336 public boolean hasNext() { 337 return iterator.hasNext(); 338 } 339 340 /* 341 * (non-Javadoc) 342 * 343 * @see java.util.Iterator#next() 344 */ 345 @Override 346 public TYPE next() { 347 return entryFacade.getFacadedElement(iterator.next()); 348 } 349 350 /* 351 * (non-Javadoc) 352 * 353 * @see java.util.Iterator#remove() 354 */ 355 @Override 356 public void remove() { 357 throw new UnsupportedOperationException( 358 "this iterator is read only"); 359 } 360 361 } 362 363 /** 364 * <p> 365 * Implementation of the entry facade returning the entries key, i.e. the 366 * symbol. 367 * </p> 368 * 369 * @author Patrick Harms 370 */ 371 private class SymbolFacade extends EntryFacade<ITaskInstance> { 372 373 /* 374 * (non-Javadoc) 375 * 376 * @see ReadOnlyCollectionIteratorFacade#getFacadedElement(Entry) 377 */ 378 @Override 379 protected ITaskInstance getFacadedElement(Entry<ITaskInstance, V> entry) { 380 return entry.getKey(); 381 } 382 } 383 384 /** 385 * <p> 386 * Internally used data structure for storing task instance - value pairs 387 * </p> 388 * 389 * @author Patrick Harms 390 */ 391 private class SymbolMapEntry implements Map.Entry<ITaskInstance, V> { 392 393 /** 394 * the task instance to map to a value 395 */ 396 private final ITaskInstance symbol; 397 398 /** 399 * the value associated with the symbol 400 */ 401 private V value; 402 403 /** 404 * <p> 405 * Simple constructor for initializing the entry with a task instance 406 * and its associated value. 407 * </p> 408 */ 409 private SymbolMapEntry(ITaskInstance symbol, V value) { 410 super(); 411 this.symbol = symbol; 412 this.value = value; 413 } 414 415 /* 416 * (non-Javadoc) 417 * 418 * @see java.lang.Object#equals(java.lang.Object) 419 */ 420 @SuppressWarnings("unchecked") 421 @Override 422 public boolean equals(Object obj) { 423 if (this == obj) { 424 return true; 425 } else if (this.getClass().isInstance(obj)) { 426 final SymbolMapEntry other = (SymbolMapEntry) obj; 427 return (symbol.equals(other.symbol) && (value == null ? other.value == null 428 : value.equals(other.value))); 429 } else { 430 return false; 431 } 432 } 433 434 /* 435 * (non-Javadoc) 436 * 437 * @see java.util.Map.Entry#getKey() 438 */ 439 @Override 440 public ITaskInstance getKey() { 441 return symbol; 442 } 443 444 /* 445 * (non-Javadoc) 446 * 447 * @see java.util.Map.Entry#getValue() 448 */ 449 @Override 450 public V getValue() { 451 return value; 452 } 453 454 /* 455 * (non-Javadoc) 456 * 457 * @see java.lang.Object#hashCode() 458 */ 459 @Override 460 public int hashCode() { 461 return symbol.hashCode(); 462 } 463 464 /* 465 * (non-Javadoc) 466 * 467 * @see java.util.Map.Entry#setValue(java.lang.Object) 468 */ 469 @Override 470 public V setValue(V value) { 471 final V oldValue = this.value; 472 this.value = value; 473 return oldValue; 474 } 475 476 /* 477 * (non-Javadoc) 478 * 479 * @see java.lang.Object#toString() 480 */ 481 @Override 482 public String toString() { 483 return symbol + "=" + value; 484 } 485 486 } 487 488 /** 489 * <p> 490 * Implementation of the entry facade returning the entries value, i.e. the 491 * value associated to the symbol. 492 * </p> 493 * 494 * @author Patrick Harms 495 */ 496 private class ValueFacade extends EntryFacade<V> { 497 498 /* 499 * (non-Javadoc) 500 * 501 * @see ReadOnlyCollectionIteratorFacade#getFacadedElement(Entry) 502 */ 503 @Override 504 protected V getFacadedElement(Entry<ITaskInstance, V> entry) { 505 return entry.getValue(); 506 } 507 } 508 509 /** 510 * <p> 511 * default serial version UID 512 * </p> 513 */ 514 private static final long serialVersionUID = 1L; 515 516 /** 517 * <p> 518 * the maximum number of task instances in this map which is still only 519 * treated as list instead of using buckets. 520 * </p> 521 */ 522 private static final int MAX_LIST_SIZE = 15; 523 524 /** 525 * <p> 526 * Comparator to be used for comparing the task instances with each other 527 * </p> 528 */ 529 private final TaskInstanceComparator comparator; 530 531 /** 532 * <p> 533 * Internally maintained plain list of task instances and associated values 534 * </p> 535 */ 536 private final List<Map.Entry<ITaskInstance, V>> symbolList; 537 538 /** 539 * <p> 540 * If the size of the map exceeds {@link #MAX_LIST_SIZE}, this is the index 541 * using buckets for optimizing the search order. 542 * </p> 543 */ 544 private Map<Integer, List<Map.Entry<ITaskInstance, V>>> symbolBuckets; 545 546 /** 547 * <p> 548 * When using buckets, not any task instance may be associated a correct 549 * bucket. Therefore, we set a default bucket for all such task instances. 550 * This may change if the same bucket for a specific symbol is selected. 551 * </p> 552 */ 553 private int defaultBucket = 0; 554 555 /** 556 * <p> 557 * Instantiates a task instance map with a comparator 558 * </p> 559 * 560 * @param comparator 561 * the comparator to use for comparing task instances 562 * 563 * @throws IllegalArgumentException 564 * if the provided comparator is null 565 */ 566 public TaskSymbolBucketedMap(TaskInstanceComparator comparator) { 567 if (comparator == null) { 568 throw new IllegalArgumentException("comparator must not be null"); 569 } 570 571 this.comparator = comparator; 572 this.symbolList = new ArrayList<Map.Entry<ITaskInstance, V>>(); 573 } 574 575 /** 576 * <p> 577 * Copy constructor 578 * </p> 579 * 580 * @param otherMap 581 * the other map to be copied including its comparator 582 * 583 * @throws IllegalArgumentException 584 * if the provided other map is null 585 */ 586 public TaskSymbolBucketedMap(TaskSymbolBucketedMap<V> otherMap) { 587 if (otherMap == null) { 588 throw new IllegalArgumentException("otherMap must not be null"); 589 } 590 591 this.comparator = otherMap.comparator; 592 this.symbolList = new ArrayList<Map.Entry<ITaskInstance, V>>( 593 otherMap.symbolList); 594 595 if (this.symbolList.size() > MAX_LIST_SIZE) { 596 createSymbolBuckets(); 597 } 598 } 599 600 /** 601 * <p> 602 * Adds a task instance and an associated value to the map. If the value is 603 * null, the task instance is added, anyway and 604 * {@link #containsSymbol(Object)} will return true for that task instance. 605 * Adding the same task instance twice will produce two entries. This is 606 * contradictory to typical map implementations. To prevent this, the 607 * {@link #containsSymbol(Object)} and {@link #removeSymbol(Object)} methods 608 * should be used to ensure map behavior. 609 * </p> 610 * 611 * @param symbol 612 * the task instance to add to the map 613 * @param value 614 * the value to associate to the task instance in this map 615 * 616 * @return as described 617 * 618 * @throws IllegalArgumentException 619 * if the provided task instance is null 620 */ 621 @Override 622 public void addSymbol(ITaskInstance symbol, V value) { 623 if (symbol == null) { 624 throw new IllegalArgumentException("symbol must not be null"); 625 } 626 627 final Map.Entry<ITaskInstance, V> entry = new SymbolMapEntry(symbol, 628 value); 629 630 symbolList.add(entry); 631 632 if (symbolList.size() > MAX_LIST_SIZE) { 633 if (symbolBuckets == null) { 634 createSymbolBuckets(); 635 } else { 636 addToSymbolBucket(entry); 637 } 638 } 639 } 640 641 /** 642 * <p> 643 * Adds a task instance and its value to its corresponding bucket. The 644 * corresponding bucket is the first element of the array returned by the 645 * method {@link #getBucketSearchOrder(ITaskInstance)}. If no search order 646 * for a task instance is defined, the entry is added to the default bucket. 647 * If the bucket id identical to the default bucket id, the default bucket 648 * id is shifted to another value. 649 * </p> 650 */ 651 private void addToSymbolBucket(Map.Entry<ITaskInstance, V> symbolEntry) { 652 int bucketId = defaultBucket; 653 final int[] bucketSearchOrder = getBucketSearchOrder(symbolEntry 654 .getKey()); 655 656 if ((bucketSearchOrder != null) && (bucketSearchOrder.length > 0)) { 657 bucketId = bucketSearchOrder[0]; 658 659 if (bucketId == defaultBucket) { 660 setNewDefaultBucketId(); 661 } 662 } 663 664 List<Map.Entry<ITaskInstance, V>> list = symbolBuckets.get(bucketId); 665 666 if (list == null) { 667 list = new LinkedList<Map.Entry<ITaskInstance, V>>(); 668 symbolBuckets.put(bucketId, list); 669 } 670 671 list.add(symbolEntry); 672 } 673 674 /** 675 * <p> 676 * Removes all task instances and associated values from the map. 677 * </p> 678 */ 679 @Override 680 public void clear() { 681 symbolList.clear(); 682 symbolBuckets = null; 683 } 684 685 /** 686 * <p> 687 * Returns true if the provided task instance was stored in this map. 688 * </p> 689 * 690 * @param symbol 691 * the task instance to check if it was stored in this map 692 * 693 * @return as described 694 * 695 * @throws IllegalArgumentException 696 * if the provided task instance is null 697 */ 698 @Override 699 public boolean containsSymbol(ITaskInstance symbol) { 700 if (symbol == null) { 701 throw new IllegalArgumentException("symbol must not be null"); 702 } 703 704 return getEntry(symbol) != null; 705 } 706 707 /** 708 * <p> 709 * Internally used to create task instance buckets in case the number of 710 * stored task instances increased above {@link #MAX_LIST_SIZE}. 711 * </p> 712 */ 713 private void createSymbolBuckets() { 714 // System.out.println("creating symbol buckets"); 715 symbolBuckets = new HashMap<Integer, List<Map.Entry<ITaskInstance, V>>>(); 716 717 for (final Map.Entry<ITaskInstance, V> symbol : symbolList) { 718 addToSymbolBucket(symbol); 719 } 720 } 721 722 /* 723 * (non-Javadoc) 724 * 725 * @see java.lang.Object#equals(java.lang.Object) 726 */ 727 @SuppressWarnings("unchecked") 728 @Override 729 public boolean equals(Object obj) { 730 if (this == obj) { 731 return true; 732 } else if (this.getClass().isInstance(obj)) { 733 final TaskSymbolBucketedMap<V> other = (TaskSymbolBucketedMap<V>) obj; 734 735 return (symbolList.size() == other.symbolList.size()) 736 && (symbolList.containsAll(other.symbolList)); 737 } else { 738 return false; 739 } 740 } 741 742 /** 743 * <p> 744 * returns the search order for a task instance which is different for event 745 * task instances, sequence instances, selection instances, and iteration 746 * instances 747 * </p> 748 */ 749 private int[] getBucketSearchOrder(ITaskInstance taskInstance) { 750 // 0 = sequence; 1 = selection; 2 = iteration; 3 = optional; 4 = event 751 // task in general; 752 // other = hashCode of name of event type 753 754 if (taskInstance instanceof IEventTaskInstance) { 755 // event tasks are most likely equal to those of the same type 756 // happening on the same 757 // target. Afterwards, they should be equal to those of the event 758 // type with the same 759 // name. Afterwards, they may be equal to iterations, optionals, 760 // other event tasks, 761 // selections, and finally the rest. 762 final Event event = ((IEventTaskInstance) taskInstance).getEvent(); 763 return new int[] { 764 event.getTarget().hashCode() 765 + event.getType().getName().hashCode(), 766 event.getType().getName().hashCode(), 2, 3, 4, 1 }; 767 } else if (taskInstance instanceof ISequenceInstance) { 768 return new int[] { 0, 2, 3, 1 }; 769 } else if (taskInstance instanceof ISelectionInstance) { 770 return new int[] { 1, 4, 2, 3 }; 771 } else if (taskInstance instanceof IIterationInstance) { 772 return new int[] { 2, 1, 4 }; 773 } 774 775 return null; 776 } 777 778 /** 779 * <p> 780 * searches for the entry belonging to the given task instance. The method 781 * either uses the list if buckets are not used yet, or it uses the buckets 782 * and searches them in the order defined by the method 783 * {@link #getBucketSearchOrder(ITaskInstance)}. If the task instances isn't 784 * found and the bucket search order does not refer all buckets, then also 785 * the other buckets are searched for the task instance. 786 * </p> 787 */ 788 private Map.Entry<ITaskInstance, V> getEntry(ITaskInstance symbol) { 789 Map.Entry<ITaskInstance, V> entry = null; 790 if (symbolBuckets == null) { 791 entry = lookup(symbol, symbolList); 792 } else { 793 final int[] bucketSearchOrder = getBucketSearchOrder(symbol); 794 for (final int bucketId : bucketSearchOrder) { 795 final List<Map.Entry<ITaskInstance, V>> list = symbolBuckets 796 .get(bucketId); 797 if (list != null) { 798 entry = lookup(symbol, list); 799 if (entry != null) { 800 break; 801 } 802 } 803 } 804 805 // try to search the other buckets 806 if (entry == null) { 807 Arrays.sort(bucketSearchOrder); 808 for (final Map.Entry<Integer, List<Map.Entry<ITaskInstance, V>>> bucket : symbolBuckets 809 .entrySet()) { 810 if (Arrays.binarySearch(bucketSearchOrder, bucket.getKey()) < 0) { 811 final List<Map.Entry<ITaskInstance, V>> list = bucket 812 .getValue(); 813 if (list != null) { 814 entry = lookup(symbol, list); 815 if (entry != null) { 816 break; 817 } 818 } 819 } 820 } 821 } 822 } 823 824 return entry; 825 } 826 827 /** 828 * <p> 829 * Returns a collection of all task instances in this map. 830 * </p> 831 * 832 * @return as described 833 */ 834 @Override 835 public Collection<ITaskInstance> getSymbols() { 836 return new ReadOnlyCollectionFacade<ITaskInstance>(symbolList, 837 new SymbolFacade()); 838 } 839 840 /** 841 * <p> 842 * Returns the value associated to the provided task instance in this map. 843 * If there is no value associated to the given task instance or if the task 844 * instance is not stored in this map, the method returns null. 845 * </p> 846 * 847 * @param symbol 848 * the task instance to return the value for 849 * 850 * @return as described 851 * 852 * @throws IllegalArgumentException 853 * if the provided task instance is null 854 */ 855 @Override 856 public V getValue(ITaskInstance symbol) { 857 if (symbol == null) { 858 throw new IllegalArgumentException("symbol must not be null"); 859 } 860 861 final Map.Entry<ITaskInstance, V> entry = getEntry(symbol); 862 863 if (entry != null) { 864 return entry.getValue(); 865 } else { 866 return null; 867 } 868 } 869 870 /** 871 * <p> 872 * Returns a collection of all values associated to task instances in this 873 * map. May contain null values, if some of the task instances are mapped to 874 * null. The length of the returned collection is in any case the same as 875 * the size of the map. 876 * </p> 877 * 878 * @return as described 879 */ 880 @Override 881 public Collection<V> getValues() { 882 return new ReadOnlyCollectionFacade<V>(symbolList, new ValueFacade()); 883 } 884 885 /* 886 * (non-Javadoc) 887 * 888 * @see java.lang.Object#hashCode() 889 */ 890 @Override 891 public int hashCode() { 892 return symbolList.size(); 893 } 894 895 /** 896 * <p> 897 * Returns true if this map is empty, i.e. if {@link #size()} returns 0 898 * </p> 899 * 900 * @return as described 901 */ 902 @Override 903 public boolean isEmpty() { 904 return symbolList.isEmpty(); 905 } 906 907 /** 908 * <p> 909 * Convenience method to look up a symbol in a list of entries using the 910 * comparator. 911 * </p> 912 */ 913 private Map.Entry<ITaskInstance, V> lookup(ITaskInstance symbol, 914 List<Map.Entry<ITaskInstance, V>> list) { 915 for (final Map.Entry<ITaskInstance, V> candidate : list) { 916 if (comparator.equals(candidate.getKey(), symbol)) { 917 return candidate; 918 } 919 } 920 921 return null; 922 } 923 924 /** 925 * <p> 926 * Removes the entry for a given task instance from the buckets. It uses the 927 * bucket search order defined to find the task instance as fast as 928 * possible. 929 * </p> 930 */ 931 private Map.Entry<ITaskInstance, V> removeFromSymbolBuckets( 932 ITaskInstance symbol) { 933 int bucketId = defaultBucket; 934 final int[] bucketSearchOrder = getBucketSearchOrder(symbol); 935 936 if ((bucketSearchOrder != null) && (bucketSearchOrder.length > 0)) { 937 bucketId = bucketSearchOrder[0]; 938 } 939 940 final List<Map.Entry<ITaskInstance, V>> list = symbolBuckets 941 .get(bucketId); 942 Map.Entry<ITaskInstance, V> result = null; 943 944 if (list != null) { 945 for (int i = 0; i < list.size(); i++) { 946 if (comparator.equals(list.get(i).getKey(), symbol)) { 947 result = list.remove(i); 948 break; 949 } 950 } 951 952 if (list.isEmpty()) { 953 symbolBuckets.remove(bucketId); 954 } 955 } 956 957 return result; 958 } 959 960 /** 961 * <p> 962 * Removes a task instance and its associated value from the map. If the 963 * task instance is stored several times, only the first of its occurrences 964 * is removed. 965 * </p> 966 * 967 * @param symbol 968 * the task instance to be removed from the map 969 * 970 * @return as described 971 * 972 * @throws IllegalArgumentException 973 * if the provided task instance is null 974 */ 975 @Override 976 public V removeSymbol(ITaskInstance symbol) { 977 if (symbol == null) { 978 throw new IllegalArgumentException("symbol must not be null"); 979 } 980 981 for (int i = 0; i < symbolList.size(); i++) { 982 if (comparator.equals(symbolList.get(i).getKey(), symbol)) { 983 // found the symbol. Remove it from the list, and if required, 984 // also from the map. 985 final V value = symbolList.remove(i).getValue(); 986 987 if (symbolList.size() > MAX_LIST_SIZE) { 988 removeFromSymbolBuckets(symbol); 989 } 990 991 return value; 992 } 993 } 994 995 return null; 996 } 997 998 /** 999 * <p> 1000 * Updates the default bucket id to a new one 1001 * </p> 1002 */ 1003 private void setNewDefaultBucketId() { 1004 final int oldDefaultBucket = defaultBucket; 1005 do { 1006 defaultBucket += 1; 1007 } while (symbolBuckets.containsKey(defaultBucket)); 1008 1009 symbolBuckets 1010 .put(defaultBucket, symbolBuckets.remove(oldDefaultBucket)); 1011 } 1012 1013 /** 1014 * <p> 1015 * Returns the size of the map, i.e. the number of task instance entries 1016 * </p> 1017 * 1018 * @return as described 1019 */ 1020 @Override 1021 public int size() { 1022 return symbolList.size(); 1023 } 919 1024 920 1025 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TaskSymbolIdentityMap.java
r1401 r1733 25 25 /** 26 26 * <p> 27 * symbol map implementation for task instances considering two task instances as equal if their28 * tasks are identical27 * symbol map implementation for task instances considering two task instances 28 * as equal if their tasks are identical 29 29 * </p> 30 30 * … … 33 33 public class TaskSymbolIdentityMap<V> implements SymbolMap<ITaskInstance, V> { 34 34 35 /** */ 36 private static final long serialVersionUID = 1L; 37 38 /** 39 * <p> 40 * internally used map for implementing the symbol map interface 41 * </p> 42 */ 43 private Map<ITask, V> delegate; 44 45 /** 46 * <p> 47 * mapping between the tasks and the real symbols stored in the map, i.e. the task instances 48 * </p> 49 */ 50 private Map<ITask, ITaskInstance> symbols; 51 52 /** 53 * <p> 54 * initializes this map 55 * </p> 56 */ 57 public TaskSymbolIdentityMap() { 58 delegate = new HashMap<ITask, V>(); 59 symbols = new HashMap<ITask, ITaskInstance>(); 60 } 61 62 /** 63 * <p> 64 * copy constructor 65 * </p> 66 * 67 * @param other the map to be copied 68 */ 69 public TaskSymbolIdentityMap(SymbolMap<ITaskInstance, V> other) { 70 if (other == null) { 71 throw new IllegalArgumentException("other map must not be null"); 72 } 73 74 delegate = new HashMap<ITask, V>(); 75 symbols = new HashMap<ITask, ITaskInstance>(); 76 77 for (ITaskInstance symbol : other.getSymbols()) { 78 delegate.put(symbol.getTask(), other.getValue(symbol)); 79 symbols.put(symbol.getTask(), symbol); 80 } 81 } 82 83 /* (non-Javadoc) 84 * @see de.ugoe.cs.autoquest.usageprofiles.SymbolMap#size() 85 */ 86 @Override 87 public int size() { 88 return delegate.size(); 89 } 90 91 /* (non-Javadoc) 92 * @see de.ugoe.cs.autoquest.usageprofiles.SymbolMap#isEmpty() 93 */ 94 @Override 95 public boolean isEmpty() { 96 return delegate.isEmpty(); 97 } 98 99 /* (non-Javadoc) 100 * @see de.ugoe.cs.autoquest.usageprofiles.SymbolMap#containsSymbol(java.lang.Object) 101 */ 102 @Override 103 public boolean containsSymbol(ITaskInstance symbol) { 104 if (symbol == null) { 105 throw new IllegalArgumentException("symbol must not be null"); 106 } 107 108 return delegate.containsKey(symbol.getTask()); 109 } 110 111 /* (non-Javadoc) 112 * @see de.ugoe.cs.autoquest.usageprofiles.SymbolMap#getValue(java.lang.Object) 113 */ 114 @Override 115 public V getValue(ITaskInstance symbol) { 116 if (symbol == null) { 117 throw new IllegalArgumentException("symbol must not be null"); 118 } 119 120 return delegate.get(symbol.getTask()); 121 } 122 123 /* (non-Javadoc) 124 * @see de.ugoe.cs.autoquest.usageprofiles.SymbolMap#addSymbol(java.lang.Object, java.lang.Object) 125 */ 126 @Override 127 public void addSymbol(ITaskInstance symbol, V value) { 128 if (symbol == null) { 129 throw new IllegalArgumentException("symbol must not be null"); 130 } 131 132 delegate.put(symbol.getTask(), value); 133 symbols.put(symbol.getTask(), symbol); 134 } 135 136 /* (non-Javadoc) 137 * @see de.ugoe.cs.autoquest.usageprofiles.SymbolMap#removeSymbol(java.lang.Object) 138 */ 139 @Override 140 public V removeSymbol(ITaskInstance symbol) { 141 if (symbol == null) { 142 throw new IllegalArgumentException("symbol must not be null"); 143 } 144 145 symbols.remove(symbol.getTask()); 146 return delegate.remove(symbol.getTask()); 147 } 148 149 /* (non-Javadoc) 150 * @see de.ugoe.cs.autoquest.usageprofiles.SymbolMap#getSymbols() 151 */ 152 @Override 153 public Collection<ITaskInstance> getSymbols() { 154 return symbols.values(); 155 } 156 157 /* (non-Javadoc) 158 * @see de.ugoe.cs.autoquest.usageprofiles.SymbolMap#getValues() 159 */ 160 @Override 161 public Collection<V> getValues() { 162 return delegate.values(); 163 } 164 165 /* (non-Javadoc) 166 * @see de.ugoe.cs.autoquest.usageprofiles.SymbolMap#clear() 167 */ 168 @Override 169 public void clear() { 170 delegate.clear(); 171 } 172 173 /* (non-Javadoc) 174 * @see java.lang.Object#hashCode() 175 */ 176 @Override 177 public int hashCode() { 178 return delegate.hashCode(); 179 } 180 181 /* (non-Javadoc) 182 * @see java.lang.Object#equals(java.lang.Object) 183 */ 184 @SuppressWarnings("unchecked") 185 @Override 186 public boolean equals(Object obj) { 187 if (this == obj) { 188 return true; 189 } 190 else if (this.getClass().isInstance(obj)) { 191 return delegate.equals(((TaskSymbolIdentityMap<V>) obj).delegate); 192 } 193 else { 194 return false; 195 } 196 } 35 /** */ 36 private static final long serialVersionUID = 1L; 37 38 /** 39 * <p> 40 * internally used map for implementing the symbol map interface 41 * </p> 42 */ 43 private final Map<ITask, V> delegate; 44 45 /** 46 * <p> 47 * mapping between the tasks and the real symbols stored in the map, i.e. 48 * the task instances 49 * </p> 50 */ 51 private final Map<ITask, ITaskInstance> symbols; 52 53 /** 54 * <p> 55 * initializes this map 56 * </p> 57 */ 58 public TaskSymbolIdentityMap() { 59 delegate = new HashMap<ITask, V>(); 60 symbols = new HashMap<ITask, ITaskInstance>(); 61 } 62 63 /** 64 * <p> 65 * copy constructor 66 * </p> 67 * 68 * @param other 69 * the map to be copied 70 */ 71 public TaskSymbolIdentityMap(SymbolMap<ITaskInstance, V> other) { 72 if (other == null) { 73 throw new IllegalArgumentException("other map must not be null"); 74 } 75 76 delegate = new HashMap<ITask, V>(); 77 symbols = new HashMap<ITask, ITaskInstance>(); 78 79 for (final ITaskInstance symbol : other.getSymbols()) { 80 delegate.put(symbol.getTask(), other.getValue(symbol)); 81 symbols.put(symbol.getTask(), symbol); 82 } 83 } 84 85 /* 86 * (non-Javadoc) 87 * 88 * @see 89 * de.ugoe.cs.autoquest.usageprofiles.SymbolMap#addSymbol(java.lang.Object, 90 * java.lang.Object) 91 */ 92 @Override 93 public void addSymbol(ITaskInstance symbol, V value) { 94 if (symbol == null) { 95 throw new IllegalArgumentException("symbol must not be null"); 96 } 97 98 delegate.put(symbol.getTask(), value); 99 symbols.put(symbol.getTask(), symbol); 100 } 101 102 /* 103 * (non-Javadoc) 104 * 105 * @see de.ugoe.cs.autoquest.usageprofiles.SymbolMap#clear() 106 */ 107 @Override 108 public void clear() { 109 delegate.clear(); 110 } 111 112 /* 113 * (non-Javadoc) 114 * 115 * @see 116 * de.ugoe.cs.autoquest.usageprofiles.SymbolMap#containsSymbol(java.lang 117 * .Object) 118 */ 119 @Override 120 public boolean containsSymbol(ITaskInstance symbol) { 121 if (symbol == null) { 122 throw new IllegalArgumentException("symbol must not be null"); 123 } 124 125 return delegate.containsKey(symbol.getTask()); 126 } 127 128 /* 129 * (non-Javadoc) 130 * 131 * @see java.lang.Object#equals(java.lang.Object) 132 */ 133 @SuppressWarnings("unchecked") 134 @Override 135 public boolean equals(Object obj) { 136 if (this == obj) { 137 return true; 138 } else if (this.getClass().isInstance(obj)) { 139 return delegate.equals(((TaskSymbolIdentityMap<V>) obj).delegate); 140 } else { 141 return false; 142 } 143 } 144 145 /* 146 * (non-Javadoc) 147 * 148 * @see de.ugoe.cs.autoquest.usageprofiles.SymbolMap#getSymbols() 149 */ 150 @Override 151 public Collection<ITaskInstance> getSymbols() { 152 return symbols.values(); 153 } 154 155 /* 156 * (non-Javadoc) 157 * 158 * @see 159 * de.ugoe.cs.autoquest.usageprofiles.SymbolMap#getValue(java.lang.Object) 160 */ 161 @Override 162 public V getValue(ITaskInstance symbol) { 163 if (symbol == null) { 164 throw new IllegalArgumentException("symbol must not be null"); 165 } 166 167 return delegate.get(symbol.getTask()); 168 } 169 170 /* 171 * (non-Javadoc) 172 * 173 * @see de.ugoe.cs.autoquest.usageprofiles.SymbolMap#getValues() 174 */ 175 @Override 176 public Collection<V> getValues() { 177 return delegate.values(); 178 } 179 180 /* 181 * (non-Javadoc) 182 * 183 * @see java.lang.Object#hashCode() 184 */ 185 @Override 186 public int hashCode() { 187 return delegate.hashCode(); 188 } 189 190 /* 191 * (non-Javadoc) 192 * 193 * @see de.ugoe.cs.autoquest.usageprofiles.SymbolMap#isEmpty() 194 */ 195 @Override 196 public boolean isEmpty() { 197 return delegate.isEmpty(); 198 } 199 200 /* 201 * (non-Javadoc) 202 * 203 * @see 204 * de.ugoe.cs.autoquest.usageprofiles.SymbolMap#removeSymbol(java.lang.Object 205 * ) 206 */ 207 @Override 208 public V removeSymbol(ITaskInstance symbol) { 209 if (symbol == null) { 210 throw new IllegalArgumentException("symbol must not be null"); 211 } 212 213 symbols.remove(symbol.getTask()); 214 return delegate.remove(symbol.getTask()); 215 } 216 217 /* 218 * (non-Javadoc) 219 * 220 * @see de.ugoe.cs.autoquest.usageprofiles.SymbolMap#size() 221 */ 222 @Override 223 public int size() { 224 return delegate.size(); 225 } 197 226 198 227 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TemporalRelationshipRuleManager.java
r1552 r1733 33 33 * 34 34 * <p> 35 * This class is responsible for applying temporal relationship rules on a task tree. Through this, 36 * a flat task tree is restructured to have more depth but to include more temporal relationships 37 * between tasks which are not only a major sequence. I.e. through the application of the 38 * rules iterations and selections of tasks are detected. Which kind of temporal relations 39 * between tasks are detected depends on the {@link ITaskInstanceScopeRule}s known to 35 * This class is responsible for applying temporal relationship rules on a task 36 * tree. Through this, a flat task tree is restructured to have more depth but 37 * to include more temporal relationships between tasks which are not only a 38 * major sequence. I.e. through the application of the rules iterations and 39 * selections of tasks are detected. Which kind of temporal relations between 40 * tasks are detected depends on the {@link ITaskInstanceScopeRule}s known to 40 41 * this class. 41 42 * </p> 42 * <p>The class holds references to the appropriate {@link ITaskInstanceScopeRule}s and calls 43 * their {@link ITaskInstanceScopeRule#apply(ITask, ITaskBuilder, ITaskFactory, boolean)} 44 * method for each task in the task tree it is needed for. The general behavior of this class is 45 * the following: 43 * <p> 44 * The class holds references to the appropriate {@link ITaskInstanceScopeRule}s 45 * and calls their 46 * {@link ITaskInstanceScopeRule#apply(ITask, ITaskBuilder, ITaskFactory, boolean)} 47 * method for each task in the task tree it is needed for. The general behavior 48 * of this class is the following: 46 49 * <ol> 47 * <li> 48 * An instance of this class is created using the constructor and calling the 49 * {@link #init()} method afterwards 50 * </li> 51 * <li> 52 * then the {@link #applyRules(ITask, ITaskBuilder, ITaskFactory, boolean)} 53 * method is called for a so far unstructured task 54 * </li> 55 * <li> 56 * the class iterates its internal list of rules and calls their 57 * {@link ITaskInstanceScopeRule#apply(ITask, ITaskBuilder, ITaskFactory, boolean)} 58 * method. 59 * </li> 60 * <li> 61 * the class evaluates the rule application result 62 * <ul> 63 * <li> 64 * if a rule returns a rule application result that is null, the next rule is tried 65 * </li> 66 * <li> 67 * if a rule returns that it would be feasible if more data was available and the rule 68 * application shall not be finalized (see finalize parameter of the applyRules method) 69 * the rule application is broken up 70 * </li> 71 * <li> 72 * if a rule returns, that it was applied, the same rule is applied again until it returns 73 * null or feasible. For each newly created parent task provided in the rule application 74 * result, the {@link #applyRules(ITask, ITaskBuilder, ITaskFactory, boolean)} 75 * method is called. 76 * </li> 77 * </ul> 78 * </li> 50 * <li> 51 * An instance of this class is created using the constructor and calling the 52 * {@link #init()} method afterwards</li> 53 * <li> 54 * then the {@link #applyRules(ITask, ITaskBuilder, ITaskFactory, boolean)} 55 * method is called for a so far unstructured task</li> 56 * <li> 57 * the class iterates its internal list of rules and calls their 58 * {@link ITaskInstanceScopeRule#apply(ITask, ITaskBuilder, ITaskFactory, boolean)} 59 * method.</li> 60 * <li> 61 * the class evaluates the rule application result 62 * <ul> 63 * <li> 64 * if a rule returns a rule application result that is null, the next rule is 65 * tried</li> 66 * <li> 67 * if a rule returns that it would be feasible if more data was available and 68 * the rule application shall not be finalized (see finalize parameter of the 69 * applyRules method) the rule application is broken up</li> 70 * <li> 71 * if a rule returns, that it was applied, the same rule is applied again until 72 * it returns null or feasible. For each newly created parent task provided in 73 * the rule application result, the 74 * {@link #applyRules(ITask, ITaskBuilder, ITaskFactory, boolean)} method is 75 * called.</li> 76 * </ul> 77 * </li> 79 78 * </ol> 80 * Through this, all rules are tried to be applied at least once to the provided parent task and81 * all parent tasks created during the rule application.79 * Through this, all rules are tried to be applied at least once to the provided 80 * parent task and all parent tasks created during the rule application. 82 81 * </p> 83 82 * … … 85 84 */ 86 85 public class TemporalRelationshipRuleManager { 87 88 /** 89 * <p> 90 * the task factory to be used during rule application 91 * </p> 92 */ 93 private ITaskFactory taskFactory; 94 95 /** 96 * <p> 97 * the task builder to be used during rule application 98 * </p> 99 */ 100 private ITaskBuilder taskBuilder; 101 102 /** 103 * <p> 104 * the temporal relationship rules known to the manager that are executed on whole sessions. 105 * The rules are applied in the order they occur in this list. 106 * </p> 107 */ 108 private ISessionScopeRule[] sessionScopeRules; 109 110 /** 111 * <p> 112 * the temporal relationship rules known to the manager that are executed on whole sub trees. 113 * The rules are applied in the order they occur in this list. 114 * </p> 115 */ 116 private ITaskInstanceScopeRule[] taskScopeRules; 117 118 /** 119 * <p> 120 * initialize the manager 121 * </p> 122 * 123 * @param taskFactory the task factory to be used for instantiating new task tree 124 * tasks during rule application 125 * @param taskBuilder the task builder to be used for linking tasks 126 * with each other during rule application 127 */ 128 public TemporalRelationshipRuleManager(ITaskFactory taskFactory, ITaskBuilder taskBuilder) { 129 super(); 130 this.taskFactory = taskFactory; 131 this.taskBuilder = taskBuilder; 132 } 133 134 /** 135 * <p> 136 * initialized the temporal relationship rule manager by instantiating the known rules and 137 * providing them with a reference to the task equality manager or other information they need. 138 * </p> 139 */ 140 public void init() { 141 List<Class<? extends IGUIElement>> frameFilter = 142 new ArrayList<Class<? extends IGUIElement>>(); 143 frameFilter.add(IFrame.class); 144 frameFilter.add(IDialog.class); 145 //frameFilter.add(ICanvas.class); 146 147 sessionScopeRules = new ISessionScopeRule[] { 148 new SequenceForTaskDetectionRuleAlignment 149 (TaskEquality.SEMANTICALLY_EQUAL, taskFactory, taskBuilder), 150 /*new DefaultTaskSequenceDetectionRule 151 (NodeEquality.SYNTACTICALLY_EQUAL, taskFactory, taskTreeBuilder), 152 new DefaultTaskSequenceDetectionRule 153 (NodeEquality.LEXICALLY_EQUAL, taskFactory, taskTreeBuilder),*/ 154 /*new TreeScopeWrapperRule 155 (new DefaultIterationDetectionRule 156 (NodeEquality.LEXICALLY_EQUAL, taskFactory, taskTreeBuilder)), 157 new TreeScopeWrapperRule 158 (new DefaultIterationDetectionRule 159 (NodeEquality.SYNTACTICALLY_EQUAL, taskFactory, taskTreeBuilder)), 160 new TreeScopeWrapperRule 161 (new DefaultIterationDetectionRule 162 (NodeEquality.SEMANTICALLY_EQUAL, taskFactory, taskTreeBuilder))*/ 163 }; 164 165 //treeScopeRules.add(new DefaultGuiElementSequenceDetectionRule(frameFilter)); 166 167 taskScopeRules = new ITaskInstanceScopeRule[] { 168 //new SequenceOnGuiElementDetectionRule(taskFactory, taskTreeBuilder), 169 //new EventSequenceOnSameTargetDetectionRule(taskFactory, taskTreeBuilder), 170 //new TrackBarSelectionDetectionRule(taskFactory, taskBuilder), 171 //new DefaultGuiEventSequenceDetectionRule(taskFactory, taskTreeBuilder), 172 }; 173 174 } 175 176 /** 177 * <p> 178 * applies the known rules to the provided sessions. For the creation of further tasks, 179 * the provided builder and task factory are utilized. The method expects, that no more data 180 * is available and, therefore, finalizes the rule application. 181 * </p> 182 * 183 * @param taskFactory the task factory to be used for instantiating new tasks. 184 */ 185 public void applyRules(List<IUserSession> sessions) { 186 applyRules(sessionScopeRules, sessions, ""); 187 } 188 189 /** 190 * <p> 191 * applies the known rules to the provided parent task. For the creation of further tasks, 192 * the provided builder and task factory are utilized. If the finalize parameter is true, the 193 * rule application is finalized as far as possible without waiting for further data. If it is 194 * false, the rule application is broken up at the first rule returning, that its application 195 * would be feasible. The method calls itself for each parent task created through the rule 196 * application. In this case, the finalize parameter is always true. 197 * </p> 198 * 199 * @param parent the parent task to apply the rules on 200 * @param finalize used to indicate, if the rule application shall break up if a rule would 201 * be feasible if further data was available, or not. 202 * @param logIndent simply used for logging purposes to indent the log messages depending 203 * on the recursion depth of calling this method. 204 */ 205 private int applyRules(ISessionScopeRule[] rules, 206 List<IUserSession> sessions, 207 String logIndent) 208 { 209 Console.traceln 210 (Level.FINER, logIndent + "applying rules for " + sessions.size() + " sessions"); 211 212 int noOfRuleApplications = 0; 213 214 for (ISessionScopeRule rule : rules) { 215 RuleApplicationResult result; 216 do { 217 Console.traceln(Level.FINER, logIndent + "trying rule " + rule); 218 result = rule.apply(sessions); 219 220 if ((result != null) && 221 (result.getRuleApplicationStatus() == RuleApplicationStatus.FINISHED)) 222 { 223 Console.traceln(Level.FINE, logIndent + "applied rule " + rule); 224 noOfRuleApplications++; 225 226 //dumpTask(parent, ""); 227 228 for (ITaskInstance newParent : result.getNewlyCreatedTaskInstances()) { 229 noOfRuleApplications += 230 applyRules(taskScopeRules, newParent, logIndent + " "); 231 } 232 } 233 } 234 while ((result != null) && 235 (result.getRuleApplicationStatus() == RuleApplicationStatus.FINISHED)); 236 237 } 238 239 if (noOfRuleApplications <= 0) { 240 Console.traceln(Level.FINE, logIndent + "no rules applied --> no temporal " + 241 "relationship generated"); 242 } 243 244 return noOfRuleApplications; 245 } 246 247 /** 248 * <p> 249 * applies the known rules to the provided parent task. For the creation of further tasks, 250 * the provided builder and task factory are utilized. If the finalize parameter is true, the 251 * rule application is finalized as far as possible without waiting for further data. If it is 252 * false, the rule application is broken up at the first rule returning, that its application 253 * would be feasible. The method calls itself for each parent task created through the rule 254 * application. In this case, the finalize parameter is always true. 255 * </p> 256 * 257 * @param parent the parent task to apply the rules on 258 * @param finalize used to indicate, if the rule application shall break up if a rule would 259 * be feasible if further data was available, or not. 260 * @param logIndent simply used for logging purposes to indent the log messages depending 261 * on the recursion depth of calling this method. 262 */ 263 private int applyRules(ITaskInstanceScopeRule[] rules, 264 ITaskInstance taskInstance, 265 String logIndent) 266 { 267 Console.traceln(Level.FINER, logIndent + "applying rules on " + taskInstance); 268 269 int noOfRuleApplications = 0; 270 271 for (ITaskInstanceScopeRule rule : rules) { 272 RuleApplicationResult result; 273 do { 274 Console.traceln 275 (Level.FINER, logIndent + "trying rule " + rule + " on " + taskInstance); 276 result = rule.apply(taskInstance); 277 278 if ((result != null) && 279 (result.getRuleApplicationStatus() == RuleApplicationStatus.FINISHED)) 280 { 281 Console.traceln 282 (Level.FINE, logIndent + "applied rule " + rule + " on " + taskInstance); 283 noOfRuleApplications++; 284 285 //dumpTask(parent, ""); 286 287 for (ITaskInstance newParent : result.getNewlyCreatedTaskInstances()) { 288 noOfRuleApplications += 289 applyRules(taskScopeRules, newParent, logIndent + " "); 290 } 291 } 292 } 293 while ((result != null) && 294 (result.getRuleApplicationStatus() == RuleApplicationStatus.FINISHED)); 295 } 296 297 if (noOfRuleApplications <= 0) { 298 Console.traceln(Level.FINE, logIndent + "no rules applied --> no temporal " + 299 "relationship generated"); 300 } 301 302 return noOfRuleApplications; 303 } 304 305 /** 306 * 307 */ 308 /*private void dumpTask(ITask task, String indent) { 309 StringBuffer message = new StringBuffer(); 310 message.append(indent); 311 message.append(task); 312 if (task.getDescription() != null) { 313 message.append('('); 314 message.append(task.getDescription()); 315 message.append(')'); 316 } 317 318 Console.traceln(Level.FINER, message.toString()); 319 320 if ((task.getChildren() != null) && (task.getChildren().size() > 0)) { 321 for (ITask child : task.getChildren()) { 322 dumpTask(child, indent + " "); 323 } 324 } 325 }*/ 86 87 /** 88 * <p> 89 * the task factory to be used during rule application 90 * </p> 91 */ 92 private final ITaskFactory taskFactory; 93 94 /** 95 * <p> 96 * the task builder to be used during rule application 97 * </p> 98 */ 99 private final ITaskBuilder taskBuilder; 100 101 /** 102 * <p> 103 * the temporal relationship rules known to the manager that are executed on 104 * whole sessions. The rules are applied in the order they occur in this 105 * list. 106 * </p> 107 */ 108 private ISessionScopeRule[] sessionScopeRules; 109 110 /** 111 * <p> 112 * the temporal relationship rules known to the manager that are executed on 113 * whole sub trees. The rules are applied in the order they occur in this 114 * list. 115 * </p> 116 */ 117 private ITaskInstanceScopeRule[] taskScopeRules; 118 119 /** 120 * <p> 121 * initialize the manager 122 * </p> 123 * 124 * @param taskFactory 125 * the task factory to be used for instantiating new task tree 126 * tasks during rule application 127 * @param taskBuilder 128 * the task builder to be used for linking tasks with each other 129 * during rule application 130 */ 131 public TemporalRelationshipRuleManager(ITaskFactory taskFactory, 132 ITaskBuilder taskBuilder) { 133 super(); 134 this.taskFactory = taskFactory; 135 this.taskBuilder = taskBuilder; 136 } 137 138 /** 139 * <p> 140 * applies the known rules to the provided parent task. For the creation of 141 * further tasks, the provided builder and task factory are utilized. If the 142 * finalize parameter is true, the rule application is finalized as far as 143 * possible without waiting for further data. If it is false, the rule 144 * application is broken up at the first rule returning, that its 145 * application would be feasible. The method calls itself for each parent 146 * task created through the rule application. In this case, the finalize 147 * parameter is always true. 148 * </p> 149 * 150 * @param parent 151 * the parent task to apply the rules on 152 * @param finalize 153 * used to indicate, if the rule application shall break up if a 154 * rule would be feasible if further data was available, or not. 155 * @param logIndent 156 * simply used for logging purposes to indent the log messages 157 * depending on the recursion depth of calling this method. 158 */ 159 private int applyRules(ISessionScopeRule[] rules, 160 List<IUserSession> sessions, String logIndent) { 161 Console.traceln(Level.FINER, logIndent + "applying rules for " 162 + sessions.size() + " sessions"); 163 164 int noOfRuleApplications = 0; 165 166 for (final ISessionScopeRule rule : rules) { 167 RuleApplicationResult result; 168 do { 169 Console.traceln(Level.FINER, logIndent + "trying rule " + rule); 170 result = rule.apply(sessions); 171 172 if ((result != null) 173 && (result.getRuleApplicationStatus() == RuleApplicationStatus.FINISHED)) { 174 Console.traceln(Level.FINE, logIndent + "applied rule " 175 + rule); 176 noOfRuleApplications++; 177 178 // dumpTask(parent, ""); 179 180 for (final ITaskInstance newParent : result 181 .getNewlyCreatedTaskInstances()) { 182 noOfRuleApplications += applyRules(taskScopeRules, 183 newParent, logIndent + " "); 184 } 185 } 186 } while ((result != null) 187 && (result.getRuleApplicationStatus() == RuleApplicationStatus.FINISHED)); 188 189 } 190 191 if (noOfRuleApplications <= 0) { 192 Console.traceln(Level.FINE, logIndent 193 + "no rules applied --> no temporal " 194 + "relationship generated"); 195 } 196 197 return noOfRuleApplications; 198 } 199 200 /** 201 * <p> 202 * applies the known rules to the provided parent task. For the creation of 203 * further tasks, the provided builder and task factory are utilized. If the 204 * finalize parameter is true, the rule application is finalized as far as 205 * possible without waiting for further data. If it is false, the rule 206 * application is broken up at the first rule returning, that its 207 * application would be feasible. The method calls itself for each parent 208 * task created through the rule application. In this case, the finalize 209 * parameter is always true. 210 * </p> 211 * 212 * @param parent 213 * the parent task to apply the rules on 214 * @param finalize 215 * used to indicate, if the rule application shall break up if a 216 * rule would be feasible if further data was available, or not. 217 * @param logIndent 218 * simply used for logging purposes to indent the log messages 219 * depending on the recursion depth of calling this method. 220 */ 221 private int applyRules(ITaskInstanceScopeRule[] rules, 222 ITaskInstance taskInstance, String logIndent) { 223 Console.traceln(Level.FINER, logIndent + "applying rules on " 224 + taskInstance); 225 226 int noOfRuleApplications = 0; 227 228 for (final ITaskInstanceScopeRule rule : rules) { 229 RuleApplicationResult result; 230 do { 231 Console.traceln(Level.FINER, logIndent + "trying rule " + rule 232 + " on " + taskInstance); 233 result = rule.apply(taskInstance); 234 235 if ((result != null) 236 && (result.getRuleApplicationStatus() == RuleApplicationStatus.FINISHED)) { 237 Console.traceln(Level.FINE, logIndent + "applied rule " 238 + rule + " on " + taskInstance); 239 noOfRuleApplications++; 240 241 // dumpTask(parent, ""); 242 243 for (final ITaskInstance newParent : result 244 .getNewlyCreatedTaskInstances()) { 245 noOfRuleApplications += applyRules(taskScopeRules, 246 newParent, logIndent + " "); 247 } 248 } 249 } while ((result != null) 250 && (result.getRuleApplicationStatus() == RuleApplicationStatus.FINISHED)); 251 } 252 253 if (noOfRuleApplications <= 0) { 254 Console.traceln(Level.FINE, logIndent 255 + "no rules applied --> no temporal " 256 + "relationship generated"); 257 } 258 259 return noOfRuleApplications; 260 } 261 262 /** 263 * <p> 264 * applies the known rules to the provided sessions. For the creation of 265 * further tasks, the provided builder and task factory are utilized. The 266 * method expects, that no more data is available and, therefore, finalizes 267 * the rule application. 268 * </p> 269 * 270 * @param taskFactory 271 * the task factory to be used for instantiating new tasks. 272 */ 273 public void applyRules(List<IUserSession> sessions) { 274 applyRules(sessionScopeRules, sessions, ""); 275 } 276 277 /** 278 * <p> 279 * initialized the temporal relationship rule manager by instantiating the 280 * known rules and providing them with a reference to the task equality 281 * manager or other information they need. 282 * </p> 283 */ 284 public void init() { 285 final List<Class<? extends IGUIElement>> frameFilter = new ArrayList<Class<? extends IGUIElement>>(); 286 frameFilter.add(IFrame.class); 287 frameFilter.add(IDialog.class); 288 // frameFilter.add(ICanvas.class); 289 290 sessionScopeRules = new ISessionScopeRule[] { new SequenceForTaskDetectionRuleAlignment( 291 TaskEquality.SEMANTICALLY_EQUAL, taskFactory, taskBuilder), 292 /* 293 * new DefaultTaskSequenceDetectionRule 294 * (NodeEquality.SYNTACTICALLY_EQUAL, taskFactory, taskTreeBuilder), new 295 * DefaultTaskSequenceDetectionRule (NodeEquality.LEXICALLY_EQUAL, 296 * taskFactory, taskTreeBuilder), 297 */ 298 /* 299 * new TreeScopeWrapperRule (new DefaultIterationDetectionRule 300 * (NodeEquality.LEXICALLY_EQUAL, taskFactory, taskTreeBuilder)), new 301 * TreeScopeWrapperRule (new DefaultIterationDetectionRule 302 * (NodeEquality.SYNTACTICALLY_EQUAL, taskFactory, taskTreeBuilder)), 303 * new TreeScopeWrapperRule (new DefaultIterationDetectionRule 304 * (NodeEquality.SEMANTICALLY_EQUAL, taskFactory, taskTreeBuilder)) 305 */ 306 }; 307 308 // treeScopeRules.add(new 309 // DefaultGuiElementSequenceDetectionRule(frameFilter)); 310 311 taskScopeRules = new ITaskInstanceScopeRule[] { 312 // new SequenceOnGuiElementDetectionRule(taskFactory, taskTreeBuilder), 313 // new EventSequenceOnSameTargetDetectionRule(taskFactory, 314 // taskTreeBuilder), 315 // new TrackBarSelectionDetectionRule(taskFactory, taskBuilder), 316 // new DefaultGuiEventSequenceDetectionRule(taskFactory, 317 // taskTreeBuilder), 318 }; 319 320 } 321 322 /** 323 * 324 */ 325 /* 326 * private void dumpTask(ITask task, String indent) { StringBuffer message = 327 * new StringBuffer(); message.append(indent); message.append(task); if 328 * (task.getDescription() != null) { message.append('('); 329 * message.append(task.getDescription()); message.append(')'); } 330 * 331 * Console.traceln(Level.FINER, message.toString()); 332 * 333 * if ((task.getChildren() != null) && (task.getChildren().size() > 0)) { 334 * for (ITask child : task.getChildren()) { dumpTask(child, indent + " "); 335 * } } } 336 */ 326 337 327 338 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/DefaultTaskInstanceTraversingVisitor.java
r1406 r1733 17 17 /** 18 18 * <p> 19 * Default implementation for a task instance visitor performing a traversal of the instances 19 * Default implementation for a task instance visitor performing a traversal of 20 * the instances 20 21 * </p> 21 22 * 22 23 * @author Patrick Harms 23 24 */ 24 public class DefaultTaskInstanceTraversingVisitor implements ITaskInstanceVisitor { 25 public class DefaultTaskInstanceTraversingVisitor implements 26 ITaskInstanceVisitor { 25 27 26 /* (non-Javadoc) 27 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceVisitor#visit(IEventTaskInstance) 28 */ 29 @Override 30 public void visit(IEventTaskInstance eventTaskInstance) { 31 // do nothing 32 } 28 /* 29 * (non-Javadoc) 30 * 31 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceVisitor#visit( 32 * IEventTaskInstance) 33 */ 34 @Override 35 public void visit(IEventTaskInstance eventTaskInstance) { 36 // do nothing 37 } 33 38 34 /* (non-Javadoc) 35 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceVisitor#visit(IIterationInstance) 36 */ 37 @Override 38 public void visit(IIterationInstance iterationInstance) { 39 visit((ITaskInstanceList) iterationInstance); 40 } 39 /* 40 * (non-Javadoc) 41 * 42 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceVisitor#visit( 43 * IIterationInstance) 44 */ 45 @Override 46 public void visit(IIterationInstance iterationInstance) { 47 visit((ITaskInstanceList) iterationInstance); 48 } 41 49 42 /* (non-Javadoc) 43 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceVisitor#visit(IOptionalInstance) 44 */ 45 @Override 46 public void visit(IOptionalInstance optionalInstance) { 47 if (optionalInstance.getChild() != null) { 48 optionalInstance.getChild().accept(this); 49 } 50 } 50 /* 51 * (non-Javadoc) 52 * 53 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceVisitor#visit( 54 * IOptionalInstance) 55 */ 56 @Override 57 public void visit(IOptionalInstance optionalInstance) { 58 if (optionalInstance.getChild() != null) { 59 optionalInstance.getChild().accept(this); 60 } 61 } 51 62 52 /* (non-Javadoc) 53 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceVisitor#visit(ISelectionInstance) 54 */ 55 @Override 56 public void visit(ISelectionInstance selectionInstance) { 57 selectionInstance.getChild().accept(this); 58 } 63 /* 64 * (non-Javadoc) 65 * 66 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceVisitor#visit( 67 * ISelectionInstance) 68 */ 69 @Override 70 public void visit(ISelectionInstance selectionInstance) { 71 selectionInstance.getChild().accept(this); 72 } 59 73 60 /* (non-Javadoc) 61 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceVisitor#visit(ISequenceInstance) 62 */ 63 @Override 64 public void visit(ISequenceInstance sequenceInstance) { 65 visit((ITaskInstanceList) sequenceInstance); 66 } 74 /* 75 * (non-Javadoc) 76 * 77 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceVisitor#visit( 78 * ISequenceInstance) 79 */ 80 @Override 81 public void visit(ISequenceInstance sequenceInstance) { 82 visit((ITaskInstanceList) sequenceInstance); 83 } 67 84 68 /* (non-Javadoc) 69 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceVisitor#visit(ITaskInstance) 70 */ 71 @Override 72 public void visit(ITaskInstance taskInstance) { 73 if (taskInstance instanceof IEventTaskInstance) { 74 visit((IEventTaskInstance) taskInstance); 75 } 76 else if (taskInstance instanceof IIterationInstance) { 77 visit((IIterationInstance) taskInstance); 78 } 79 else if (taskInstance instanceof IOptionalInstance) { 80 visit((IOptionalInstance) taskInstance); 81 } 82 else if (taskInstance instanceof ISelectionInstance) { 83 visit((ISelectionInstance) taskInstance); 84 } 85 else if (taskInstance instanceof ISequenceInstance) { 86 visit((ISequenceInstance) taskInstance); 87 } 88 } 85 /* 86 * (non-Javadoc) 87 * 88 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceVisitor#visit( 89 * ITaskInstance) 90 */ 91 @Override 92 public void visit(ITaskInstance taskInstance) { 93 if (taskInstance instanceof IEventTaskInstance) { 94 visit((IEventTaskInstance) taskInstance); 95 } else if (taskInstance instanceof IIterationInstance) { 96 visit((IIterationInstance) taskInstance); 97 } else if (taskInstance instanceof IOptionalInstance) { 98 visit((IOptionalInstance) taskInstance); 99 } else if (taskInstance instanceof ISelectionInstance) { 100 visit((ISelectionInstance) taskInstance); 101 } else if (taskInstance instanceof ISequenceInstance) { 102 visit((ISequenceInstance) taskInstance); 103 } 104 } 89 105 90 91 /** 92 * <p> 93 * common implementation for traversing task instance lists. 94 * </p> 95 * 96 * @param taskInstanceListthe task instance list to be traversed97 98 99 for (ITaskInstance child : taskInstanceList) {100 101 102 106 /** 107 * <p> 108 * common implementation for traversing task instance lists. 109 * </p> 110 * 111 * @param taskInstanceList 112 * the task instance list to be traversed 113 */ 114 public void visit(ITaskInstanceList taskInstanceList) { 115 for (final ITaskInstance child : taskInstanceList) { 116 child.accept(this); 117 } 118 } 103 119 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/DefaultTaskTraversingVisitor.java
r1409 r1733 24 24 public class DefaultTaskTraversingVisitor implements ITaskVisitor { 25 25 26 /* (non-Javadoc) 27 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskVisitor#visit(IEventTask) 28 */ 29 @Override 30 public void visit(IEventTask eventTask) { 31 // do nothing 32 } 26 /* 27 * (non-Javadoc) 28 * 29 * @see 30 * de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskVisitor#visit(IEventTask) 31 */ 32 @Override 33 public void visit(IEventTask eventTask) { 34 // do nothing 35 } 33 36 34 /* (non-Javadoc) 35 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskVisitor#visit(IIteration) 36 */ 37 @Override 38 public void visit(IIteration iteration) { 39 visit((IMarkingTemporalRelationship) iteration); 40 } 37 /* 38 * (non-Javadoc) 39 * 40 * @see 41 * de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskVisitor#visit(IIteration) 42 */ 43 @Override 44 public void visit(IIteration iteration) { 45 visit((IMarkingTemporalRelationship) iteration); 46 } 41 47 42 /* (non-Javadoc) 43 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskVisitor#visit(IOptional) 44 */ 45 @Override 46 public void visit(IOptional optional) { 47 visit((IMarkingTemporalRelationship) optional); 48 } 48 /** 49 * <p> 50 * common implementation for traversing a marking temporal relationship 51 * </p> 52 * 53 * @param relationship 54 * the marking temporal relationship to be traversed 55 */ 56 public void visit(IMarkingTemporalRelationship relationship) { 57 if (relationship.getMarkedTask() != null) { 58 relationship.getMarkedTask().accept(this); 59 } 60 } 49 61 50 /* (non-Javadoc) 51 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskVisitor#visit(ISelection) 52 */ 53 @Override 54 public void visit(ISelection selection) { 55 visit((IStructuringTemporalRelationship) selection); 56 } 62 /* 63 * (non-Javadoc) 64 * 65 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskVisitor#visit(IOptional) 66 */ 67 @Override 68 public void visit(IOptional optional) { 69 visit((IMarkingTemporalRelationship) optional); 70 } 57 71 58 /* (non-Javadoc) 59 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskVisitor#visit(ISequence) 60 */ 61 @Override 62 public void visit(ISequence sequence) { 63 visit((IStructuringTemporalRelationship) sequence); 64 } 72 /* 73 * (non-Javadoc) 74 * 75 * @see 76 * de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskVisitor#visit(ISelection) 77 */ 78 @Override 79 public void visit(ISelection selection) { 80 visit((IStructuringTemporalRelationship) selection); 81 } 65 82 66 /* (non-Javadoc) 67 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskVisitor#visit(ITask) 68 */ 69 @Override 70 public void visit(ITask task) { 71 if (task instanceof IEventTask) { 72 visit((IEventTask) task); 73 } 74 else if (task instanceof IIteration) { 75 visit((IIteration) task); 76 } 77 else if (task instanceof IOptional) { 78 visit((IOptional) task); 79 } 80 else if (task instanceof ISelection) { 81 visit((ISelection) task); 82 } 83 else if (task instanceof ISequence) { 84 visit((ISequence) task); 85 } 86 } 83 /* 84 * (non-Javadoc) 85 * 86 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskVisitor#visit(ISequence) 87 */ 88 @Override 89 public void visit(ISequence sequence) { 90 visit((IStructuringTemporalRelationship) sequence); 91 } 87 92 88 /** 89 * <p> 90 * common implementation for traversing a structuring temporal relationship 91 * </p> 92 * 93 * @param relationship the structuring temporal relationship to be traversed 94 */ 95 public void visit(IStructuringTemporalRelationship relationship) { 96 for (ITask child : relationship.getChildren()) { 97 child.accept(this); 98 } 99 } 93 /** 94 * <p> 95 * common implementation for traversing a structuring temporal relationship 96 * </p> 97 * 98 * @param relationship 99 * the structuring temporal relationship to be traversed 100 */ 101 public void visit(IStructuringTemporalRelationship relationship) { 102 for (final ITask child : relationship.getChildren()) { 103 child.accept(this); 104 } 105 } 100 106 101 /** 102 * <p> 103 * common implementation for traversing a marking temporal relationship 104 * </p> 105 * 106 * @param relationship the marking temporal relationship to be traversed 107 */ 108 public void visit(IMarkingTemporalRelationship relationship) { 109 if (relationship.getMarkedTask() != null) { 110 relationship.getMarkedTask().accept(this); 111 } 112 } 107 /* 108 * (non-Javadoc) 109 * 110 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskVisitor#visit(ITask) 111 */ 112 @Override 113 public void visit(ITask task) { 114 if (task instanceof IEventTask) { 115 visit((IEventTask) task); 116 } else if (task instanceof IIteration) { 117 visit((IIteration) task); 118 } else if (task instanceof IOptional) { 119 visit((IOptional) task); 120 } else if (task instanceof ISelection) { 121 visit((ISelection) task); 122 } else if (task instanceof ISequence) { 123 visit((ISequence) task); 124 } 125 } 113 126 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IEventTask.java
r1294 r1733 17 17 /** 18 18 * <p> 19 * Event tasks represent single events. They have no children and are therefore the leaf nodes of 20 * a task model. They provide information about the event they represent as a String description. 21 * They do not refer to events, as they may represented several semantically equal but lexically 22 * different events. Their description carries as much information as required to show the 23 * level of distinction. 19 * Event tasks represent single events. They have no children and are therefore 20 * the leaf nodes of a task model. They provide information about the event they 21 * represent as a String description. They do not refer to events, as they may 22 * represented several semantically equal but lexically different events. Their 23 * description carries as much information as required to show the level of 24 * distinction. 24 25 * </p> 25 26 * … … 27 28 */ 28 29 public interface IEventTask extends ITask { 29 30 /** 31 * <p> 32 * returns a clone of this task, i.e. another event task being identical to this. The event 33 * type and target are not cloned but reused. 34 * </p> 35 * 36 * @return as described 37 */ 38 public IEventTask clone(); 30 31 /** 32 * <p> 33 * returns a clone of this task, i.e. another event task being identical to 34 * this. The event type and target are not cloned but reused. 35 * </p> 36 * 37 * @return as described 38 */ 39 @Override 40 public IEventTask clone(); 39 41 40 42 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IEventTaskInstance.java
r1398 r1733 19 19 /** 20 20 * <p> 21 * the instance of an {@link IEventTask}. The instance refers to the concrete event it represents. 21 * the instance of an {@link IEventTask}. The instance refers to the concrete 22 * event it represents. 22 23 * </p> 23 24 * … … 26 27 public interface IEventTaskInstance extends ITaskInstance { 27 28 28 /** 29 * <p> 30 * returns the event represented by this event task instance 31 * </p> 32 * 33 * @return as described 34 */ 35 public Event getEvent(); 29 /** 30 * <p> 31 * clones this task instance by creating exact clones of itself. The 32 * referred task and event stay untouched 33 * </p> 34 * 35 * @return a clone of the task instance 36 */ 37 @Override 38 public IEventTaskInstance clone(); 36 39 37 38 39 * returns the task related to the instance, i.e. the event task. 40 41 42 43 44 public IEventTask getEventTask();40 /** 41 * <p> 42 * returns the event represented by this event task instance 43 * </p> 44 * 45 * @return as described 46 */ 47 public Event getEvent(); 45 48 46 /** 47 * <p> 48 * clones this task instance by creating exact clones of itself. The referred task and event 49 * stay untouched 50 * </p> 51 * 52 * @return a clone of the task instance 53 */ 54 public IEventTaskInstance clone(); 55 49 /** 50 * <p> 51 * returns the task related to the instance, i.e. the event task. 52 * </p> 53 * 54 * @return as described 55 */ 56 public IEventTask getEventTask(); 57 56 58 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IIteration.java
r1180 r1733 17 17 /** 18 18 * <p> 19 * This temporal relationship defines that its single child may be executed zero or more times for 20 * fulfilling the task. This is most important for the parent node in the task model as this 21 * node may require that a specific subtask is executed several times. 19 * This temporal relationship defines that its single child may be executed zero 20 * or more times for fulfilling the task. This is most important for the parent 21 * node in the task model as this node may require that a specific subtask is 22 * executed several times. 22 23 * </p> 23 24 * … … 26 27 public interface IIteration extends IMarkingTemporalRelationship { 27 28 28 /** 29 * <p> 30 * returns an exact copy of this temporal relationship. The clone has the same id. Its child 31 * is a clone of the child of the cloned task. A call on the method {@link #equals(ITask)} 32 * with the result of this method must return true. 33 * </p> 34 * 35 * @return as described 36 */ 37 public IIteration clone(); 29 /** 30 * <p> 31 * returns an exact copy of this temporal relationship. The clone has the 32 * same id. Its child is a clone of the child of the cloned task. A call on 33 * the method {@link #equals(ITask)} with the result of this method must 34 * return true. 35 * </p> 36 * 37 * @return as described 38 */ 39 @Override 40 public IIteration clone(); 38 41 39 42 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IIterationInstance.java
r1398 r1733 17 17 /** 18 18 * <p> 19 * the instance of an {@link IIteration}. The instance may have several children each being an 20 * instance of the task marked by the iteration of which this is an instance. 19 * the instance of an {@link IIteration}. The instance may have several children 20 * each being an instance of the task marked by the iteration of which this is 21 * an instance. 21 22 * </p> 22 23 * … … 25 26 public interface IIterationInstance extends ITaskInstance, ITaskInstanceList { 26 27 27 /** 28 * <p> 29 * returns the task related to the instance, i.e. the iteration. 30 * </p> 31 * 32 * @return as described 33 */ 34 public IIteration getIteration(); 28 /** 29 * <p> 30 * clones this task instance by creating exact clones of each contained 31 * instance in their order 32 * </p> 33 * 34 * @return a clone of the task instance list 35 */ 36 @Override 37 public IIterationInstance clone(); 35 38 36 /** 37 * <p> 38 * clones this task instance by creating exact clones of each contained instance in their 39 * order 40 * </p> 41 * 42 * @return a clone of the task instance list 43 */ 44 public IIterationInstance clone(); 39 /** 40 * <p> 41 * returns the task related to the instance, i.e. the iteration. 42 * </p> 43 * 44 * @return as described 45 */ 46 public IIteration getIteration(); 45 47 46 48 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IMarkingTemporalRelationship.java
r1180 r1733 17 17 /** 18 18 * <p> 19 * A marking temporal relationship defines a temporal information for exactly one node in the task 20 * model. I.e., it has only one child for which it defines a special execution characteristic. 19 * A marking temporal relationship defines a temporal information for exactly 20 * one node in the task model. I.e., it has only one child for which it defines 21 * a special execution characteristic. 21 22 * </p> 22 23 * … … 25 26 public interface IMarkingTemporalRelationship extends ITemporalRelationship { 26 27 27 /** 28 * <p> 29 * returns the task for which this relationship defines the execution characteristic. The 30 * task can be seen as the child node of this node. 31 * </p> 32 * 33 * @return as described 34 */ 35 public ITask getMarkedTask(); 28 /** 29 * <p> 30 * returns an exact copy of this temporal relationship. The clone has the 31 * same id. Its child is a clone of the child of the cloned task. A call on 32 * the method {@link #equals(ITask)} with the result of this method must 33 * return true. 34 * </p> 35 * 36 * @return as described 37 */ 38 @Override 39 public IMarkingTemporalRelationship clone(); 36 40 37 /** 38 * <p> 39 * returns an exact copy of this temporal relationship. The clone has the same id. Its child 40 * is a clone of the child of the cloned task. A call on the method {@link #equals(ITask)} 41 * with the result of this method must return true. 42 * </p> 43 * 44 * @return as described 45 */ 46 public IMarkingTemporalRelationship clone(); 41 /** 42 * <p> 43 * returns the task for which this relationship defines the execution 44 * characteristic. The task can be seen as the child node of this node. 45 * </p> 46 * 47 * @return as described 48 */ 49 public ITask getMarkedTask(); 47 50 48 51 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IOptional.java
r1180 r1733 17 17 /** 18 18 * <p> 19 * This temporal relationship defines that its single child may or may not be executed for 20 * fulfilling the task. This is most important for the parent node in the task model as this 21 * node may require that a specific subtask is optional. 19 * This temporal relationship defines that its single child may or may not be 20 * executed for fulfilling the task. This is most important for the parent node 21 * in the task model as this node may require that a specific subtask is 22 * optional. 22 23 * </p> 23 24 * … … 26 27 public interface IOptional extends IMarkingTemporalRelationship { 27 28 28 /** 29 * <p> 30 * returns an exact copy of this temporal relationship. The clone has the same id. Its child 31 * is a clone of the child of the cloned task. A call on the method {@link #equals(ITask)} 32 * with the result of this method must return true. 33 * </p> 34 * 35 * @return as described 36 */ 37 public IOptional clone(); 29 /** 30 * <p> 31 * returns an exact copy of this temporal relationship. The clone has the 32 * same id. Its child is a clone of the child of the cloned task. A call on 33 * the method {@link #equals(ITask)} with the result of this method must 34 * return true. 35 * </p> 36 * 37 * @return as described 38 */ 39 @Override 40 public IOptional clone(); 38 41 39 42 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IOptionalInstance.java
r1413 r1733 18 18 * <p> 19 19 * the instance of an {@link IOptional}. The instance may have a child being an 20 * instance of the task marked by the optional of which this is an instance. If this instance 21 * does not have a child, the optional child task was not executed. 20 * instance of the task marked by the optional of which this is an instance. If 21 * this instance does not have a child, the optional child task was not 22 * executed. 22 23 * </p> 23 24 * … … 26 27 public interface IOptionalInstance extends ITaskInstance { 27 28 28 /** 29 * <p> 30 * returns the child of the optional of null if the optional was not executed 31 * </p> 32 * 33 * @return as described 34 */ 35 public ITaskInstance getChild(); 29 /** 30 * <p> 31 * clones this task instance by creating exact clones of each contained 32 * instance 33 * </p> 34 * 35 * @return a clone of the task instance 36 */ 37 @Override 38 public IOptionalInstance clone(); 36 39 37 /** 38 * <p> 39 * returns the task related to the instance, i.e. the optional. 40 * </p> 41 * 42 * @return as described 43 */ 44 public IOptional getOptional(); 40 /** 41 * <p> 42 * returns the child of the optional of null if the optional was not 43 * executed 44 * </p> 45 * 46 * @return as described 47 */ 48 public ITaskInstance getChild(); 45 49 46 47 48 * clones this task instance by creating exact clones of each contained instance 49 50 51 * @return a clone of the task instance 52 53 public IOptionalInstance clone();50 /** 51 * <p> 52 * returns the task related to the instance, i.e. the optional. 53 * </p> 54 * 55 * @return as described 56 */ 57 public IOptional getOptional(); 54 58 55 59 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ISelection.java
r1180 r1733 17 17 /** 18 18 * <p> 19 * This temporal relationship defines that only one of its children must be executed for20 * fulfilling the represented task.19 * This temporal relationship defines that only one of its children must be 20 * executed for fulfilling the represented task. 21 21 * </p> 22 22 * … … 25 25 public interface ISelection extends IStructuringTemporalRelationship { 26 26 27 /** 28 * <p> 29 * returns an exact copy of this temporal relationship. The clone has the same id. Its children 30 * are clones of the children of the cloned task. A call on the method {@link #equals(ITask)} 31 * with the result of this method must return true. 32 * </p> 33 * 34 * @return as described 35 */ 36 public ISelection clone(); 27 /** 28 * <p> 29 * returns an exact copy of this temporal relationship. The clone has the 30 * same id. Its children are clones of the children of the cloned task. A 31 * call on the method {@link #equals(ITask)} with the result of this method 32 * must return true. 33 * </p> 34 * 35 * @return as described 36 */ 37 @Override 38 public ISelection clone(); 37 39 38 40 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ISelectionInstance.java
r1413 r1733 17 17 /** 18 18 * <p> 19 * the instance of an {@link ISelection}. The instance has a child being an instance of the child20 * task of the selection that was selected for execution.19 * the instance of an {@link ISelection}. The instance has a child being an 20 * instance of the child task of the selection that was selected for execution. 21 21 * </p> 22 22 * … … 25 25 public interface ISelectionInstance extends ITaskInstance { 26 26 27 /** 28 * <p> 29 * returns the selected child of the selection 30 * </p> 31 * 32 * @return as described 33 */ 34 public ITaskInstance getChild(); 27 /** 28 * <p> 29 * clones this task instance by creating exact clones of the contained 30 * instance 31 * </p> 32 * 33 * @return a clone of the task instance 34 */ 35 @Override 36 public ISelectionInstance clone(); 35 37 36 37 38 * returns the task related to the instance, i.e. the selection. 39 40 41 42 43 public ISelection getSelection();38 /** 39 * <p> 40 * returns the selected child of the selection 41 * </p> 42 * 43 * @return as described 44 */ 45 public ITaskInstance getChild(); 44 46 45 46 47 * clones this task instance by creating exact clones of the contained instance 48 49 50 * @return a clone of the task instance 51 52 public ISelectionInstance clone();47 /** 48 * <p> 49 * returns the task related to the instance, i.e. the selection. 50 * </p> 51 * 52 * @return as described 53 */ 54 public ISelection getSelection(); 53 55 54 56 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ISequence.java
r1180 r1733 17 17 /** 18 18 * <p> 19 * This temporal relationship defines that its children must be executed in the order they are20 * listed for fulfilling the represented task.19 * This temporal relationship defines that its children must be executed in the 20 * order they are listed for fulfilling the represented task. 21 21 * </p> 22 22 * … … 25 25 public interface ISequence extends IStructuringTemporalRelationship { 26 26 27 /** 28 * <p> 29 * returns an exact copy of this temporal relationship. The clone has the same id. Its children 30 * are clones of the children of the cloned task. A call on the method {@link #equals(ITask)} 31 * with the result of this method must return true. 32 * </p> 33 * 34 * @return as described 35 */ 36 public ISequence clone(); 27 /** 28 * <p> 29 * returns an exact copy of this temporal relationship. The clone has the 30 * same id. Its children are clones of the children of the cloned task. A 31 * call on the method {@link #equals(ITask)} with the result of this method 32 * must return true. 33 * </p> 34 * 35 * @return as described 36 */ 37 @Override 38 public ISequence clone(); 37 39 38 40 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ISequenceInstance.java
r1413 r1733 17 17 /** 18 18 * <p> 19 * the instance of an {@link ISequence}. The instance has the same number of children as the20 * sequence it represents.19 * the instance of an {@link ISequence}. The instance has the same number of 20 * children as the sequence it represents. 21 21 * </p> 22 22 * … … 25 25 public interface ISequenceInstance extends ITaskInstance, ITaskInstanceList { 26 26 27 /** 28 * <p> 29 * returns the task related to the instance, i.e. the sequence. 30 * </p> 31 * 32 * @return as described 33 */ 34 public ISequence getSequence(); 27 /** 28 * <p> 29 * clones this task instance by creating exact clones of each contained 30 * instance in their order 31 * </p> 32 * 33 * @return a clone of the task instance 34 */ 35 @Override 36 public ISequenceInstance clone(); 35 37 36 /** 37 * <p> 38 * clones this task instance by creating exact clones of each contained instance in their 39 * order 40 * </p> 41 * 42 * @return a clone of the task instance 43 */ 44 public ISequenceInstance clone(); 45 38 /** 39 * <p> 40 * returns the task related to the instance, i.e. the sequence. 41 * </p> 42 * 43 * @return as described 44 */ 45 public ISequence getSequence(); 46 46 47 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IStructuringTemporalRelationship.java
r1180 r1733 19 19 /** 20 20 * <p> 21 * A structuring temporal relationship defines a temporal information for several nodes in the task 22 * model. I.e., it has several children and defines an execution order for them. 21 * A structuring temporal relationship defines a temporal information for 22 * several nodes in the task model. I.e., it has several children and defines an 23 * execution order for them. 23 24 * </p> 24 25 * … … 27 28 public interface IStructuringTemporalRelationship extends ITemporalRelationship { 28 29 29 /** 30 * <p> 31 * returns the children of this temporal relationship. 32 * </p> 33 * 34 * @return as described 35 */ 36 public List<ITask> getChildren(); 30 /** 31 * <p> 32 * returns an exact copy of this temporal relationship. The clone has the 33 * same id. Its children are clones of the children of the cloned task. A 34 * call on the method {@link #equals(ITask)} with the result of this method 35 * must return true. 36 * </p> 37 * 38 * @return as described 39 */ 40 @Override 41 public IStructuringTemporalRelationship clone(); 37 42 38 /** 39 * <p> 40 * returns an exact copy of this temporal relationship. The clone has the same id. Its children 41 * are clones of the children of the cloned task. A call on the method {@link #equals(ITask)} 42 * with the result of this method must return true. 43 * </p> 44 * 45 * @return as described 46 */ 47 public IStructuringTemporalRelationship clone(); 43 /** 44 * <p> 45 * returns the children of this temporal relationship. 46 * </p> 47 * 48 * @return as described 49 */ 50 public List<ITask> getChildren(); 48 51 49 52 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITask.java
r1400 r1733 20 20 /** 21 21 * <p> 22 * A task represents a model for events that occur if the user interacts with a software for 23 * achieving a specific goal. A task can be a single event or a complex structure of events 24 * and temporal relationships defining the event order. Tasks may especially refer to other tasks 25 * to create task structures similar to trees. These structures fully define in which ways the 26 * events that form the task can occur. However, the structure of a task is not necessarily a 27 * tree as task structures may be reused several times in larger scale task structures. 22 * A task represents a model for events that occur if the user interacts with a 23 * software for achieving a specific goal. A task can be a single event or a 24 * complex structure of events and temporal relationships defining the event 25 * order. Tasks may especially refer to other tasks to create task structures 26 * similar to trees. These structures fully define in which ways the events that 27 * form the task can occur. However, the structure of a task is not necessarily 28 * a tree as task structures may be reused several times in larger scale task 29 * structures. 28 30 * </p> 29 31 * … … 32 34 public interface ITask extends Cloneable, Serializable { 33 35 34 /** 35 * <p> 36 * every task is assigned a unique id which is returned by this method. The id is unique for 37 * the current runtime. 38 * </p> 39 * 40 * @return as described 41 */ 42 public int getId(); 36 /** 37 * <p> 38 * implements the visitor pattern to be able to process tasks and their 39 * children. 40 * </p> 41 * 42 * @param visitor 43 * the visitor used to process the task 44 */ 45 public void accept(ITaskVisitor visitor); 43 46 44 /** 45 * <p> 46 * returns a human readable type for the task. 47 * </p> 48 * 49 * @return as described 50 */ 51 public String getType(); 47 /** 48 * <p> 49 * returns an exact copy of this task. The clone has the same id. If the 50 * task has children, they are cloned as well. A call on the method 51 * {@link #equals(ITask)} with the result of this method must return true. 52 * </p> 53 * 54 * @return as described 55 */ 56 public ITask clone(); 52 57 53 /** 54 * <p> 55 * returns a human readable description for the task. 56 * </p> 57 * 58 * @return as described 59 */ 60 public String getDescription(); 58 /** 59 * <p> 60 * checks whether this task is equal to another one. Task equality is only 61 * given, if two tasks have the same id. This means, that this method must 62 * only return true if the other task is either the same object or a clone 63 * of it. 64 * </p> 65 * 66 * @return as described 67 */ 68 public boolean equals(ITask task); 61 69 62 63 64 * returns a collection of all observed instances of this task 65 66 67 68 69 public Collection<ITaskInstance> getInstances();70 /** 71 * <p> 72 * returns a human readable description for the task. 73 * </p> 74 * 75 * @return as described 76 */ 77 public String getDescription(); 70 78 71 /** 72 * <p> 73 * returns a collection of collections of all different execution variants of this task. This 74 * is a grouping of all instances where each group contains structurally identical instances. 75 * </p> 76 * 77 * @return as described 78 */ 79 public Collection<Collection<ITaskInstance>> getExecutionVariants(); 79 /** 80 * <p> 81 * returns a collection of collections of all different execution variants 82 * of this task. This is a grouping of all instances where each group 83 * contains structurally identical instances. 84 * </p> 85 * 86 * @return as described 87 */ 88 public Collection<Collection<ITaskInstance>> getExecutionVariants(); 80 89 81 /** 82 * <p> 83 * checks whether this task is equal to another one. Task equality is only given, if two 84 * tasks have the same id. This means, that this method must only return true if the other 85 * task is either the same object or a clone of it. 86 * </p> 87 * 88 * @return as described 89 */ 90 public boolean equals(ITask task); 90 /** 91 * <p> 92 * every task is assigned a unique id which is returned by this method. The 93 * id is unique for the current runtime. 94 * </p> 95 * 96 * @return as described 97 */ 98 public int getId(); 91 99 92 93 94 * returns a hash code for the task, which is usually the id returned by {@link #getId()}. 95 96 97 98 99 public int hashCode();100 /** 101 * <p> 102 * returns a collection of all observed instances of this task 103 * </p> 104 * 105 * @return as described 106 */ 107 public Collection<ITaskInstance> getInstances(); 100 108 101 102 103 * returns an exact copy of this task. The clone has the same id. If the task has 104 * children, they are cloned as well. A call on the method {@link #equals(ITask)} with the 105 * result of this method must return true. 106 * </p> 107 * 108 * @return as described 109 */ 110 public ITask clone(); 111 112 /** 113 * <p> 114 * implements the visitor pattern to be able to process tasks and their children. 115 * </p> 116 * 117 * @param visitor the visitor used to process the task 118 */ 119 public void accept(ITaskVisitor visitor);120 109 /** 110 * <p> 111 * returns a human readable type for the task. 112 * </p> 113 * 114 * @return as described 115 */ 116 public String getType(); 117 118 /** 119 * <p> 120 * returns a hash code for the task, which is usually the id returned by 121 * {@link #getId()}. 122 * </p> 123 * 124 * @return as described 125 */ 126 @Override 127 public int hashCode(); 128 121 129 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskBuilder.java
r1294 r1733 17 17 /** 18 18 * <p> 19 * Builder for task models. Can be used to create and edit task models. May perform integrity20 * checks, though they may be incomplete as the integrity of a task model can not be ensured during21 * creation.19 * Builder for task models. Can be used to create and edit task models. May 20 * perform integrity checks, though they may be incomplete as the integrity of a 21 * task model can not be ensured during creation. 22 22 * </p> 23 23 */ 24 24 public interface ITaskBuilder { 25 25 26 /** 27 * <p> 28 * adds a child to a sequence instance. May ensure, that the child is a valid child considering 29 * the task model of the parent. In that case, an IllegalArgumentException is thrown. 30 * </p> 31 * 32 * @param instance the instance of add the child to 33 * @param child the child to be added 34 * 35 * @throws IllegalArgumentException as described 36 */ 37 void addChild(ISequenceInstance instance, ITaskInstance child) throws IllegalArgumentException; 38 39 /** 40 * <p> 41 * adds a child to an iteration instance. May ensure, that the child is a valid child 42 * considering the task model of the parent. In that case, an IllegalArgumentException is 43 * thrown. 44 * </p> 45 * 46 * @param instance the instance of add the child to 47 * @param child the child to be added 48 * 49 * @throws IllegalArgumentException as described 50 */ 51 void addChild(IIterationInstance instance, ITaskInstance child) throws IllegalArgumentException; 52 53 /** 54 * <p> 55 * sets the child of a selection instance. May ensure, that the child is a valid child 56 * considering the task model of the parent. In that case, an IllegalArgumentException is 57 * thrown. 58 * </p> 59 * 60 * @param instance the instance of add the child to 61 * @param child the child to be added 62 * 63 * @throws IllegalArgumentException as described 64 */ 65 void setChild(ISelectionInstance instance, ITaskInstance child) throws IllegalArgumentException; 66 67 /** 68 * <p> 69 * sets the child of an optional instance. May ensure, that the child is a valid child 70 * considering the task model of the parent. In that case, an IllegalArgumentException is 71 * thrown. 72 * </p> 73 * 74 * @param instance the instance of add the child to 75 * @param child the child to be added 76 * 77 * @throws IllegalArgumentException as described 78 */ 79 void setChild(IOptionalInstance instance, ITaskInstance child) throws IllegalArgumentException; 80 81 /** 82 * <p> 83 * adds a task instance to a user session 84 * </p> 85 * 86 * @param session the session to add the task instance to 87 * @param taskInstance the task instance to add 88 */ 89 void addExecutedTask(IUserSession session, ITaskInstance taskInstance); 90 91 /** 92 * <p> 93 * adds a task instance to a task instance list 94 * </p> 95 * 96 * @param taskInstanceList the list to add the task instance to 97 * @param taskInstance the task instance to add 98 */ 99 void addTaskInstance(ITaskInstanceList taskInstanceList, ITaskInstance taskInstance); 100 101 /** 102 * <p> 103 * adds a task instance to a task instance list at a specific position. Subsequent task 104 * instances will be moved one index forward 105 * </p> 106 * 107 * @param taskInstanceList the list to add the task instance to 108 * @param index the index of the task instance to add 109 * @param taskInstance the task instance to add 110 * 111 * @throws IndexOutOfBoundsException if the index is invalid 112 */ 113 void addTaskInstance(ITaskInstanceList taskInstanceList, int index, ITaskInstance taskInstance) 114 throws IndexOutOfBoundsException; 115 116 /** 117 * <p> 118 * sets a task instance in a task instance list at a specific position 119 * </p> 120 * 121 * @param taskInstanceList the list to set the task instance in 122 * @param index the index of the task instance to replace 123 * @param taskInstance the replacement for the task instance at the index 124 * 125 * @throws IndexOutOfBoundsException if the index is invalid 126 */ 127 void setTaskInstance(ITaskInstanceList taskInstanceList, int index, ITaskInstance taskInstance) 128 throws IndexOutOfBoundsException; 129 130 /** 131 * <p> 132 * sets the task model of a task instance 133 * </p> 134 * 135 * @param taskInstance the task instance to set the task model for 136 * @param task the task model of the instance 137 */ 138 void setTask(ITaskInstance taskInstance, ITask task); 139 140 /** 141 * <p> 142 * adds a child task to the end of a sequence 143 * </p> 144 * 145 * @param parent the sequence to add the child to 146 * @param child the child to be added 147 */ 148 void addChild(ISequence parent, ITask child); 149 150 /** 151 * <p> 152 * adds a child task to a specific index of a sequence 153 * </p> 154 * 155 * @param parent the sequence to add the child to 156 * @param index the index to set the child at 157 * @param child the child to be added 158 * 159 * @throws IndexOutOfBoundsException if the index is invalid 160 */ 161 void addChild(ISequence parent, int index, ITask child) 162 throws IndexOutOfBoundsException; 163 164 /** 165 * <p> 166 * replaces the child task of a sequence at a specific position 167 * </p> 168 * 169 * @param parent the sequence to replace the child in 170 * @param index the index to replace the child at 171 * @param child the child to be added 172 * 173 * @throws IndexOutOfBoundsException if the index is invalid 174 */ 175 void setChild(ISequence parent, int index, ITask child) 176 throws IndexOutOfBoundsException; 177 178 /** 179 * <p> 180 * adds a child task to a selection 181 * </p> 182 * 183 * @param parent the selection to add the child to 184 * @param child the child to be added 185 */ 186 void addChild(ISelection parent, ITask child); 187 188 /** 189 * <p> 190 * sets the child task of an iteration 191 * </p> 192 * 193 * @param iteration the iteration to set the child of 194 * @param child the child to be set 195 */ 196 void setMarkedTask(IIteration iteration, ITask child); 197 198 /** 199 * <p> 200 * sets the child task of an optional 201 * </p> 202 * 203 * @param optional the optional to set the child of 204 * @param child the child to be set 205 */ 206 void setMarkedTask(IOptional optional, ITask child); 207 208 /** 209 * <p> 210 * removes the child of a sequence at a specific position 211 * </p> 212 * 213 * @param parent the sequence of which the child must be removed 214 * @param index the index of the child to be removed 215 * 216 * @throws IndexOutOfBoundsException if the index is invalid 217 */ 218 void removeChild(ISequence parent, int index) 219 throws IndexOutOfBoundsException; 220 221 /** 222 * <p> 223 * removes a child of a selection. Ignores the call, if the child is not found 224 * (comparison using equals). 225 * </p> 226 * 227 * @param parent the selection of which the child must be removed 228 * @param child the child to be removes 229 */ 230 void removeChild(ISelection parent, ITask child); 231 232 /** 233 * <p> 234 * removes the entry of a task instance list at a specific position 235 * </p> 236 * 237 * @param taskInstanceList the task instance list of which the entry must be removed 238 * @param index the index of the entry to be removed 239 * 240 * @throws IndexOutOfBoundsException if the index is invalid 241 */ 242 void removeTaskInstance(ITaskInstanceList taskInstanceList, int index) 243 throws IndexOutOfBoundsException; 244 245 /** 246 * <p> 247 * replaces a child of a selection. Throws an IllegalArgumentException if the child is not 248 * found (comparison using equals). 249 * </p> 250 * 251 * @param parent the selection of which the child must be replace 252 * @param oldChild the child to replace 253 * @param newChild the replacement for the child 254 * 255 * @throws as described 256 */ 257 void replaceChild(ISelection parent, ITask oldChild, ITask newChild); 26 /** 27 * <p> 28 * adds a child to an iteration instance. May ensure, that the child is a 29 * valid child considering the task model of the parent. In that case, an 30 * IllegalArgumentException is thrown. 31 * </p> 32 * 33 * @param instance 34 * the instance of add the child to 35 * @param child 36 * the child to be added 37 * 38 * @throws IllegalArgumentException 39 * as described 40 */ 41 void addChild(IIterationInstance instance, ITaskInstance child) 42 throws IllegalArgumentException; 43 44 /** 45 * <p> 46 * adds a child task to a selection 47 * </p> 48 * 49 * @param parent 50 * the selection to add the child to 51 * @param child 52 * the child to be added 53 */ 54 void addChild(ISelection parent, ITask child); 55 56 /** 57 * <p> 58 * adds a child task to a specific index of a sequence 59 * </p> 60 * 61 * @param parent 62 * the sequence to add the child to 63 * @param index 64 * the index to set the child at 65 * @param child 66 * the child to be added 67 * 68 * @throws IndexOutOfBoundsException 69 * if the index is invalid 70 */ 71 void addChild(ISequence parent, int index, ITask child) 72 throws IndexOutOfBoundsException; 73 74 /** 75 * <p> 76 * adds a child task to the end of a sequence 77 * </p> 78 * 79 * @param parent 80 * the sequence to add the child to 81 * @param child 82 * the child to be added 83 */ 84 void addChild(ISequence parent, ITask child); 85 86 /** 87 * <p> 88 * adds a child to a sequence instance. May ensure, that the child is a 89 * valid child considering the task model of the parent. In that case, an 90 * IllegalArgumentException is thrown. 91 * </p> 92 * 93 * @param instance 94 * the instance of add the child to 95 * @param child 96 * the child to be added 97 * 98 * @throws IllegalArgumentException 99 * as described 100 */ 101 void addChild(ISequenceInstance instance, ITaskInstance child) 102 throws IllegalArgumentException; 103 104 /** 105 * <p> 106 * adds a task instance to a user session 107 * </p> 108 * 109 * @param session 110 * the session to add the task instance to 111 * @param taskInstance 112 * the task instance to add 113 */ 114 void addExecutedTask(IUserSession session, ITaskInstance taskInstance); 115 116 /** 117 * <p> 118 * adds a task instance to a task instance list at a specific position. 119 * Subsequent task instances will be moved one index forward 120 * </p> 121 * 122 * @param taskInstanceList 123 * the list to add the task instance to 124 * @param index 125 * the index of the task instance to add 126 * @param taskInstance 127 * the task instance to add 128 * 129 * @throws IndexOutOfBoundsException 130 * if the index is invalid 131 */ 132 void addTaskInstance(ITaskInstanceList taskInstanceList, int index, 133 ITaskInstance taskInstance) throws IndexOutOfBoundsException; 134 135 /** 136 * <p> 137 * adds a task instance to a task instance list 138 * </p> 139 * 140 * @param taskInstanceList 141 * the list to add the task instance to 142 * @param taskInstance 143 * the task instance to add 144 */ 145 void addTaskInstance(ITaskInstanceList taskInstanceList, 146 ITaskInstance taskInstance); 147 148 /** 149 * <p> 150 * removes a child of a selection. Ignores the call, if the child is not 151 * found (comparison using equals). 152 * </p> 153 * 154 * @param parent 155 * the selection of which the child must be removed 156 * @param child 157 * the child to be removes 158 */ 159 void removeChild(ISelection parent, ITask child); 160 161 /** 162 * <p> 163 * removes the child of a sequence at a specific position 164 * </p> 165 * 166 * @param parent 167 * the sequence of which the child must be removed 168 * @param index 169 * the index of the child to be removed 170 * 171 * @throws IndexOutOfBoundsException 172 * if the index is invalid 173 */ 174 void removeChild(ISequence parent, int index) 175 throws IndexOutOfBoundsException; 176 177 /** 178 * <p> 179 * removes the entry of a task instance list at a specific position 180 * </p> 181 * 182 * @param taskInstanceList 183 * the task instance list of which the entry must be removed 184 * @param index 185 * the index of the entry to be removed 186 * 187 * @throws IndexOutOfBoundsException 188 * if the index is invalid 189 */ 190 void removeTaskInstance(ITaskInstanceList taskInstanceList, int index) 191 throws IndexOutOfBoundsException; 192 193 /** 194 * <p> 195 * replaces a child of a selection. Throws an IllegalArgumentException if 196 * the child is not found (comparison using equals). 197 * </p> 198 * 199 * @param parent 200 * the selection of which the child must be replace 201 * @param oldChild 202 * the child to replace 203 * @param newChild 204 * the replacement for the child 205 * 206 * @throws as 207 * described 208 */ 209 void replaceChild(ISelection parent, ITask oldChild, ITask newChild); 210 211 /** 212 * <p> 213 * sets the child of an optional instance. May ensure, that the child is a 214 * valid child considering the task model of the parent. In that case, an 215 * IllegalArgumentException is thrown. 216 * </p> 217 * 218 * @param instance 219 * the instance of add the child to 220 * @param child 221 * the child to be added 222 * 223 * @throws IllegalArgumentException 224 * as described 225 */ 226 void setChild(IOptionalInstance instance, ITaskInstance child) 227 throws IllegalArgumentException; 228 229 /** 230 * <p> 231 * sets the child of a selection instance. May ensure, that the child is a 232 * valid child considering the task model of the parent. In that case, an 233 * IllegalArgumentException is thrown. 234 * </p> 235 * 236 * @param instance 237 * the instance of add the child to 238 * @param child 239 * the child to be added 240 * 241 * @throws IllegalArgumentException 242 * as described 243 */ 244 void setChild(ISelectionInstance instance, ITaskInstance child) 245 throws IllegalArgumentException; 246 247 /** 248 * <p> 249 * replaces the child task of a sequence at a specific position 250 * </p> 251 * 252 * @param parent 253 * the sequence to replace the child in 254 * @param index 255 * the index to replace the child at 256 * @param child 257 * the child to be added 258 * 259 * @throws IndexOutOfBoundsException 260 * if the index is invalid 261 */ 262 void setChild(ISequence parent, int index, ITask child) 263 throws IndexOutOfBoundsException; 264 265 /** 266 * <p> 267 * sets the child task of an iteration 268 * </p> 269 * 270 * @param iteration 271 * the iteration to set the child of 272 * @param child 273 * the child to be set 274 */ 275 void setMarkedTask(IIteration iteration, ITask child); 276 277 /** 278 * <p> 279 * sets the child task of an optional 280 * </p> 281 * 282 * @param optional 283 * the optional to set the child of 284 * @param child 285 * the child to be set 286 */ 287 void setMarkedTask(IOptional optional, ITask child); 288 289 /** 290 * <p> 291 * sets the task model of a task instance 292 * </p> 293 * 294 * @param taskInstance 295 * the task instance to set the task model for 296 * @param task 297 * the task model of the instance 298 */ 299 void setTask(ITaskInstance taskInstance, ITask task); 300 301 /** 302 * <p> 303 * sets a task instance in a task instance list at a specific position 304 * </p> 305 * 306 * @param taskInstanceList 307 * the list to set the task instance in 308 * @param index 309 * the index of the task instance to replace 310 * @param taskInstance 311 * the replacement for the task instance at the index 312 * 313 * @throws IndexOutOfBoundsException 314 * if the index is invalid 315 */ 316 void setTaskInstance(ITaskInstanceList taskInstanceList, int index, 317 ITaskInstance taskInstance) throws IndexOutOfBoundsException; 258 318 259 319 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskFactory.java
r1294 r1733 28 28 public interface ITaskFactory { 29 29 30 /** 31 * <p> 32 * creates a new event task with the given description 33 * </p> 34 * 35 * @param description the description for the represented events 36 * 37 * @return the event task 38 */ 39 IEventTask createNewEventTask(String description); 30 /** 31 * <p> 32 * creates a new event task with the given description 33 * </p> 34 * 35 * @param description 36 * the description for the represented events 37 * 38 * @return the event task 39 */ 40 IEventTask createNewEventTask(String description); 40 41 41 42 43 * creates a new empty sequence 44 45 46 * @return the sequence 47 48 ISequence createNewSequence();42 /** 43 * <p> 44 * creates a new empty iteration 45 * </p> 46 * 47 * @return the iteration 48 */ 49 IIteration createNewIteration(); 49 50 50 51 52 * creates a new empty iteration 53 54 55 * @return the iteration 56 57 IIteration createNewIteration();51 /** 52 * <p> 53 * creates a new empty optional 54 * </p> 55 * 56 * @return the optional 57 */ 58 IOptional createNewOptional(); 58 59 59 60 61 * creates a new empty optional 62 63 64 * @return the optional 65 66 IOptional createNewOptional();60 /** 61 * <p> 62 * creates a new empty selection 63 * </p> 64 * 65 * @return the selection 66 */ 67 ISelection createNewSelection(); 67 68 68 69 70 * creates a new empty selection 71 72 73 * @return the selection 74 75 ISelection createNewSelection();69 /** 70 * <p> 71 * creates a new empty sequence 72 * </p> 73 * 74 * @return the sequence 75 */ 76 ISequence createNewSequence(); 76 77 77 /** 78 * <p> 79 * creates a new task instance with the given task as its model representing the provided event 80 * </p> 81 * 82 * @param task the model of the task instance to be created 83 * @param event the event represented by the task instance 84 * 85 * @return the task instance 86 */ 87 IEventTaskInstance createNewTaskInstance(IEventTask task, Event event); 78 /** 79 * <p> 80 * creates a new task instance with the given task as its model representing 81 * the provided event 82 * </p> 83 * 84 * @param task 85 * the model of the task instance to be created 86 * @param event 87 * the event represented by the task instance 88 * 89 * @return the task instance 90 */ 91 IEventTaskInstance createNewTaskInstance(IEventTask task, Event event); 88 92 89 /** 90 * <p> 91 * creates a new task instance with the given sequence as its model 92 * </p> 93 * 94 * @param sequence the model of the task instance to be created 95 * 96 * @return the task instance 97 */ 98 ISequenceInstance createNewTaskInstance(ISequence sequence); 93 /** 94 * <p> 95 * creates a new task instance with the given iteration as its model 96 * </p> 97 * 98 * @param iteration 99 * the model of the task instance to be created 100 * 101 * @return the task instance 102 */ 103 IIterationInstance createNewTaskInstance(IIteration iteration); 99 104 100 /** 101 * <p> 102 * creates a new task instance with the given iteration as its model 103 * </p> 104 * 105 * @param iteration the model of the task instance to be created 106 * 107 * @return the task instance 108 */ 109 IIterationInstance createNewTaskInstance(IIteration iteration); 105 /** 106 * <p> 107 * creates a new task instance with the given optional as its model 108 * </p> 109 * 110 * @param optional 111 * the model of the task instance to be created 112 * 113 * @return the task instance 114 */ 115 IOptionalInstance createNewTaskInstance(IOptional optional); 110 116 111 /** 112 * <p> 113 * creates a new task instance with the given optional as its model 114 * </p> 115 * 116 * @param optional the model of the task instance to be created 117 * 118 * @return the task instance 119 */ 120 IOptionalInstance createNewTaskInstance(IOptional optional); 117 /** 118 * <p> 119 * creates a new task instance with the given selection as its model 120 * </p> 121 * 122 * @param selection 123 * the model of the task instance to be created 124 * 125 * @return the task instance 126 */ 127 ISelectionInstance createNewTaskInstance(ISelection selection); 121 128 122 /** 123 * <p> 124 * creates a new task instance with the given selection as its model 125 * </p> 126 * 127 * @param selection the model of the task instance to be created 128 * 129 * @return the task instance 130 */ 131 ISelectionInstance createNewTaskInstance(ISelection selection); 129 /** 130 * <p> 131 * creates a new task instance with the given sequence as its model 132 * </p> 133 * 134 * @param sequence 135 * the model of the task instance to be created 136 * 137 * @return the task instance 138 */ 139 ISequenceInstance createNewTaskInstance(ISequence sequence); 132 140 133 /** 134 * <p> 135 * creates a new empty user session 136 * </p> 137 * 138 * @return the user session 139 */ 140 IUserSession createUserSession(); 141 /** 142 * <p> 143 * creates a task model based on the provided user sessions 144 * </p> 145 * 146 * @param userSessions 147 * the session based on which the task model shall be created 148 * 149 * @return the task model 150 */ 151 ITaskModel createTaskModel(List<IUserSession> userSessions); 141 152 142 /** 143 * <p> 144 * creates a task model based on the provided user sessions 145 * </p> 146 * 147 * @param userSessions the session based on which the task model shall be created 148 * 149 * @return the task model 150 */ 151 ITaskModel createTaskModel(List<IUserSession> userSessions); 153 /** 154 * <p> 155 * creates a new empty user session 156 * </p> 157 * 158 * @return the user session 159 */ 160 IUserSession createUserSession(); 152 161 153 162 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskInfo.java
r1428 r1733 17 17 /** 18 18 * <p> 19 * Provides extended information about a specific task, such as statistics about task occurrences, 20 * etc. It contains measures for different metrics determined for a task. 19 * Provides extended information about a specific task, such as statistics about 20 * task occurrences, etc. It contains measures for different metrics determined 21 * for a task. 21 22 * </p> 22 23 * … … 25 26 public interface ITaskInfo { 26 27 27 28 29 * returns the task to which these infos belong 30 31 32 * @return as described 33 34 public ITask getTask(); 28 /** 29 * <p> 30 * represents a measure for a specific metric 31 * </p> 32 * 33 * @author Patrick Harms 34 */ 35 public interface IMeasure { 35 36 36 37 38 * returns all available measures 39 40 41 42 43 public IMeasure[] getMeasures();37 /** 38 * <p> 39 * returns the metric of the measure 40 * </p> 41 * 42 * @return as described 43 */ 44 public TaskMetric getMetric(); 44 45 45 /** 46 * <p> 47 * returns the value of the measure identified through the given metric 48 * </p> 49 * 50 * @param metric the metric for which the value is to be returned 51 * 52 * @return as described 53 */ 54 public int getMeasureValue(TaskMetric metric); 46 /** 47 * <p> 48 * returns the value of the measure 49 * </p> 50 * 51 * @return as described 52 */ 53 public int getValue(); 55 54 56 /** 57 * <p> 58 * returns the value of the measure identified through the given metric if the task is 59 * observed in the given context, i.e. parent task. The result is Integer.MIN_VALUE if there 60 * is no value for this measure in a context. 61 * </p> 62 * 63 * @param metric the metric for which the value is to be returned 64 * @param context the context for which the measure value is to be returned 65 * 66 * @return as described 67 */ 68 public int getMeasureValue(TaskMetric metric, ITask context); 55 /** 56 * <p> 57 * returns the value of the measure if the task was observed in a 58 * specific context, i.e. parent task 59 * </p> 60 * 61 * @return as described 62 */ 63 public int getValue(ITask context); 69 64 70 /** 71 * <p> 72 * represents a measure for a specific metric 73 * </p> 74 * 75 * @author Patrick Harms 76 */ 77 public interface IMeasure { 78 79 /** 80 * <p> 81 * returns the metric of the measure 82 * </p> 83 * 84 * @return as described 85 */ 86 public TaskMetric getMetric(); 87 88 /** 89 * <p> 90 * returns the value of the measure 91 * </p> 92 * 93 * @return as described 94 */ 95 public int getValue(); 96 97 /** 98 * <p> 99 * returns the value of the measure if the task was observed in a specific context, i.e. 100 * parent task 101 * </p> 102 * 103 * @return as described 104 */ 105 public int getValue(ITask context); 106 107 } 65 } 66 67 /** 68 * <p> 69 * returns all available measures 70 * </p> 71 * 72 * @return as described 73 */ 74 public IMeasure[] getMeasures(); 75 76 /** 77 * <p> 78 * returns the value of the measure identified through the given metric 79 * </p> 80 * 81 * @param metric 82 * the metric for which the value is to be returned 83 * 84 * @return as described 85 */ 86 public int getMeasureValue(TaskMetric metric); 87 88 /** 89 * <p> 90 * returns the value of the measure identified through the given metric if 91 * the task is observed in the given context, i.e. parent task. The result 92 * is Integer.MIN_VALUE if there is no value for this measure in a context. 93 * </p> 94 * 95 * @param metric 96 * the metric for which the value is to be returned 97 * @param context 98 * the context for which the measure value is to be returned 99 * 100 * @return as described 101 */ 102 public int getMeasureValue(TaskMetric metric, ITask context); 103 104 /** 105 * <p> 106 * returns the task to which these infos belong 107 * </p> 108 * 109 * @return as described 110 */ 111 public ITask getTask(); 108 112 109 113 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskInstance.java
r1405 r1733 19 19 /** 20 20 * <p> 21 * a task instance represents the execution of a specific task within a user session. A task22 * instance is always related to the task that was executed.21 * a task instance represents the execution of a specific task within a user 22 * session. A task instance is always related to the task that was executed. 23 23 * </p> 24 24 * … … 27 27 public interface ITaskInstance extends Serializable, Cloneable { 28 28 29 /** 30 * <p> 31 * returns the task related to the instance. 32 * </p> 33 * 34 * @return as described 35 */ 36 public ITask getTask(); 29 /** 30 * <p> 31 * implements the visitor pattern to be able to process task instances and 32 * their children. 33 * </p> 34 * 35 * @param visitor 36 * the visitor used to process the task 37 */ 38 public void accept(ITaskInstanceVisitor visitor); 37 39 38 /** 39 * <p> 40 * compares an instance to another one. Returns true if both instances are the same, i.e. not 41 * only the related task is equal but also all children and further characteristics of the 42 * task instance 43 * </p> 44 * 45 * @param taskInstance the instance to compare to 46 * 47 * @return as described 48 */ 49 public boolean equals(ITaskInstance taskInstance); 40 /** 41 * <p> 42 * clones a task instance by creating exact clones of each contained child 43 * instance as well as the related task. Furthermore, all other non 44 * transient information of the task instance must be cloned. 45 * </p> 46 * 47 * @return a clone of the task instance 48 */ 49 public ITaskInstance clone(); 50 50 51 /** 52 * <p> 53 * returns a hash code for the task instance to be able to put it into hash maps 54 * </p> 55 * 56 * @return as described 57 */ 58 public int hashCode(); 51 /** 52 * <p> 53 * compares an instance to another one. Returns true if both instances are 54 * the same, i.e. not only the related task is equal but also all children 55 * and further characteristics of the task instance 56 * </p> 57 * 58 * @param taskInstance 59 * the instance to compare to 60 * 61 * @return as described 62 */ 63 public boolean equals(ITaskInstance taskInstance); 59 64 60 /** 61 * <p> 62 * clones a task instance by creating exact clones of each contained child instance as well 63 * as the related task. Furthermore, all other non transient information of the task 64 * instance must be cloned. 65 * </p> 66 * 67 * @return a clone of the task instance 68 */ 69 public ITaskInstance clone(); 65 /** 66 * <p> 67 * returns the task related to the instance. 68 * </p> 69 * 70 * @return as described 71 */ 72 public ITask getTask(); 70 73 71 /** 72 * <p> 73 * implements the visitor pattern to be able to process task instances and their children. 74 * </p> 75 * 76 * @param visitor the visitor used to process the task 77 */ 78 public void accept(ITaskInstanceVisitor visitor); 79 74 /** 75 * <p> 76 * returns a hash code for the task instance to be able to put it into hash 77 * maps 78 * </p> 79 * 80 * @return as described 81 */ 82 @Override 83 public int hashCode(); 84 80 85 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskInstanceList.java
r1350 r1733 19 19 /** 20 20 * <p> 21 * represents a serializable and iterable representation of a read only list of task 22 * instances. The list is ordered. It does not provide methods for changing it. 21 * represents a serializable and iterable representation of a read only list of 22 * task instances. The list is ordered. It does not provide methods for changing 23 * it. 23 24 * </p> 24 25 * 25 26 * @author Patrick Harms 26 27 */ 27 public interface ITaskInstanceList extends Cloneable, Serializable, Iterable<ITaskInstance> { 28 public interface ITaskInstanceList extends Cloneable, Serializable, 29 Iterable<ITaskInstance> { 28 30 29 /** 30 * <p> 31 * returns the task instance at the position with the given index. May throw an exception 32 * if the index is invalid. 33 * </p> 34 * 35 * @param index the index of the task instance to be returned 36 * 37 * @return the task instance at the given index 38 */ 39 public ITaskInstance get(int index); 31 /** 32 * <p> 33 * returns the task instance at the position with the given index. May throw 34 * an exception if the index is invalid. 35 * </p> 36 * 37 * @param index 38 * the index of the task instance to be returned 39 * 40 * @return the task instance at the given index 41 */ 42 public ITaskInstance get(int index); 40 43 41 /** 42 * <p> 43 * returns the size of the list, i.e. the number of task instances in the list 44 * </p> 45 * 46 * @return as described 47 */ 48 public int size(); 44 /** 45 * <p> 46 * returns the size of the list, i.e. the number of task instances in the 47 * list 48 * </p> 49 * 50 * @return as described 51 */ 52 public int size(); 49 53 50 54 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskInstanceVisitor.java
r1405 r1733 15 15 package de.ugoe.cs.autoquest.tasktrees.treeifc; 16 16 17 18 17 /** 19 18 * <p> 20 * This is an implementation of the visitor pattern. Through this, it is possible to effectively21 * p rocess a task instance tree.19 * This is an implementation of the visitor pattern. Through this, it is 20 * possible to effectively process a task instance tree. 22 21 * </p> 23 22 * … … 26 25 public interface ITaskInstanceVisitor { 27 26 28 /** 29 * <p> 30 * method called for each visited event task instance. 31 * </p> 32 * 33 * @param eventTaskInstance the event task instance to be processed 34 */ 35 public void visit(IEventTaskInstance eventTaskInstance); 36 37 /** 38 * <p> 39 * method called for each visited iteration instance. 40 * </p> 41 * 42 * @param iterationInstance the iteration instance to be processed 43 */ 44 public void visit(IIterationInstance iterationInstance); 45 46 /** 47 * <p> 48 * method called for each visited optional instance. 49 * </p> 50 * 51 * @param optionalInstance the optional instance to be processed 52 */ 53 public void visit(IOptionalInstance optionalInstance); 54 55 /** 56 * <p> 57 * method called for each visited selection instance. 58 * </p> 59 * 60 * @param selectionInstance the selection instance to be processed 61 */ 62 public void visit(ISelectionInstance selectionInstance); 63 64 /** 65 * <p> 66 * method called for each visited sequence instance. 67 * </p> 68 * 69 * @param sequenceInstance the sequence instance to be processed 70 */ 71 public void visit(ISequenceInstance sequenceInstance); 27 /** 28 * <p> 29 * method called for each visited event task instance. 30 * </p> 31 * 32 * @param eventTaskInstance 33 * the event task instance to be processed 34 */ 35 public void visit(IEventTaskInstance eventTaskInstance); 72 36 73 /** 74 * <p> 75 * method called for each other kind of visited task instance (implemented to support future 76 * versions). 77 * </p> 78 * 79 * @param taskInstance the task instance to be processed 80 */ 81 public void visit(ITaskInstance taskInstance); 82 37 /** 38 * <p> 39 * method called for each visited iteration instance. 40 * </p> 41 * 42 * @param iterationInstance 43 * the iteration instance to be processed 44 */ 45 public void visit(IIterationInstance iterationInstance); 46 47 /** 48 * <p> 49 * method called for each visited optional instance. 50 * </p> 51 * 52 * @param optionalInstance 53 * the optional instance to be processed 54 */ 55 public void visit(IOptionalInstance optionalInstance); 56 57 /** 58 * <p> 59 * method called for each visited selection instance. 60 * </p> 61 * 62 * @param selectionInstance 63 * the selection instance to be processed 64 */ 65 public void visit(ISelectionInstance selectionInstance); 66 67 /** 68 * <p> 69 * method called for each visited sequence instance. 70 * </p> 71 * 72 * @param sequenceInstance 73 * the sequence instance to be processed 74 */ 75 public void visit(ISequenceInstance sequenceInstance); 76 77 /** 78 * <p> 79 * method called for each other kind of visited task instance (implemented 80 * to support future versions). 81 * </p> 82 * 83 * @param taskInstance 84 * the task instance to be processed 85 */ 86 public void visit(ITaskInstance taskInstance); 87 83 88 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskModel.java
r1423 r1733 21 21 /** 22 22 * <p> 23 * This class represents a complete task model. A task model within AutoQUEST is usually generated 24 * based on user sessions. Therefore, the task model consists of the user sessions, the models 25 * of the identified tasks, as well as further information about the tasks (e.g. their 26 * occurrence count) for statistical processing. 23 * This class represents a complete task model. A task model within AutoQUEST is 24 * usually generated based on user sessions. Therefore, the task model consists 25 * of the user sessions, the models of the identified tasks, as well as further 26 * information about the tasks (e.g. their occurrence count) for statistical 27 * processing. 27 28 * </p> 28 29 * … … 31 32 public interface ITaskModel extends Cloneable, Serializable { 32 33 33 /** 34 * <p> 35 * returns the user sessions belonging to the model. The return value may be null in the case 36 * no user sessions are associated the the tasks in the model. 37 * </p> 38 * 39 * @return as described 40 */ 41 public List<IUserSession> getUserSessions(); 34 /** 35 * <p> 36 * creates a deep clone of the model including all tasks and user sessions. 37 * </p> 38 * 39 * @return as described 40 */ 41 public ITaskModel clone(); 42 42 43 44 45 * returns the tasks belonging to the model. The return value must not be null. However, 46 * it may be an empty list, if the model is an empty model. 47 48 * 49 50 51 public Collection<ITask> getTasks();43 /** 44 * <p> 45 * returns a list of all metrics calculated by this model for the tasks and 46 * stored in the respective task infos 47 * </p> 48 * 49 * @return as described 50 */ 51 public TaskMetric[] getAllMetrics(); 52 52 53 54 55 * returns additional info for the provided task. The method returns null, if the provided 56 *task does not belong to the model.57 58 59 60 61 53 /** 54 * <p> 55 * returns additional info for the provided task. The method returns null, 56 * if the provided task does not belong to the model. 57 * </p> 58 * 59 * @return as described 60 */ 61 public ITaskInfo getTaskInfo(ITask task); 62 62 63 64 65 * returns a list of all metrics calculated by this model for the tasks and stored in the66 * respective task infos 67 68 * 69 70 71 public TaskMetric[] getAllMetrics();63 /** 64 * <p> 65 * returns the tasks belonging to the model. The return value must not be 66 * null. However, it may be an empty list, if the model is an empty model. 67 * </p> 68 * 69 * @return as described 70 */ 71 public Collection<ITask> getTasks(); 72 72 73 /** 74 * <p> 75 * creates a deep clone of the model including all tasks and user sessions. 76 * </p> 77 * 78 * @return as described 79 */ 80 public ITaskModel clone(); 73 /** 74 * <p> 75 * returns the user sessions belonging to the model. The return value may be 76 * null in the case no user sessions are associated the the tasks in the 77 * model. 78 * </p> 79 * 80 * @return as described 81 */ 82 public List<IUserSession> getUserSessions(); 81 83 82 84 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskVisitor.java
r1213 r1733 15 15 package de.ugoe.cs.autoquest.tasktrees.treeifc; 16 16 17 18 17 /** 19 18 * <p> 20 * This is an implementation of the visitor pattern. Through this, it is possible to effectively21 * p rocess a task model.19 * This is an implementation of the visitor pattern. Through this, it is 20 * possible to effectively process a task model. 22 21 * </p> 23 22 * … … 26 25 public interface ITaskVisitor { 27 26 28 /** 29 * <p> 30 * method called for each visited event task. 31 * </p> 32 * 33 * @param eventTask the event task to be processed 34 */ 35 public void visit(IEventTask eventTask); 36 37 /** 38 * <p> 39 * method called for each visited iteration. 40 * </p> 41 * 42 * @param iteration the iteration to be processed 43 */ 44 public void visit(IIteration iteration); 45 46 /** 47 * <p> 48 * method called for each visited optional. 49 * </p> 50 * 51 * @param optional the optional to be processed 52 */ 53 public void visit(IOptional optional); 54 55 /** 56 * <p> 57 * method called for each visited selection. 58 * </p> 59 * 60 * @param selection the selection to be processed 61 */ 62 public void visit(ISelection selection); 63 64 /** 65 * <p> 66 * method called for each visited sequence. 67 * </p> 68 * 69 * @param sequence the sequence to be processed 70 */ 71 public void visit(ISequence sequence); 27 /** 28 * <p> 29 * method called for each visited event task. 30 * </p> 31 * 32 * @param eventTask 33 * the event task to be processed 34 */ 35 public void visit(IEventTask eventTask); 72 36 73 /** 74 * <p> 75 * method called for each other kind of visited task (implemented to support future versions). 76 * </p> 77 * 78 * @param task the task to be processed 79 */ 80 public void visit(ITask task); 81 37 /** 38 * <p> 39 * method called for each visited iteration. 40 * </p> 41 * 42 * @param iteration 43 * the iteration to be processed 44 */ 45 public void visit(IIteration iteration); 46 47 /** 48 * <p> 49 * method called for each visited optional. 50 * </p> 51 * 52 * @param optional 53 * the optional to be processed 54 */ 55 public void visit(IOptional optional); 56 57 /** 58 * <p> 59 * method called for each visited selection. 60 * </p> 61 * 62 * @param selection 63 * the selection to be processed 64 */ 65 public void visit(ISelection selection); 66 67 /** 68 * <p> 69 * method called for each visited sequence. 70 * </p> 71 * 72 * @param sequence 73 * the sequence to be processed 74 */ 75 public void visit(ISequence sequence); 76 77 /** 78 * <p> 79 * method called for each other kind of visited task (implemented to support 80 * future versions). 81 * </p> 82 * 83 * @param task 84 * the task to be processed 85 */ 86 public void visit(ITask task); 87 82 88 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITemporalRelationship.java
r1180 r1733 17 17 /** 18 18 * <p> 19 * A temporal relationship is a node in a task model which is no leaf node. They are used to 20 * structure the tasks in a task model into useful orders. A temporal relationship defines through 21 * its type how its children can be executed to fulfill the task they represent themselves. E.g., 22 * the task of filling out a form can be subdivided into several subtasks for filling out the 23 * different elements of the. The task itself will define the order, in which the fill out process 24 * can and must be done. 19 * A temporal relationship is a node in a task model which is no leaf node. They 20 * are used to structure the tasks in a task model into useful orders. A 21 * temporal relationship defines through its type how its children can be 22 * executed to fulfill the task they represent themselves. E.g., the task of 23 * filling out a form can be subdivided into several subtasks for filling out 24 * the different elements of the. The task itself will define the order, in 25 * which the fill out process can and must be done. 25 26 * </p> 26 27 * … … 29 30 public interface ITemporalRelationship extends ITask { 30 31 31 /** 32 * <p> 33 * returns an exact copy of this temporal relationship. The clone has the same id. Its children 34 * are clones of the children of the cloned task. A call on the method {@link #equals(ITask)} 35 * with the result of this method must return true. 36 * </p> 37 * 38 * @return as described 39 */ 40 public ITemporalRelationship clone(); 32 /** 33 * <p> 34 * returns an exact copy of this temporal relationship. The clone has the 35 * same id. Its children are clones of the children of the cloned task. A 36 * call on the method {@link #equals(ITask)} with the result of this method 37 * must return true. 38 * </p> 39 * 40 * @return as described 41 */ 42 @Override 43 public ITemporalRelationship clone(); 41 44 42 45 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IUserSession.java
r1177 r1733 19 19 /** 20 20 * <p> 21 * A user session represents task executions, i.e. a task instances of a specific user that were 22 * executed in a coherent manner. Therefore, they are an ordered list of task instances where 23 * the order denotes the order of the task executions. 21 * A user session represents task executions, i.e. a task instances of a 22 * specific user that were executed in a coherent manner. Therefore, they are an 23 * ordered list of task instances where the order denotes the order of the task 24 * executions. 24 25 * </p> 25 26 * … … 28 29 public interface IUserSession extends ITaskInstanceList { 29 30 30 /** 31 * <p> 32 * returns the list of task instances executed in the represented session. 33 * </p> 34 * 35 * @return as described 36 */ 37 public List<ITaskInstance> getExecutedTasks(); 38 39 /** 40 * <p> 41 * compares the user session with another one. Two user sessions are only equal, if they 42 * contain the same number of task instances and if each task instance at each position is 43 * equal to the respective other session. 44 * </p> 45 * 46 * @param userSession the session to compare the session to 47 * 48 * @return true if both sessions are equal, false else 49 */ 50 public boolean equals(IUserSession userSession); 31 /** 32 * <p> 33 * clones a user session by creating exact clones of each contained instance 34 * in their order 35 * </p> 36 * 37 * @return a clone of the session 38 */ 39 public IUserSession clone(); 51 40 52 /** 53 * <p> 54 * returns a hash code for the session to be able to store the session in a hash map. 55 * </p> 56 * 57 * @return as described 58 */ 59 public int hashCode(); 41 /** 42 * <p> 43 * compares the user session with another one. Two user sessions are only 44 * equal, if they contain the same number of task instances and if each task 45 * instance at each position is equal to the respective other session. 46 * </p> 47 * 48 * @param userSession 49 * the session to compare the session to 50 * 51 * @return true if both sessions are equal, false else 52 */ 53 public boolean equals(IUserSession userSession); 60 54 61 /** 62 * <p> 63 * clones a user session by creating exact clones of each contained instance in their order 64 * </p> 65 * 66 * @return a clone of the session 67 */ 68 public IUserSession clone(); 55 /** 56 * <p> 57 * returns the list of task instances executed in the represented session. 58 * </p> 59 * 60 * @return as described 61 */ 62 public List<ITaskInstance> getExecutedTasks(); 63 64 /** 65 * <p> 66 * returns a hash code for the session to be able to store the session in a 67 * hash map. 68 * </p> 69 * 70 * @return as described 71 */ 72 @Override 73 public int hashCode(); 69 74 70 75 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/TaskMetric.java
r1494 r1733 19 19 /** 20 20 * <p> 21 * represents different metrics available or calculatable for tasks. Measure for the metrics 22 * are calculated by a task model and added to the task infos of a specific task. 21 * represents different metrics available or calculatable for tasks. Measure for 22 * the metrics are calculated by a task model and added to the task infos of a 23 * specific task. 23 24 * </p> 24 25 * … … 27 28 public enum TaskMetric { 28 29 29 COUNT("count", "number of all occurrences of the task in the model"), 30 DEPTH("depth", 31 "the maximum depth of the task, i.e., the number of children levels including the " + 32 "level of the task itself"), 33 EVENT_COVERAGE("covered events", "number of all event task instances covered by the task"), 34 EVENT_COVERAGE_RATIO("event coverage ratio", 35 "the ratio of events covered by this task in relation to all events " + 36 "covered by all tasks in their instances in per mille", 0.1, "%"), 37 EVENT_COVERAGE_QUANTILE("event coverage ratio quantile", 38 "the quantile of with respect to all event coverages begining with " + 39 "the lowest", 0.1, "%"); 40 41 /** 42 * <p> 43 * the name of the metric 44 * </p> 45 */ 46 private String name; 47 48 /** 49 * <p> 50 * a human readable description of the metric 51 * </p> 52 */ 53 private String description; 30 COUNT("count", "number of all occurrences of the task in the model"), DEPTH( 31 "depth", 32 "the maximum depth of the task, i.e., the number of children levels including the " 33 + "level of the task itself"), EVENT_COVERAGE( 34 "covered events", 35 "number of all event task instances covered by the task"), EVENT_COVERAGE_RATIO( 36 "event coverage ratio", 37 "the ratio of events covered by this task in relation to all events " 38 + "covered by all tasks in their instances in per mille", 39 0.1, "%"), EVENT_COVERAGE_QUANTILE("event coverage ratio quantile", 40 "the quantile of with respect to all event coverages begining with " 41 + "the lowest", 0.1, "%"); 54 42 55 /** 56 * <p> 57 * a scale applied for the metric when formatting the value 58 * </p> 59 */ 60 private double formatScale; 61 62 /** 63 * <p> 64 * the unit of the metric used when formatting the value 65 * </p> 66 */ 67 private String formatUnit; 68 69 /** 70 * <p> 71 * initializes the metric with a name and a description 72 * </p> 73 */ 74 private TaskMetric(String name, String description) { 75 this.name = name; 76 this.description = description; 77 this.formatScale = 1.0; 78 this.formatUnit = null; 79 } 43 /** 44 * <p> 45 * the name of the metric 46 * </p> 47 */ 48 private String name; 80 49 81 /** 82 * <p> 83 * initializes the metric with a name and a description, as well as with a scale and a unit for 84 * formatting it. 85 * </p> 86 */ 87 private TaskMetric(String name, String description, double formatScale, String formatUnit) { 88 this.name = name; 89 this.description = description; 90 this.formatScale = formatScale; 91 this.formatUnit = formatUnit; 92 } 50 /** 51 * <p> 52 * a human readable description of the metric 53 * </p> 54 */ 55 private String description; 93 56 94 /** 95 * <p> 96 * returns the name of the metric 97 * </p> 98 * 99 * @return the name of the metric 100 */ 101 public String getName() { 102 return name; 103 } 57 /** 58 * <p> 59 * a scale applied for the metric when formatting the value 60 * </p> 61 */ 62 private double formatScale; 104 63 105 /** 106 * <p> 107 * returns the human readable description of the metric 108 * </p> 109 * 110 * @return the human readable description of the metric 111 */ 112 public String getDescription() { 113 return description; 114 } 115 116 /** 117 * <p> 118 * formats the provided value of a measure of the metric using the internal format scale and 119 * unit. 120 * </p> 121 * 122 * @return the formatted value depending on the scale and unit of the metric 123 */ 124 public String formatValue(int value) { 125 String formattedValue; 126 127 if (formatScale != 1.0) { 128 double effectiveValue = formatScale * value; 129 formattedValue = new DecimalFormat( "#,##0.0;(#)").format(effectiveValue); 130 } 131 else { 132 formattedValue = Integer.toString(value); 133 } 134 135 if (formatUnit != null) { 136 formattedValue += formatUnit; 137 } 138 139 return formattedValue; 140 } 64 /** 65 * <p> 66 * the unit of the metric used when formatting the value 67 * </p> 68 */ 69 private String formatUnit; 70 71 /** 72 * <p> 73 * initializes the metric with a name and a description 74 * </p> 75 */ 76 private TaskMetric(String name, String description) { 77 this.name = name; 78 this.description = description; 79 this.formatScale = 1.0; 80 this.formatUnit = null; 81 } 82 83 /** 84 * <p> 85 * initializes the metric with a name and a description, as well as with a 86 * scale and a unit for formatting it. 87 * </p> 88 */ 89 private TaskMetric(String name, String description, double formatScale, 90 String formatUnit) { 91 this.name = name; 92 this.description = description; 93 this.formatScale = formatScale; 94 this.formatUnit = formatUnit; 95 } 96 97 /** 98 * <p> 99 * formats the provided value of a measure of the metric using the internal 100 * format scale and unit. 101 * </p> 102 * 103 * @return the formatted value depending on the scale and unit of the metric 104 */ 105 public String formatValue(int value) { 106 String formattedValue; 107 108 if (formatScale != 1.0) { 109 final double effectiveValue = formatScale * value; 110 formattedValue = new DecimalFormat("#,##0.0;(#)") 111 .format(effectiveValue); 112 } else { 113 formattedValue = Integer.toString(value); 114 } 115 116 if (formatUnit != null) { 117 formattedValue += formatUnit; 118 } 119 120 return formattedValue; 121 } 122 123 /** 124 * <p> 125 * returns the human readable description of the metric 126 * </p> 127 * 128 * @return the human readable description of the metric 129 */ 130 public String getDescription() { 131 return description; 132 } 133 134 /** 135 * <p> 136 * returns the name of the metric 137 * </p> 138 * 139 * @return the name of the metric 140 */ 141 public String getName() { 142 return name; 143 } 141 144 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/EventTask.java
r1410 r1733 20 20 /** 21 21 * <p> 22 * this is the default implementation of the interface {@link IEventTask}. It does not do anything23 * fancy except implementing the interface.24 * </p> 22 * this is the default implementation of the interface {@link IEventTask}. It 23 * does not do anything fancy except implementing the interface. 24 * </p> 25 25 * 26 26 * @author Patrick Harms 27 27 */ 28 28 class EventTask extends Task implements IEventTask { 29 30 /**31 * <p>32 * default serial version UID33 * </p>34 */35 private static final long serialVersionUID = 1L;36 29 37 /** 38 * <p> 39 * simple constructor initializing this task with a description for the represented events 40 * </p> 41 * 42 * @param type a type for the represented events 43 */ 44 EventTask(String type) { 45 super(type); 46 } 30 /** 31 * <p> 32 * default serial version UID 33 * </p> 34 */ 35 private static final long serialVersionUID = 1L; 47 36 48 /* (non-Javadoc) 49 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.Task#clone() 50 */ 51 @Override 52 public EventTask clone() { 53 // Event type and target are unchangeable and do not need to be cloned 54 return (EventTask) super.clone(); 55 } 37 /** 38 * <p> 39 * simple constructor initializing this task with a description for the 40 * represented events 41 * </p> 42 * 43 * @param type 44 * a type for the represented events 45 */ 46 EventTask(String type) { 47 super(type); 48 } 56 49 57 /* (non-Javadoc) 58 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.Task#accept(ITaskVisitor) 59 */ 60 @Override 61 public void accept(ITaskVisitor visitor) { 62 visitor.visit(this); 63 } 50 /* 51 * (non-Javadoc) 52 * 53 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.Task#accept(ITaskVisitor) 54 */ 55 @Override 56 public void accept(ITaskVisitor visitor) { 57 visitor.visit(this); 58 } 59 60 /* 61 * (non-Javadoc) 62 * 63 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.Task#clone() 64 */ 65 @Override 66 public EventTask clone() { 67 // Event type and target are unchangeable and do not need to be cloned 68 return (EventTask) super.clone(); 69 } 64 70 65 71 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/EventTaskInstance.java
r1414 r1733 28 28 class EventTaskInstance extends TaskInstance implements IEventTaskInstance { 29 29 30 /** 31 * <p> 32 * default serial version UID 33 * </p> 34 */ 35 private static final long serialVersionUID = 1L; 36 37 /** 38 * <p> 39 * the event represented by this instance 40 * </p> 41 */ 42 private Event event; 30 /** 31 * <p> 32 * default serial version UID 33 * </p> 34 */ 35 private static final long serialVersionUID = 1L; 43 36 44 /** 45 * <p> 46 * initializes this instance with the respective task model and the represented event 47 * </p> 48 * 49 * @param task the task of which this is an instance 50 * @param event the event represented by this instance 51 */ 52 EventTaskInstance(IEventTask task, Event event) { 53 super(task); 54 this.event = event; 55 } 37 /** 38 * <p> 39 * the event represented by this instance 40 * </p> 41 */ 42 private final Event event; 56 43 57 /* (non-Javadoc) 58 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance#getEvent() 59 */ 60 @Override 61 public Event getEvent() { 62 return event; 63 } 44 /** 45 * <p> 46 * initializes this instance with the respective task model and the 47 * represented event 48 * </p> 49 * 50 * @param task 51 * the task of which this is an instance 52 * @param event 53 * the event represented by this instance 54 */ 55 EventTaskInstance(IEventTask task, Event event) { 56 super(task); 57 this.event = event; 58 } 64 59 65 /* (non-Javadoc) 66 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance#getEventTask() 67 */ 68 @Override 69 public IEventTask getEventTask() { 70 return (IEventTask) super.getTask(); 71 } 60 /* 61 * (non-Javadoc) 62 * 63 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.IEventTaskInstance#clone() 64 */ 65 @Override 66 public synchronized IEventTaskInstance clone() { 67 return (IEventTaskInstance) super.clone(); 68 } 72 69 73 /* (non-Javadoc) 74 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.IEventTaskInstance#clone() 75 */ 76 @Override 77 public synchronized IEventTaskInstance clone() { 78 return (IEventTaskInstance) super.clone(); 79 } 70 /* 71 * (non-Javadoc) 72 * 73 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance#getEvent() 74 */ 75 @Override 76 public Event getEvent() { 77 return event; 78 } 79 80 /* 81 * (non-Javadoc) 82 * 83 * @see 84 * de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance#getEventTask() 85 */ 86 @Override 87 public IEventTask getEventTask() { 88 return (IEventTask) super.getTask(); 89 } 80 90 81 91 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/Iteration.java
r1215 r1733 21 21 /** 22 22 * <p> 23 * this is the default implementation of the interface {@link IIteration}. It does not do anything24 * fancy except implementing the interface.25 * </p> 23 * this is the default implementation of the interface {@link IIteration}. It 24 * does not do anything fancy except implementing the interface. 25 * </p> 26 26 * 27 27 * @author Patrick Harms … … 29 29 class Iteration extends MarkingTemporalRelationship implements IIteration { 30 30 31 32 33 34 35 36 31 /** 32 * <p> 33 * default serial version UID 34 * </p> 35 */ 36 private static final long serialVersionUID = 1L; 37 37 38 39 40 * simple constructor providing the base class with a human readable name of the type of this 41 *task42 43 44 45 46 38 /** 39 * <p> 40 * simple constructor providing the base class with a human readable name of 41 * the type of this task 42 * </p> 43 */ 44 Iteration() { 45 super("iteration"); 46 } 47 47 48 /* (non-Javadoc) 49 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.MarkingTemporalRelationship#setMarkedTask(ITask) 50 */ 51 @Override 52 protected void setMarkedTask(ITask markedTask) { 53 if (markedTask instanceof IIteration) { 54 throw new IllegalArgumentException 55 ("the marked task of an iteration must not be an iteration"); 56 } 57 else if (markedTask instanceof IOptional) { 58 throw new IllegalArgumentException 59 ("the marked task of an iteration must not be an optional"); 60 } 61 62 super.setMarkedTask(markedTask); 63 } 48 /* 49 * (non-Javadoc) 50 * 51 * @see 52 * de.ugoe.cs.autoquest.tasktrees.treeimpl.MarkingTemporalRelationship#clone 53 * () 54 */ 55 @Override 56 public Iteration clone() { 57 return (Iteration) super.clone(); 58 } 64 59 65 /* (non-Javadoc) 66 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.MarkingTemporalRelationship#clone() 67 */ 68 @Override 69 public Iteration clone() { 70 return (Iteration) super.clone(); 71 } 72 60 /* 61 * (non-Javadoc) 62 * 63 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.MarkingTemporalRelationship# 64 * setMarkedTask(ITask) 65 */ 66 @Override 67 protected void setMarkedTask(ITask markedTask) { 68 if (markedTask instanceof IIteration) { 69 throw new IllegalArgumentException( 70 "the marked task of an iteration must not be an iteration"); 71 } else if (markedTask instanceof IOptional) { 72 throw new IllegalArgumentException( 73 "the marked task of an iteration must not be an optional"); 74 } 75 76 super.setMarkedTask(markedTask); 77 } 78 73 79 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/IterationInstance.java
r1414 r1733 33 33 class IterationInstance extends TaskInstance implements IIterationInstance { 34 34 35 36 37 38 39 40 35 /** 36 * <p> 37 * default serial version UID 38 * </p> 39 */ 40 private static final long serialVersionUID = 1L; 41 41 42 43 44 45 46 47 42 /** 43 * <p> 44 * the children of this task instance which are task instances, as well 45 * </p> 46 */ 47 private List<ITaskInstance> children; 48 48 49 /** 50 * <p> 51 * initializes this instance with the respective task model 52 * </p> 53 * 54 * @param task the task of which this is an instance 55 */ 56 IterationInstance(IIteration task) { 57 super(task); 58 } 49 /** 50 * <p> 51 * initializes this instance with the respective task model 52 * </p> 53 * 54 * @param task 55 * the task of which this is an instance 56 */ 57 IterationInstance(IIteration task) { 58 super(task); 59 } 59 60 60 /* (non-Javadoc) 61 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance#getChildren() 62 */ 63 public synchronized List<ITaskInstance> getChildren() { 64 if (children == null) { 65 children = new LinkedList<ITaskInstance>(); 66 } 61 /** 62 * <p> 63 * used to add a child to this task instance at a specific position 64 * </p> 65 * 66 * @param index 67 * the position of the new child in the list of children 68 * @param child 69 * the new child of this instance 70 */ 71 synchronized void addChild(int index, ITaskInstance child) { 72 if (children == null) { 73 children = new LinkedList<ITaskInstance>(); 74 } 67 75 68 return Collections.unmodifiableList(children);69 76 children.add(index, child); 77 } 70 78 71 /* (non-Javadoc) 72 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList#get(int) 73 */ 74 @Override 75 public ITaskInstance get(int index) { 76 if (children == null) { 77 throw new IndexOutOfBoundsException(Integer.toString(index)); 78 } 79 else{80 return children.get(index); 81 } 82 79 /** 80 * <p> 81 * used to add a child to this task instance 82 * </p> 83 * 84 * @param child 85 * the new child of this instance 86 */ 87 synchronized void addChild(ITaskInstance child) { 88 if (children == null) { 89 children = new LinkedList<ITaskInstance>(); 90 } 83 91 84 /* (non-Javadoc) 85 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList#size() 86 */ 87 @Override 88 public int size() { 89 if (children == null) { 90 return 0; 91 } 92 else { 93 return children.size(); 94 } 95 } 92 children.add(child); 93 } 96 94 97 /* (non-Javadoc) 98 * @see java.lang.Iterable#iterator() 99 */ 100 @Override 101 public Iterator<ITaskInstance> iterator() { 102 return getChildren().iterator(); 103 } 95 /* 96 * (non-Javadoc) 97 * 98 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.IIterationInstance#clone() 99 */ 100 @Override 101 public synchronized IIterationInstance clone() { 102 final IterationInstance clone = (IterationInstance) super.clone(); 104 103 105 /* (non-Javadoc) 106 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.IIterationInstance#getIteration() 107 */ 108 @Override 109 public IIteration getIteration() { 110 return (IIteration) super.getTask(); 111 } 104 if (children != null) { 105 clone.children = new LinkedList<ITaskInstance>(); 112 106 113 /* (non-Javadoc) 114 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.IIterationInstance#clone() 115 */ 116 @Override 117 public synchronized IIterationInstance clone() { 118 IterationInstance clone = (IterationInstance) super.clone(); 107 for (final ITaskInstance child : children) { 108 clone.children.add(child.clone()); 109 } 110 } 119 111 120 if (children != null) { 121 clone.children = new LinkedList<ITaskInstance>(); 112 return clone; 113 } 122 114 123 for (ITaskInstance child : children) { 124 clone.children.add(child.clone()); 125 } 126 } 115 /* 116 * (non-Javadoc) 117 * 118 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList#get(int) 119 */ 120 @Override 121 public ITaskInstance get(int index) { 122 if (children == null) { 123 throw new IndexOutOfBoundsException(Integer.toString(index)); 124 } else { 125 return children.get(index); 126 } 127 } 127 128 128 return clone; 129 } 129 /* 130 * (non-Javadoc) 131 * 132 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance#getChildren() 133 */ 134 public synchronized List<ITaskInstance> getChildren() { 135 if (children == null) { 136 children = new LinkedList<ITaskInstance>(); 137 } 130 138 131 /** 132 * <p> 133 * used to add a child to this task instance 134 * </p> 135 * 136 * @param child the new child of this instance 137 */ 138 synchronized void addChild(ITaskInstance child) { 139 if (children == null) { 140 children = new LinkedList<ITaskInstance>(); 141 } 139 return Collections.unmodifiableList(children); 140 } 142 141 143 children.add(child); 144 } 142 /* 143 * (non-Javadoc) 144 * 145 * @see 146 * de.ugoe.cs.autoquest.tasktrees.treeifc.IIterationInstance#getIteration() 147 */ 148 @Override 149 public IIteration getIteration() { 150 return (IIteration) super.getTask(); 151 } 145 152 146 /** 147 * <p> 148 * used to add a child to this task instance at a specific position 149 * </p> 150 * 151 * @param index the position of the new child in the list of children 152 * @param child the new child of this instance 153 */ 154 synchronized void addChild(int index, ITaskInstance child) { 155 if (children == null) { 156 children = new LinkedList<ITaskInstance>(); 157 } 153 /* 154 * (non-Javadoc) 155 * 156 * @see java.lang.Iterable#iterator() 157 */ 158 @Override 159 public Iterator<ITaskInstance> iterator() { 160 return getChildren().iterator(); 161 } 158 162 159 children.add(index, child); 160 } 163 /** 164 * <p> 165 * removes a child from this task instance at a specific position 166 * </p> 167 * 168 * @param index 169 * the position of the child to be removed 170 * 171 * @return the child removed from the children of this instance 172 */ 173 synchronized ITaskInstance removeChild(int index) { 174 if (children != null) { 175 return children.remove(index); 176 } else { 177 throw new IllegalArgumentException( 178 "this task instance does not have children that can be removed"); 179 } 180 } 161 181 162 /** 163 * <p> 164 * removes a child from this task instance at a specific position 165 * </p> 166 * 167 * @param index the position of the child to be removed 168 * 169 * @return the child removed from the children of this instance 170 */ 171 synchronized ITaskInstance removeChild(int index) { 172 if (children != null) { 173 return children.remove(index); 174 } 175 else { 176 throw new IllegalArgumentException 177 ("this task instance does not have children that can be removed"); 178 } 179 } 182 /* 183 * (non-Javadoc) 184 * 185 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList#size() 186 */ 187 @Override 188 public int size() { 189 if (children == null) { 190 return 0; 191 } else { 192 return children.size(); 193 } 194 } 180 195 181 196 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/MarkingTemporalRelationship.java
r1357 r1733 20 20 /** 21 21 * <p> 22 * this is the default implementation of the interface {@link IMarkingTemporalRelationship}. It 23 * does not do anything fancy except implementing the interface. 22 * this is the default implementation of the interface 23 * {@link IMarkingTemporalRelationship}. It does not do anything fancy except 24 * implementing the interface. 24 25 * </p> 25 26 * 26 27 * @author Patrick Harms 27 28 */ 28 abstract class MarkingTemporalRelationship extends Task 29 implements IMarkingTemporalRelationship 30 { 29 abstract class MarkingTemporalRelationship extends Task implements 30 IMarkingTemporalRelationship { 31 31 32 33 34 35 36 37 32 /** 33 * <p> 34 * default serial version UID 35 * </p> 36 */ 37 private static final long serialVersionUID = 1L; 38 38 39 /** 40 * <p> 41 * the task marked through this marking temporal relationship 42 * </p> 43 */ 44 private ITask markedTask; 45 46 /** 47 * <p> 48 * initializes this temporal relationship with a human readable name 49 * </p> 50 * 51 * @param relationshipType the human readable name of this temporal relationship 52 */ 53 MarkingTemporalRelationship(String relationshipType) { 54 super(relationshipType); 55 56 if ((relationshipType == null) || ("".equals(relationshipType))) { 57 throw new IllegalArgumentException 58 ("the relationship type must be something meaningful"); 59 } 60 } 39 /** 40 * <p> 41 * the task marked through this marking temporal relationship 42 * </p> 43 */ 44 private ITask markedTask; 61 45 62 /* (non-Javadoc) 63 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.IMarkingTemporalRelationship#getMarkedTask() 64 */ 65 @Override 66 public ITask getMarkedTask() { 67 return markedTask; 68 } 46 /** 47 * <p> 48 * initializes this temporal relationship with a human readable name 49 * </p> 50 * 51 * @param relationshipType 52 * the human readable name of this temporal relationship 53 */ 54 MarkingTemporalRelationship(String relationshipType) { 55 super(relationshipType); 69 56 70 /* (non-Javadoc) 71 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.Task#clone() 72 */ 73 @Override 74 public synchronized MarkingTemporalRelationship clone() { 75 MarkingTemporalRelationship clone = null; 76 clone = (MarkingTemporalRelationship) super.clone(); 77 78 if (markedTask != null) { 79 clone.markedTask = markedTask.clone(); 80 } 57 if ((relationshipType == null) || ("".equals(relationshipType))) { 58 throw new IllegalArgumentException( 59 "the relationship type must be something meaningful"); 60 } 61 } 81 62 82 return clone; 83 } 63 /* 64 * (non-Javadoc) 65 * 66 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.Task#clone() 67 */ 68 @Override 69 public synchronized MarkingTemporalRelationship clone() { 70 MarkingTemporalRelationship clone = null; 71 clone = (MarkingTemporalRelationship) super.clone(); 84 72 85 /** 86 * <p> 87 * used to set the marked task 88 * </p> 89 * 90 * @param markedTask the marked task to set 91 */ 92 protected void setMarkedTask(ITask markedTask) { 93 this.markedTask = markedTask; 94 95 super.setDescription(markedTask.toString()); 96 } 73 if (markedTask != null) { 74 clone.markedTask = markedTask.clone(); 75 } 76 77 return clone; 78 } 79 80 /* 81 * (non-Javadoc) 82 * 83 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.IMarkingTemporalRelationship# 84 * getMarkedTask() 85 */ 86 @Override 87 public ITask getMarkedTask() { 88 return markedTask; 89 } 90 91 /** 92 * <p> 93 * used to set the marked task 94 * </p> 95 * 96 * @param markedTask 97 * the marked task to set 98 */ 99 protected void setMarkedTask(ITask markedTask) { 100 this.markedTask = markedTask; 101 102 super.setDescription(markedTask.toString()); 103 } 97 104 98 105 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/Optional.java
r1215 r1733 20 20 /** 21 21 * <p> 22 * this is the default implementation of the interface {@link IOptional}. It does not do anything23 * fancy except implementing the interface.24 * </p> 22 * this is the default implementation of the interface {@link IOptional}. It 23 * does not do anything fancy except implementing the interface. 24 * </p> 25 25 * 26 26 * @author Patrick Harms … … 28 28 class Optional extends MarkingTemporalRelationship implements IOptional { 29 29 30 31 32 33 34 35 30 /** 31 * <p> 32 * default serial version UID 33 * </p> 34 */ 35 private static final long serialVersionUID = 1L; 36 36 37 /** 38 * <p> 39 * simple constructor providing the base class with a human readable name of the type of this 40 * task 41 * </p> 42 */ 43 Optional() { 44 super("optionality"); 45 } 46 47 /* (non-Javadoc) 48 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.MarkingTemporalRelationship#setMarkedTask(ITask) 49 */ 50 @Override 51 protected void setMarkedTask(ITask markedTask) { 52 if (markedTask instanceof IOptional) { 53 throw new IllegalArgumentException 54 ("the marked task of an optional must not be an optional"); 55 } 56 57 super.setMarkedTask(markedTask); 58 } 37 /** 38 * <p> 39 * simple constructor providing the base class with a human readable name of 40 * the type of this task 41 * </p> 42 */ 43 Optional() { 44 super("optionality"); 45 } 59 46 60 /* (non-Javadoc) 61 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.MarkingTemporalRelationship#clone() 62 */ 63 @Override 64 public Optional clone() { 65 return (Optional) super.clone(); 66 } 47 /* 48 * (non-Javadoc) 49 * 50 * @see 51 * de.ugoe.cs.autoquest.tasktrees.treeimpl.MarkingTemporalRelationship#clone 52 * () 53 */ 54 @Override 55 public Optional clone() { 56 return (Optional) super.clone(); 57 } 58 59 /* 60 * (non-Javadoc) 61 * 62 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.MarkingTemporalRelationship# 63 * setMarkedTask(ITask) 64 */ 65 @Override 66 protected void setMarkedTask(ITask markedTask) { 67 if (markedTask instanceof IOptional) { 68 throw new IllegalArgumentException( 69 "the marked task of an optional must not be an optional"); 70 } 71 72 super.setMarkedTask(markedTask); 73 } 67 74 68 75 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/OptionalInstance.java
r1414 r1733 29 29 class OptionalInstance extends TaskInstance implements IOptionalInstance { 30 30 31 32 33 34 35 36 31 /** 32 * <p> 33 * default serial version UID 34 * </p> 35 */ 36 private static final long serialVersionUID = 1L; 37 37 38 /** 39 * <p> 40 * the child of this task instance if any 41 * </p> 42 */ 43 private ITaskInstance child; 44 45 /** 46 * <p> 47 * initializes this instance with the respective task model 48 * </p> 49 * 50 * @param task the task of which this is an instance 51 */ 52 OptionalInstance(ITask task) { 53 super(task); 54 } 38 /** 39 * <p> 40 * the child of this task instance if any 41 * </p> 42 */ 43 private ITaskInstance child; 55 44 56 /* (non-Javadoc) 57 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.IOptionalInstance#getChild() 58 */ 59 @Override 60 public ITaskInstance getChild() { 61 return child; 62 } 45 /** 46 * <p> 47 * initializes this instance with the respective task model 48 * </p> 49 * 50 * @param task 51 * the task of which this is an instance 52 */ 53 OptionalInstance(ITask task) { 54 super(task); 55 } 63 56 64 /* (non-Javadoc) 65 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.IOptionalInstance#getOptional() 66 */ 67 @Override 68 public IOptional getOptional() { 69 return (IOptional) super.getTask(); 70 } 57 /* 58 * (non-Javadoc) 59 * 60 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.ISequenceInstance#clone() 61 */ 62 @Override 63 public synchronized IOptionalInstance clone() { 64 final OptionalInstance clone = (OptionalInstance) super.clone(); 71 65 72 /* (non-Javadoc) 73 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.ISequenceInstance#clone() 74 */ 75 @Override 76 public synchronized IOptionalInstance clone() { 77 OptionalInstance clone = (OptionalInstance) super.clone(); 66 if (child != null) { 67 clone.child = child.clone(); 68 } 78 69 79 if (child != null) { 80 clone.child = child.clone(); 81 } 70 return clone; 71 } 82 72 83 return clone; 84 } 73 /* 74 * (non-Javadoc) 75 * 76 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.IOptionalInstance#getChild() 77 */ 78 @Override 79 public ITaskInstance getChild() { 80 return child; 81 } 85 82 86 /** 87 * <p> 88 * used to set the child of this task instance 89 * </p> 90 * 91 * @param child the new child of this instance 92 */ 93 void setChild(ITaskInstance child) { 94 if (child instanceof IOptionalInstance) { 95 throw new IllegalArgumentException("the child of an optional can not be an optional"); 96 } 97 98 this.child = child; 99 } 83 /* 84 * (non-Javadoc) 85 * 86 * @see 87 * de.ugoe.cs.autoquest.tasktrees.treeifc.IOptionalInstance#getOptional() 88 */ 89 @Override 90 public IOptional getOptional() { 91 return (IOptional) super.getTask(); 92 } 93 94 /** 95 * <p> 96 * used to set the child of this task instance 97 * </p> 98 * 99 * @param child 100 * the new child of this instance 101 */ 102 void setChild(ITaskInstance child) { 103 if (child instanceof IOptionalInstance) { 104 throw new IllegalArgumentException( 105 "the child of an optional can not be an optional"); 106 } 107 108 this.child = child; 109 } 100 110 101 111 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/Selection.java
r1404 r1733 20 20 /** 21 21 * <p> 22 * this is the default implementation of the interface {@link ISelection}. It does not do anything23 * fancy except implementing the interface.24 * </p> 22 * this is the default implementation of the interface {@link ISelection}. It 23 * does not do anything fancy except implementing the interface. 24 * </p> 25 25 * 26 26 * @author Patrick Harms … … 28 28 class Selection extends StructuringTemporalRelationship implements ISelection { 29 29 30 31 32 33 34 35 30 /** 31 * <p> 32 * default serial version UID 33 * </p> 34 */ 35 private static final long serialVersionUID = 1L; 36 36 37 38 39 * simple constructor providing the base class with a human readable name of the type of this 40 *task41 42 43 44 45 37 /** 38 * <p> 39 * simple constructor providing the base class with a human readable name of 40 * the type of this task 41 * </p> 42 */ 43 Selection() { 44 super("selection"); 45 } 46 46 47 /* (non-Javadoc) 48 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.StructuringTemporalRelationship#clone() 49 */ 50 @Override 51 public Selection clone() { 52 return (Selection) super.clone(); 53 } 47 /* 48 * (non-Javadoc) 49 * 50 * @see 51 * de.ugoe.cs.autoquest.tasktrees.treeimpl.StructuringTemporalRelationship 52 * #addChild(int,ITask) 53 */ 54 @Override 55 void addChild(int index, ITask newChild) { 56 super.addChild(index, newChild); 57 } 54 58 55 /* (non-Javadoc) 56 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.StructuringTemporalRelationship#addChild(ITask) 57 */ 58 @Override 59 void addChild(ITask newChild) { 60 super.addChild(newChild); 61 } 59 /* 60 * (non-Javadoc) 61 * 62 * @see 63 * de.ugoe.cs.autoquest.tasktrees.treeimpl.StructuringTemporalRelationship 64 * #addChild(ITask) 65 */ 66 @Override 67 void addChild(ITask newChild) { 68 super.addChild(newChild); 69 } 62 70 63 /* (non-Javadoc) 64 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.StructuringTemporalRelationship#addChild(int,ITask) 65 */ 66 @Override 67 void addChild(int index, ITask newChild) { 68 super.addChild(index, newChild); 69 } 71 /* 72 * (non-Javadoc) 73 * 74 * @see 75 * de.ugoe.cs.autoquest.tasktrees.treeimpl.StructuringTemporalRelationship 76 * #clone() 77 */ 78 @Override 79 public Selection clone() { 80 return (Selection) super.clone(); 81 } 70 82 71 83 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/SelectionInstance.java
r1414 r1733 29 29 class SelectionInstance extends TaskInstance implements ISelectionInstance { 30 30 31 32 33 34 35 36 31 /** 32 * <p> 33 * default serial version UID 34 * </p> 35 */ 36 private static final long serialVersionUID = 1L; 37 37 38 /** 39 * <p> 40 * the child of this task instance 41 * </p> 42 */ 43 private ITaskInstance child; 44 45 /** 46 * <p> 47 * initializes this instance with the respective task model 48 * </p> 49 * 50 * @param task the task of which this is an instance 51 */ 52 SelectionInstance(ITask task) { 53 super(task); 54 } 38 /** 39 * <p> 40 * the child of this task instance 41 * </p> 42 */ 43 private ITaskInstance child; 55 44 56 /* (non-Javadoc) 57 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ISelectionInstance#getChild() 58 */ 59 @Override 60 public ITaskInstance getChild() { 61 return child; 62 } 45 /** 46 * <p> 47 * initializes this instance with the respective task model 48 * </p> 49 * 50 * @param task 51 * the task of which this is an instance 52 */ 53 SelectionInstance(ITask task) { 54 super(task); 55 } 63 56 64 /* (non-Javadoc) 65 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ISelectionInstance#getSelection() 66 */ 67 @Override 68 public ISelection getSelection() { 69 return (ISelection) super.getTask(); 70 } 57 /* 58 * (non-Javadoc) 59 * 60 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.ISequenceInstance#clone() 61 */ 62 @Override 63 public synchronized ISelectionInstance clone() { 64 final SelectionInstance clone = (SelectionInstance) super.clone(); 71 65 72 /* (non-Javadoc) 73 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.ISequenceInstance#clone() 74 */ 75 @Override 76 public synchronized ISelectionInstance clone() { 77 SelectionInstance clone = (SelectionInstance) super.clone(); 66 if (child != null) { 67 clone.child = child.clone(); 68 } 78 69 79 if (child != null) { 80 clone.child = child.clone(); 81 } 70 return clone; 71 } 82 72 83 return clone; 84 } 73 /* 74 * (non-Javadoc) 75 * 76 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ISelectionInstance#getChild() 77 */ 78 @Override 79 public ITaskInstance getChild() { 80 return child; 81 } 85 82 86 /** 87 * <p> 88 * used to set the child of this task instance 89 * </p> 90 * 91 * @param child the new child of this instance 92 */ 93 void setChild(ITaskInstance child) { 94 if (child instanceof ISelectionInstance) { 95 throw new IllegalArgumentException("the child of a selection can not be a selection"); 96 } 97 98 this.child = child; 99 } 83 /* 84 * (non-Javadoc) 85 * 86 * @see 87 * de.ugoe.cs.autoquest.tasktrees.treeifc.ISelectionInstance#getSelection() 88 */ 89 @Override 90 public ISelection getSelection() { 91 return (ISelection) super.getTask(); 92 } 93 94 /** 95 * <p> 96 * used to set the child of this task instance 97 * </p> 98 * 99 * @param child 100 * the new child of this instance 101 */ 102 void setChild(ITaskInstance child) { 103 if (child instanceof ISelectionInstance) { 104 throw new IllegalArgumentException( 105 "the child of a selection can not be a selection"); 106 } 107 108 this.child = child; 109 } 100 110 101 111 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/Sequence.java
r1215 r1733 19 19 /** 20 20 * <p> 21 * this is the default implementation of the interface {@link ISequence}. It does not do anything22 * fancy except implementing the interface.23 * </p> 21 * this is the default implementation of the interface {@link ISequence}. It 22 * does not do anything fancy except implementing the interface. 23 * </p> 24 24 * 25 25 * @author Patrick Harms 26 26 */ 27 27 class Sequence extends StructuringTemporalRelationship implements ISequence { 28 29 /**30 * <p>31 * default serial version UID32 * </p>33 */34 private static final long serialVersionUID = 1L;35 28 36 /** 37 * <p> 38 * simple constructor providing the base class with a human readable name of the type of this 39 * task 40 * </p> 41 */ 42 Sequence() { 43 super("sequence"); 44 } 29 /** 30 * <p> 31 * default serial version UID 32 * </p> 33 */ 34 private static final long serialVersionUID = 1L; 45 35 46 /* (non-Javadoc) 47 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.StructuringTemporalRelationship#clone() 48 */ 49 @Override 50 public Sequence clone() { 51 return (Sequence) super.clone(); 52 } 53 36 /** 37 * <p> 38 * simple constructor providing the base class with a human readable name of 39 * the type of this task 40 * </p> 41 */ 42 Sequence() { 43 super("sequence"); 44 } 45 46 /* 47 * (non-Javadoc) 48 * 49 * @see 50 * de.ugoe.cs.autoquest.tasktrees.treeimpl.StructuringTemporalRelationship 51 * #clone() 52 */ 53 @Override 54 public Sequence clone() { 55 return (Sequence) super.clone(); 56 } 57 54 58 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/SequenceInstance.java
r1414 r1733 34 34 class SequenceInstance extends TaskInstance implements ISequenceInstance { 35 35 36 37 38 39 40 41 36 /** 37 * <p> 38 * default serial version UID 39 * </p> 40 */ 41 private static final long serialVersionUID = 1L; 42 42 43 44 45 46 47 48 43 /** 44 * <p> 45 * the children of this task instance which are task instances, as well 46 * </p> 47 */ 48 private List<ITaskInstance> children; 49 49 50 /** 51 * <p> 52 * initializes this instance with the respective task model 53 * </p> 54 * 55 * @param task the task of which this is an instance 56 */ 57 SequenceInstance(ISequence task) { 58 super(task); 59 } 50 /** 51 * <p> 52 * initializes this instance with the respective task model 53 * </p> 54 * 55 * @param task 56 * the task of which this is an instance 57 */ 58 SequenceInstance(ISequence task) { 59 super(task); 60 } 60 61 61 /* (non-Javadoc) 62 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance#getChildren() 63 */ 64 public synchronized List<ITaskInstance> getChildren() { 65 if (children == null) { 66 children = new LinkedList<ITaskInstance>(); 67 } 62 /** 63 * <p> 64 * used to add a child to this task instance at a specific position 65 * </p> 66 * 67 * @param index 68 * the position of the new child in the list of children 69 * @param child 70 * the new child of this instance 71 */ 72 synchronized void addChild(int index, ITaskInstance child) { 73 if (children == null) { 74 children = new LinkedList<ITaskInstance>(); 75 } 68 76 69 return Collections.unmodifiableList(children);70 77 children.add(index, child); 78 } 71 79 72 /* (non-Javadoc) 73 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList#get(int) 74 */ 75 @Override 76 public ITaskInstance get(int index) { 77 if (children == null) { 78 throw new IndexOutOfBoundsException(Integer.toString(index)); 79 } 80 else{81 return children.get(index); 82 } 83 80 /** 81 * <p> 82 * used to add a child to this task instance 83 * </p> 84 * 85 * @param child 86 * the new child of this instance 87 */ 88 synchronized void addChild(ITaskInstance child) { 89 if (children == null) { 90 children = new LinkedList<ITaskInstance>(); 91 } 84 92 85 /* (non-Javadoc) 86 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList#size() 87 */ 88 @Override 89 public int size() { 90 if (children == null) { 91 return 0; 92 } 93 else { 94 return children.size(); 95 } 96 } 93 children.add(child); 94 } 97 95 98 /* (non-Javadoc) 99 * @see java.lang.Iterable#iterator() 100 */ 101 @Override 102 public Iterator<ITaskInstance> iterator() { 103 return getChildren().iterator(); 104 } 96 /* 97 * (non-Javadoc) 98 * 99 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.ISequenceInstance#clone() 100 */ 101 @Override 102 public synchronized ISequenceInstance clone() { 103 final SequenceInstance clone = (SequenceInstance) super.clone(); 105 104 106 /* (non-Javadoc) 107 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ISequenceInstance#getSequence() 108 */ 109 @Override 110 public ISequence getSequence() { 111 return (ISequence) super.getTask(); 112 } 105 if (children != null) { 106 clone.children = new LinkedList<ITaskInstance>(); 113 107 114 /* (non-Javadoc) 115 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.ISequenceInstance#clone() 116 */ 117 @Override 118 public synchronized ISequenceInstance clone() { 119 SequenceInstance clone = (SequenceInstance) super.clone(); 108 for (final ITaskInstance child : children) { 109 clone.children.add(child.clone()); 110 } 111 } 120 112 121 if (children != null) { 122 clone.children = new LinkedList<ITaskInstance>(); 113 return clone; 114 } 123 115 124 for (ITaskInstance child : children) { 125 clone.children.add(child.clone()); 126 } 127 } 116 /* 117 * (non-Javadoc) 118 * 119 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList#get(int) 120 */ 121 @Override 122 public ITaskInstance get(int index) { 123 if (children == null) { 124 throw new IndexOutOfBoundsException(Integer.toString(index)); 125 } else { 126 return children.get(index); 127 } 128 } 128 129 129 return clone; 130 } 130 /* 131 * (non-Javadoc) 132 * 133 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance#getChildren() 134 */ 135 public synchronized List<ITaskInstance> getChildren() { 136 if (children == null) { 137 children = new LinkedList<ITaskInstance>(); 138 } 131 139 132 /** 133 * <p> 134 * used to add a child to this task instance 135 * </p> 136 * 137 * @param child the new child of this instance 138 */ 139 synchronized void addChild(ITaskInstance child) { 140 if (children == null) { 141 children = new LinkedList<ITaskInstance>(); 142 } 140 return Collections.unmodifiableList(children); 141 } 143 142 144 children.add(child); 145 } 143 /* 144 * (non-Javadoc) 145 * 146 * @see 147 * de.ugoe.cs.autoquest.tasktrees.treeifc.ISequenceInstance#getSequence() 148 */ 149 @Override 150 public ISequence getSequence() { 151 return (ISequence) super.getTask(); 152 } 146 153 147 /** 148 * <p> 149 * used to add a child to this task instance at a specific position 150 * </p> 151 * 152 * @param index the position of the new child in the list of children 153 * @param child the new child of this instance 154 */ 155 synchronized void addChild(int index, ITaskInstance child) { 156 if (children == null) { 157 children = new LinkedList<ITaskInstance>(); 158 } 154 /* 155 * (non-Javadoc) 156 * 157 * @see java.lang.Iterable#iterator() 158 */ 159 @Override 160 public Iterator<ITaskInstance> iterator() { 161 return getChildren().iterator(); 162 } 159 163 160 children.add(index, child); 161 } 164 /** 165 * <p> 166 * removes a child from this task instance at a specific position 167 * </p> 168 * 169 * @param index 170 * the position of the child to be removed 171 * 172 * @return the child removed from the children of this instance 173 */ 174 synchronized ITaskInstance removeChild(int index) { 175 if (children != null) { 176 return children.remove(index); 177 } else { 178 throw new IllegalArgumentException( 179 "this task instance does not have children that can be removed"); 180 } 181 } 162 182 163 /** 164 * <p> 165 * removes a child from this task instance at a specific position 166 * </p> 167 * 168 * @param index the position of the child to be removed 169 * 170 * @return the child removed from the children of this instance 171 */ 172 synchronized ITaskInstance removeChild(int index) { 173 if (children != null) { 174 return children.remove(index); 175 } 176 else { 177 throw new IllegalArgumentException 178 ("this task instance does not have children that can be removed"); 179 } 180 } 183 /* 184 * (non-Javadoc) 185 * 186 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList#size() 187 */ 188 @Override 189 public int size() { 190 if (children == null) { 191 return 0; 192 } else { 193 return children.size(); 194 } 195 } 181 196 182 197 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/StructuringTemporalRelationship.java
r1357 r1733 23 23 /** 24 24 * <p> 25 * this is the default implementation of the interface {@link IStructuringTemporalRelationship}. It 26 * does not do anything fancy except implementing the interface. 25 * this is the default implementation of the interface 26 * {@link IStructuringTemporalRelationship}. It does not do anything fancy 27 * except implementing the interface. 27 28 * </p> 28 29 * 29 30 * @author Patrick Harms 30 31 */ 31 abstract class StructuringTemporalRelationship extends Task 32 implements IStructuringTemporalRelationship 33 { 32 abstract class StructuringTemporalRelationship extends Task implements 33 IStructuringTemporalRelationship { 34 34 35 /** 36 * <p> 37 * default serial version UID 38 * </p> 39 */ 40 private static final long serialVersionUID = 1L; 41 42 /** 43 * <p> 44 * the list of children of this temporal relationship 45 * </p> 46 */ 47 private List<ITask> children = new LinkedList<ITask>(); 35 /** 36 * <p> 37 * default serial version UID 38 * </p> 39 */ 40 private static final long serialVersionUID = 1L; 48 41 49 /** 50 * <p> 51 * initializes this temporal relationship with a human readable name 52 * </p> 53 * 54 * @param relationshipType the human readable name of this temporal relationship 55 */ 56 StructuringTemporalRelationship(String relationshipType) { 57 super(relationshipType); 58 59 if ((relationshipType == null) || ("".equals(relationshipType))) { 60 throw new IllegalArgumentException 61 ("the relationship type must be something meaningful"); 62 } 63 } 42 /** 43 * <p> 44 * the list of children of this temporal relationship 45 * </p> 46 */ 47 private List<ITask> children = new LinkedList<ITask>(); 64 48 65 /* (non-Javadoc) 66 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.IStructuringTemporalRelationship#getChildren() 67 */ 68 @Override 69 public List<ITask> getChildren() { 70 return children; 71 } 49 /** 50 * <p> 51 * initializes this temporal relationship with a human readable name 52 * </p> 53 * 54 * @param relationshipType 55 * the human readable name of this temporal relationship 56 */ 57 StructuringTemporalRelationship(String relationshipType) { 58 super(relationshipType); 72 59 73 /* (non-Javadoc) 74 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.Task#clone() 75 */ 76 @Override 77 public synchronized StructuringTemporalRelationship clone() { 78 StructuringTemporalRelationship clone = null; 79 clone = (StructuringTemporalRelationship) super.clone(); 80 81 clone.children = new LinkedList<ITask>(); 82 83 for (ITask child : this.children) { 84 clone.children.add(child.clone()); 85 } 60 if ((relationshipType == null) || ("".equals(relationshipType))) { 61 throw new IllegalArgumentException( 62 "the relationship type must be something meaningful"); 63 } 64 } 86 65 87 return clone; 88 } 66 /** 67 * <p> 68 * used to add a new child to this temporal relationship at a specific 69 * position. 70 * </p> 71 * 72 * @param index 73 * the index of the new child to be added. 74 * @param newChild 75 * the new child to be added 76 */ 77 void addChild(int index, ITask newChild) { 78 children.add(index, newChild); 79 } 89 80 90 /** 91 * <p> 92 * used to add a new child to this temporal relationship. 93 * </p> 94 * 95 * @param newChild the new child to be added 96 */ 97 void addChild(ITask newChild) { 98 children.add(newChild); 99 } 81 /** 82 * <p> 83 * used to add a new child to this temporal relationship. 84 * </p> 85 * 86 * @param newChild 87 * the new child to be added 88 */ 89 void addChild(ITask newChild) { 90 children.add(newChild); 91 } 100 92 101 /** 102 * <p> 103 * used to add a new child to this temporal relationship at a specific position. 104 * </p> 105 * 106 * @param index the index of the new child to be added. 107 * @param newChild the new child to be added 108 */ 109 void addChild(int index, ITask newChild) { 110 children.add(index, newChild); 111 } 112 113 /** 114 * <p> 115 * removes a child from this temporal relationship at a specific position. 116 * </p> 117 * 118 * @param index the index of the child to be removed. 119 */ 120 void removeChild(int index) { 121 children.remove(index); 122 } 93 /* 94 * (non-Javadoc) 95 * 96 * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.Task#clone() 97 */ 98 @Override 99 public synchronized StructuringTemporalRelationship clone() { 100 StructuringTemporalRelationship clone = null; 101 clone = (StructuringTemporalRelationship) super.clone(); 102 103 clone.children = new LinkedList<ITask>(); 104 105 for (final ITask child : this.children) { 106 clone.children.add(child.clone()); 107 } 108 109 return clone; 110 } 111 112 /* 113 * (non-Javadoc) 114 * 115 * @see 116 * de.ugoe.cs.autoquest.tasktrees.treeifc.IStructuringTemporalRelationship 117 * #getChildren() 118 */ 119 @Override 120 public List<ITask> getChildren() { 121 return children; 122 } 123 124 /** 125 * <p> 126 * removes a child from this temporal relationship at a specific position. 127 * </p> 128 * 129 * @param index 130 * the index of the child to be removed. 131 */ 132 void removeChild(int index) { 133 children.remove(index); 134 } 123 135 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/Task.java
r1400 r1733 32 32 /** 33 33 * <p> 34 * this is the default implementation of the interface {@link ITask}. It 35 * doesnot do anything fancy except implementing the interface.34 * this is the default implementation of the interface {@link ITask}. It does 35 * not do anything fancy except implementing the interface. 36 36 * </p> 37 37 * … … 40 40 abstract class Task implements ITask { 41 41 42 /** 43 * <p> 44 * default serial version UID 45 * </p> 46 */ 47 private static final long serialVersionUID = 1L; 48 49 /** 50 * <p> 51 * used as a counter to generate new ids for each newly created task. May overflow. 52 * </p> 53 */ 54 private static int temporalId = 0; 55 56 /** 57 * <p> 58 * the id of the task (unique throughout the system as long as {@link #temporalId} does not 59 * overflow. 60 * </p> 61 */ 62 private int id; 63 64 /** 65 * <p> 66 * a human readable type of the task (used for visualization purposes) 67 * </p> 68 */ 69 private String type; 70 71 /** 72 * <p> 73 * a human readable description of the task 74 * </p> 75 */ 76 private String description; 77 78 /** 79 * <p> 80 * the instances of this task 81 * </p> 82 */ 83 private Collection<ITaskInstance> instances = new HashSet<ITaskInstance>(); 84 85 /** 86 * <p> 87 * the execution variants of this task 88 * </p> 89 */ 90 private Collection<Collection<ITaskInstance>> executionVariants; 91 92 /** 93 * <p> 94 * constructs a new task with a new id. The id is generated using the {@link #getNewId()} 95 * method 96 * </p> 97 * 98 * @param type the human readable type of the task 99 * 100 * @throws IllegalArgumentException in the case the provided type is null 101 */ 102 Task(String type) { 103 this.id = getNewId(); 104 this.type = type; 105 106 if (type == null) { 107 throw new IllegalArgumentException("type must not be null"); 108 } 109 } 110 111 /** 112 * <p> 113 * creates a new id for a task using {@link #temporalId} by incrementing it an returning its 114 * current value. Resets the counter if {@link Integer.MAX_VALUE} is reached. 115 * </p> 116 * 117 * @return a new unique id for a task as long as {@link #temporalId} does not overflow 118 */ 119 private static synchronized int getNewId() { 120 if (temporalId == Integer.MAX_VALUE) { 121 temporalId = 0; 122 } 123 124 return temporalId++; 125 } 126 127 /* (non-Javadoc) 128 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#geId() 129 */ 130 @Override 131 public int getId() { 132 return id; 133 } 134 135 /* (non-Javadoc) 136 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#getType() 137 */ 138 @Override 139 public String getType() { 140 return type; 141 } 142 143 /* (non-Javadoc) 144 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#getDescription() 145 */ 146 @Override 147 public String getDescription() { 148 return description; 149 } 150 151 /* (non-Javadoc) 152 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#getInstances() 153 */ 154 @Override 155 public Collection<ITaskInstance> getInstances() { 156 return Collections.unmodifiableCollection(instances); 157 } 158 159 /* (non-Javadoc) 160 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#getExecutionVariants() 161 */ 162 @Override 163 public synchronized Collection<Collection<ITaskInstance>> getExecutionVariants() { 164 if (executionVariants == null) { 165 executionVariants = new LinkedList<Collection<ITaskInstance>>(); 166 determineExecutionVariants(executionVariants); 167 } 168 169 return executionVariants; 170 } 171 172 /* (non-Javadoc) 173 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#equals(ITask) 174 */ 175 @Override 176 public final boolean equals(ITask task) { 177 // tasks are only equal if they are identical or if they have the same id 178 // (may happen, if they are cloned) 179 return (this == task) || (this.hashCode() == task.hashCode()); 180 } 181 182 /* (non-Javadoc) 183 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#hashCode() 184 */ 185 @Override 186 public synchronized int hashCode() { 187 return id; 188 } 189 190 /* (non-Javadoc) 191 * @see java.lang.Object#toString() 192 */ 193 @Override 194 public synchronized String toString() { 195 StringBuffer result = new StringBuffer(); 196 result.append(type); 197 result.append(" #"); 198 result.append(id); 199 200 if (description != null) { 201 result.append(" ("); 202 result.append(description); 203 result.append(')'); 204 } 205 206 return result.toString(); 207 } 208 209 /* (non-Javadoc) 210 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#clone() 211 */ 212 @Override 213 public synchronized ITask clone() { 214 Task clone = null; 215 try { 216 clone = (Task) super.clone(); 217 } 218 catch (CloneNotSupportedException e) { 219 // this should never happen. Therefore simply dump the exception 220 e.printStackTrace(); 221 } 222 223 return clone; 224 } 225 226 /** 227 * <p> 228 * internally used to set the human readable description of the task 229 * </p> 230 * 231 * @param description the new human readable description of the task 232 */ 233 void setDescription(String description) { 234 this.description = description; 235 } 236 237 /** 238 * <p> 239 * internally used to remove an instance from this task 240 * </p> 241 * 242 * @param instance the instance to be removed from this task 243 */ 244 synchronized void removeInstance(ITaskInstance instance) { 245 this.instances.remove(instance); 246 this.executionVariants = null; 247 } 248 249 /** 250 * <p> 251 * internally used to add an instance to this task 252 * </p> 253 * 254 * @param instance the instance belonging to this task 255 */ 256 synchronized void addInstance(ITaskInstance instance) { 257 this.instances.add(instance); 258 this.executionVariants = null; 259 } 260 261 /* (non-Javadoc) 262 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#accept(ITaskVisitor) 263 */ 264 @Override 265 public void accept(ITaskVisitor visitor) { 266 visitor.visit(this); 267 } 268 269 /** 270 * 271 */ 272 private void determineExecutionVariants(Collection<Collection<ITaskInstance>> executionVariants) 273 { 274 for (ITaskInstance instance : instances) { 275 boolean added = false; 276 for (Collection<ITaskInstance> variant : executionVariants) { 277 if (!variant.isEmpty() && (isSameExecution(variant.iterator().next(), instance))) { 278 variant.add(instance); 279 added = true; 280 } 281 } 282 283 if (!added) { 284 Collection<ITaskInstance> variant = new HashSet<ITaskInstance>(); 285 variant.add(instance); 286 executionVariants.add(variant); 287 } 288 } 289 } 290 291 /** 292 * 293 */ 294 private boolean isSameExecution(ITaskInstance instance1, ITaskInstance instance2) { 295 if (instance1 instanceof IIterationInstance) { 296 if (!(instance2 instanceof IIterationInstance)) { 297 return false; 298 } 299 300 ITaskInstanceList iteration1 = (ITaskInstanceList) instance1; 301 ITaskInstanceList iteration2 = (ITaskInstanceList) instance2; 302 303 return isSameExecutionList(iteration1, iteration2); 304 } 305 else if (instance1 instanceof ISequenceInstance) { 306 if (!(instance2 instanceof ISequenceInstance)) { 307 return false; 308 } 309 310 ITaskInstanceList selection1 = (ITaskInstanceList) instance1; 311 ITaskInstanceList selection2 = (ITaskInstanceList) instance2; 312 313 return isSameExecutionList(selection1, selection2); 314 } 315 else if (instance1 instanceof ISelectionInstance) { 316 if (!(instance2 instanceof ISelectionInstance)) { 317 return false; 318 } 319 else { 320 return isSameExecution(((ISelectionInstance) instance1).getChild(), 321 ((ISelectionInstance) instance2).getChild()); 322 } 323 } 324 else if (instance1 instanceof IOptionalInstance) { 325 if (!(instance2 instanceof IOptionalInstance)) { 326 return false; 327 } 328 else { 329 return isSameExecution(((IOptionalInstance) instance1).getChild(), 330 ((IOptionalInstance) instance2).getChild()); 331 } 332 } 333 else if (instance1 instanceof IEventTaskInstance) { 334 if (!(instance2 instanceof IEventTaskInstance)) { 335 return false; 336 } 337 else { 338 return ((IEventTaskInstance) instance1).getTask().equals 339 (((IEventTaskInstance) instance2).getTask()); 340 } 341 } 342 else if (instance1 == null) { 343 return instance2 == null; 344 } 345 else { 346 throw new IllegalArgumentException("unknown type of task instance: " + instance1); 347 } 348 } 349 350 /** 351 * 352 */ 353 private boolean isSameExecutionList(ITaskInstanceList list1, ITaskInstanceList list2) { 354 if (list1.size() == list2.size()) { 355 for (int i = 0; i < list1.size(); i++) { 356 if (!isSameExecution(list1.get(i), list2.get(i))) { 357 return false; 358 } 359 } 360 361 return true; 362 } 363 else { 364 return false; 365 } 366 } 42 /** 43 * <p> 44 * creates a new id for a task using {@link #temporalId} by incrementing it 45 * an returning its current value. Resets the counter if 46 * {@link Integer.MAX_VALUE} is reached. 47 * </p> 48 * 49 * @return a new unique id for a task as long as {@link #temporalId} does 50 * not overflow 51 */ 52 private static synchronized int getNewId() { 53 if (temporalId == Integer.MAX_VALUE) { 54 temporalId = 0; 55 } 56 57 return temporalId++; 58 } 59 60 /** 61 * <p> 62 * default serial version UID 63 * </p> 64 */ 65 private static final long serialVersionUID = 1L; 66 67 /** 68 * <p> 69 * used as a counter to generate new ids for each newly created task. May 70 * overflow. 71 * </p> 72 */ 73 private static int temporalId = 0; 74 75 /** 76 * <p> 77 * the id of the task (unique throughout the system as long as 78 * {@link #temporalId} does not overflow. 79 * </p> 80 */ 81 private final int id; 82 83 /** 84 * <p> 85 * a human readable type of the task (used for visualization purposes) 86 * </p> 87 */ 88 private final String type; 89 90 /** 91 * <p> 92 * a human readable description of the task 93 * </p> 94 */ 95 private String description; 96 97 /** 98 * <p> 99 * the instances of this task 100 * </p> 101 */ 102 private final Collection<ITaskInstance> instances = new HashSet<ITaskInstance>(); 103 104 /** 105 * <p> 106 * the execution variants of this task 107 * </p> 108 */ 109 private Collection<Collection<ITaskInstance>> executionVariants; 110 111 /** 112 * <p> 113 * constructs a new task with a new id. The id is generated using the 114 * {@link #getNewId()} method 115 * </p> 116 * 117 * @param type 118 * the human readable type of the task 119 * 120 * @throws IllegalArgumentException 121 * in the case the provided type is null 122 */ 123 Task(String type) { 124 this.id = getNewId(); 125 this.type = type; 126 127 if (type == null) { 128 throw new IllegalArgumentException("type must not be null"); 129 } 130 } 131 132 /* 133 * (non-Javadoc) 134 * 135 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#accept(ITaskVisitor) 136 */ 137 @Override 138 public void accept(ITaskVisitor visitor) { 139 visitor.visit(this); 140 } 141 142 /** 143 * <p> 144 * internally used to add an instance to this task 145 * </p> 146 * 147 * @param instance 148 * the instance belonging to this task 149 */ 150 synchronized void addInstance(ITaskInstance instance) { 151 this.instances.add(instance); 152 this.executionVariants = null; 153 } 154 155 /* 156 * (non-Javadoc) 157 * 158 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#clone() 159 */ 160 @Override 161 public synchronized ITask clone() { 162 Task clone = null; 163 try { 164 clone = (Task) super.clone(); 165 } catch (final CloneNotSupportedException e) { 166 // this should never happen. Therefore simply dump the exception 167 e.printStackTrace(); 168 } 169 170 return clone; 171 } 172 173 /** 174 * 175 */ 176 private void determineExecutionVariants( 177 Collection<Collection<ITaskInstance>> executionVariants) { 178 for (final ITaskInstance instance : instances) { 179 boolean added = false; 180 for (final Collection<ITaskInstance> variant : executionVariants) { 181 if (!variant.isEmpty() 182 && (isSameExecution(variant.iterator().next(), instance))) { 183 variant.add(instance); 184 added = true; 185 } 186 } 187 188 if (!added) { 189 final Collection<ITaskInstance> variant = new HashSet<ITaskInstance>(); 190 variant.add(instance); 191 executionVariants.add(variant); 192 } 193 } 194 } 195 196 /* 197 * (non-Javadoc) 198 * 199 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#equals(ITask) 200 */ 201 @Override 202 public final boolean equals(ITask task) { 203 // tasks are only equal if they are identical or if they have the same 204 // id 205 // (may happen, if they are cloned) 206 return (this == task) || (this.hashCode() == task.hashCode()); 207 } 208 209 /* 210 * (non-Javadoc) 211 * 212 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#getDescription() 213 */ 214 @Override 215 public String getDescription() { 216 return description; 217 } 218 219 /* 220 * (non-Javadoc) 221 * 222 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#getExecutionVariants() 223 */ 224 @Override 225 public synchronized Collection<Collection<ITaskInstance>> getExecutionVariants() { 226 if (executionVariants == null) { 227 executionVariants = new LinkedList<Collection<ITaskInstance>>(); 228 determineExecutionVariants(executionVariants); 229 } 230 231 return executionVariants; 232 } 233 234 /* 235 * (non-Javadoc) 236 * 237 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#geId() 238 */ 239 @Override 240 public int getId() { 241 return id; 242 } 243 244 /* 245 * (non-Javadoc) 246 * 247 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#getInstances() 248 */ 249 @Override 250 public Collection<ITaskInstance> getInstances() { 251 return Collections.unmodifiableCollection(instances); 252 } 253 254 /* 255 * (non-Javadoc) 256 * 257 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#getType() 258 */ 259 @Override 260 public String getType() { 261 return type; 262 } 263 264 /* 265 * (non-Javadoc) 266 * 267 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#hashCode() 268 */ 269 @Override 270 public synchronized int hashCode() { 271 return id; 272 } 273 274 /** 275 * 276 */ 277 private boolean isSameExecution(ITaskInstance instance1, 278 ITaskInstance instance2) { 279 if (instance1 instanceof IIterationInstance) { 280 if (!(instance2 instanceof IIterationInstance)) { 281 return false; 282 } 283 284 final ITaskInstanceList iteration1 = (ITaskInstanceList) instance1; 285 final ITaskInstanceList iteration2 = (ITaskInstanceList) instance2; 286 287 return isSameExecutionList(iteration1, iteration2); 288 } else if (instance1 instanceof ISequenceInstance) { 289 if (!(instance2 instanceof ISequenceInstance)) { 290 return false; 291 } 292 293 final ITaskInstanceList selection1 = (ITaskInstanceList) instance1; 294 final ITaskInstanceList selection2 = (ITaskInstanceList) instance2; 295 296 return isSameExecutionList(selection1, selection2); 297 } else if (instance1 instanceof ISelectionInstance) { 298 if (!(instance2 instanceof ISelectionInstance)) { 299 return false; 300 } else { 301 return isSameExecution( 302 ((ISelectionInstance) instance1).getChild(), 303 ((ISelectionInstance) instance2).getChild()); 304 } 305 } else if (instance1 instanceof IOptionalInstance) { 306 if (!(instance2 instanceof IOptionalInstance)) { 307 return false; 308 } else { 309 return isSameExecution( 310 ((IOptionalInstance) instance1).getChild(), 311 ((IOptionalInstance) instance2).getChild()); 312 } 313 } else if (instance1 instanceof IEventTaskInstance) { 314 if (!(instance2 instanceof IEventTaskInstance)) { 315 return false; 316 } else { 317 return ((IEventTaskInstance) instance1).getTask().equals( 318 ((IEventTaskInstance) instance2).getTask()); 319 } 320 } else if (instance1 == null) { 321 return instance2 == null; 322 } else { 323 throw new IllegalArgumentException( 324 "unknown type of task instance: " + instance1); 325 } 326 } 327 328 /** 329 * 330 */ 331 private boolean isSameExecutionList(ITaskInstanceList list1, 332 ITaskInstanceList list2) { 333 if (list1.size() == list2.size()) { 334 for (int i = 0; i < list1.size(); i++) { 335 if (!isSameExecution(list1.get(i), list2.get(i))) { 336 return false; 337 } 338 } 339 340 return true; 341 } else { 342 return false; 343 } 344 } 345 346 /** 347 * <p> 348 * internally used to remove an instance from this task 349 * </p> 350 * 351 * @param instance 352 * the instance to be removed from this task 353 */ 354 synchronized void removeInstance(ITaskInstance instance) { 355 this.instances.remove(instance); 356 this.executionVariants = null; 357 } 358 359 /** 360 * <p> 361 * internally used to set the human readable description of the task 362 * </p> 363 * 364 * @param description 365 * the new human readable description of the task 366 */ 367 void setDescription(String description) { 368 this.description = description; 369 } 370 371 /* 372 * (non-Javadoc) 373 * 374 * @see java.lang.Object#toString() 375 */ 376 @Override 377 public synchronized String toString() { 378 final StringBuffer result = new StringBuffer(); 379 result.append(type); 380 result.append(" #"); 381 result.append(id); 382 383 if (description != null) { 384 result.append(" ("); 385 result.append(description); 386 result.append(')'); 387 } 388 389 return result.toString(); 390 } 367 391 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/TaskBuilder.java
r1422 r1733 36 36 * <p> 37 37 * this is the default implementation of the interface {@link ITaskBuilder}. It 38 * does not do anything fancy except implementing the interface. In some situations, it performs 39 * a check if the model or instances to be created a valid. However, this can not be done 40 * in any situation of the creation process. 38 * does not do anything fancy except implementing the interface. In some 39 * situations, it performs a check if the model or instances to be created a 40 * valid. However, this can not be done in any situation of the creation 41 * process. 41 42 * </p> 42 43 * … … 45 46 public class TaskBuilder implements ITaskBuilder { 46 47 47 /* (non-Javadoc) 48 * @see ITaskBuilder#addChild(ISequenceInstance, ITaskInstance) 49 */ 50 @Override 51 public void addChild(ISequenceInstance instance, ITaskInstance child) 52 throws IllegalArgumentException 53 { 54 if (!(instance instanceof SequenceInstance)) { 55 throw new IllegalArgumentException 56 ("illegal type of sequence instance provided: " + instance.getClass()); 57 } 58 59 if (!(child instanceof TaskInstance)) { 60 throw new IllegalArgumentException 61 ("illegal type of task instance provided: " + child.getClass()); 62 } 63 64 SequenceInstance seqInstance = (SequenceInstance) instance; 65 66 // check if new child instance matches the model, if this can be checked 67 IStructuringTemporalRelationship parentTask = 68 (IStructuringTemporalRelationship) instance.getTask(); 69 70 if (((parentTask.getChildren() != null) && (parentTask.getChildren().size() > 0)) && 71 ((parentTask.getChildren().size() <= seqInstance.size()) || 72 (!parentTask.getChildren().get(seqInstance.size()).equals(child.getTask())))) 73 { 74 throw new IllegalArgumentException 75 ("the task of the child instance to be added does not belong to the children " + 76 "of the task of the parent instance"); 77 } 78 79 seqInstance.addChild(child); 80 } 81 82 /* (non-Javadoc) 83 * @see ITaskBuilder#addChild(ISequenceInstance, int, ITaskInstance) 84 */ 85 public void addChild(ISequenceInstance instance, int index, ITaskInstance child) 86 throws IllegalArgumentException 87 { 88 if (!(instance instanceof SequenceInstance)) { 89 throw new IllegalArgumentException 90 ("illegal type of sequence instance provided: " + instance.getClass()); 91 } 92 93 if (!(child instanceof TaskInstance)) { 94 throw new IllegalArgumentException 95 ("illegal type of task instance provided: " + child.getClass()); 96 } 97 98 SequenceInstance seqInstance = (SequenceInstance) instance; 99 100 // check if new child instance matches the model, if this can be checked 101 IStructuringTemporalRelationship parentTask = 102 (IStructuringTemporalRelationship) instance.getTask(); 103 104 if (((parentTask.getChildren() != null) && (parentTask.getChildren().size() > 0)) && 105 ((parentTask.getChildren().size() <= index) || 106 (!parentTask.getChildren().get(index).equals(child.getTask())))) 107 { 108 throw new IllegalArgumentException 109 ("the task of the child instance to be added does not belong to the children " + 110 "of the task of the parent instance"); 111 } 112 113 seqInstance.addChild(index, child); 114 } 115 116 /* (non-Javadoc) 117 * @see ITaskBuilder#addChild(IIterationInstance, ITaskInstance) 118 */ 119 @Override 120 public void addChild(IIterationInstance instance, ITaskInstance child) 121 throws IllegalArgumentException 122 { 123 if (!(instance instanceof IterationInstance)) { 124 throw new IllegalArgumentException 125 ("illegal type of iteration instance provided: " + instance.getClass()); 126 } 127 128 if (!(child instanceof TaskInstance)) { 129 throw new IllegalArgumentException 130 ("illegal type of task instance provided: " + child.getClass()); 131 } 132 133 // check if new child instance matches the model, if this can be checked 134 IMarkingTemporalRelationship parentTask = 135 (IMarkingTemporalRelationship) instance.getTask(); 136 137 boolean foundChildTask = parentTask.getMarkedTask() != null ? 138 parentTask.getMarkedTask().equals(child.getTask()) : true; 139 140 if (!foundChildTask) { 141 throw new IllegalArgumentException 142 ("the task of the child instance does not match the model of the task of the " + 143 "iteration instance: " + parentTask.getMarkedTask() + " <> " + child.getTask()); 144 } 145 146 ((IterationInstance) instance).addChild(child); 147 } 148 149 /* (non-Javadoc) 150 * @see ITaskBuilder#addChild(IIterationInstance, int, ITaskInstance) 151 */ 152 public void addChild(IIterationInstance instance, int index, ITaskInstance child) 153 throws IllegalArgumentException 154 { 155 if (!(instance instanceof IterationInstance)) { 156 throw new IllegalArgumentException 157 ("illegal type of iteration instance provided: " + instance.getClass()); 158 } 159 160 if (!(child instanceof TaskInstance)) { 161 throw new IllegalArgumentException 162 ("illegal type of task instance provided: " + child.getClass()); 163 } 164 165 // check if new child instance matches the model, if this can be checked 166 IMarkingTemporalRelationship parentTask = 167 (IMarkingTemporalRelationship) instance.getTask(); 168 169 boolean foundChildTask = parentTask.getMarkedTask() != null ? 170 parentTask.getMarkedTask().equals(child.getTask()) : true; 171 172 if (!foundChildTask) { 173 throw new IllegalArgumentException 174 ("the task of the child instance does not match the model of the task of the " + 175 "iteration instance: " + parentTask.getMarkedTask() + " <> " + child.getTask()); 176 } 177 178 ((IterationInstance) instance).addChild(index, child); 179 } 180 181 /* (non-Javadoc) 182 * @see ITaskBuilder#setChild(ISelectionInstance, ITaskInstance) 183 */ 184 @Override 185 public void setChild(ISelectionInstance instance, ITaskInstance child) 186 throws IllegalArgumentException 187 { 188 if (!(instance instanceof SelectionInstance)) { 189 throw new IllegalArgumentException 190 ("illegal type of selection instance provided: " + instance.getClass()); 191 } 192 193 if (!(child instanceof TaskInstance)) { 194 throw new IllegalArgumentException("illegal type of task instance provided: " + 195 (child == null ? null : child.getClass())); 196 } 197 198 // check if new child instance matches the model, if this can be checked 199 IStructuringTemporalRelationship parentTask = 200 (IStructuringTemporalRelationship) instance.getTask(); 201 202 boolean foundChildTask = false; 203 for (ITask parentTaskChild : parentTask.getChildren()) { 204 if (parentTaskChild.equals(child.getTask())) { 205 foundChildTask = true; 206 break; 207 } 208 } 209 210 if (!foundChildTask) { 211 throw new IllegalArgumentException 212 ("the task of the child instance to be added does not belong to the children " + 213 "of the selection task model of the parent instance"); 214 } 215 216 ((SelectionInstance) instance).setChild(child); 217 } 218 219 /* (non-Javadoc) 220 * @see ITaskBuilder#setChild(IOptionalInstance, ITaskInstance) 221 */ 222 @Override 223 public void setChild(IOptionalInstance instance, ITaskInstance child) 224 throws IllegalArgumentException 225 { 226 if (!(instance instanceof OptionalInstance)) { 227 throw new IllegalArgumentException 228 ("illegal type of optional instance provided: " + instance.getClass()); 229 } 230 231 if (!(child instanceof TaskInstance)) { 232 throw new IllegalArgumentException 233 ("illegal type of task instance provided: " + child.getClass()); 234 } 235 236 // check if new child instance matches the model, if this can be checked 237 IMarkingTemporalRelationship parentTask = 238 (IMarkingTemporalRelationship) instance.getTask(); 239 240 boolean foundChildTask = parentTask.getMarkedTask() != null ? 241 parentTask.getMarkedTask().equals(child.getTask()) : true; 242 243 if (!foundChildTask) { 244 throw new IllegalArgumentException 245 ("the task of the child instance does not match the model of the task of the " + 246 "optional instance: " + parentTask.getMarkedTask() + " <> " + child.getTask()); 247 } 248 249 ((OptionalInstance) instance).setChild(child); 250 } 251 252 /* (non-Javadoc) 253 * @see ITaskBuilder#addExecutedTask(IUserSession, ITaskInstance) 254 */ 255 @Override 256 public void addExecutedTask(IUserSession session, ITaskInstance taskInstance) { 257 if (!(session instanceof UserSession)) { 258 throw new IllegalArgumentException 259 ("illegal type of session provided: " + session.getClass()); 260 } 261 262 if (!(taskInstance instanceof TaskInstance)) { 263 throw new IllegalArgumentException 264 ("illegal type of task instance provided: " + taskInstance.getClass()); 265 } 266 267 ((UserSession) session).addExecutedTask(taskInstance); 268 } 269 270 /* (non-Javadoc) 271 * @see ITaskBuilder#addExecutedTask(IUserSession, int, ITaskInstance) 272 */ 273 public void addExecutedTask(IUserSession session, int index, ITaskInstance taskInstance) { 274 if (!(session instanceof UserSession)) { 275 throw new IllegalArgumentException 276 ("illegal type of session provided: " + session.getClass()); 277 } 278 279 if (!(taskInstance instanceof TaskInstance)) { 280 throw new IllegalArgumentException 281 ("illegal type of task instance provided: " + taskInstance.getClass()); 282 } 283 284 ((UserSession) session).addExecutedTask(index, taskInstance); 285 } 286 287 /* (non-Javadoc) 288 * @see ITaskBuilder#addTaskInstance(ITaskInstanceList, ITaskInstance) 289 */ 290 @Override 291 public void addTaskInstance(ITaskInstanceList taskInstanceList, ITaskInstance taskInstance) { 292 if (taskInstanceList instanceof SequenceInstance) { 293 addChild((SequenceInstance) taskInstanceList, taskInstance); 294 } 295 else if (taskInstanceList instanceof IterationInstance) { 296 addChild((IterationInstance) taskInstanceList, taskInstance); 297 } 298 else if (taskInstanceList instanceof UserSession) { 299 addExecutedTask((UserSession) taskInstanceList, taskInstance); 300 } 301 else { 302 throw new IllegalArgumentException 303 ("illegal type of task instance list provided: " + taskInstanceList.getClass()); 304 } 305 } 306 307 /* (non-Javadoc) 308 * @see ITaskBuilder#addTaskInstance(ITaskInstanceList, int, ITaskInstance) 309 */ 310 @Override 311 public void addTaskInstance(ITaskInstanceList taskInstanceList, 312 int index, 313 ITaskInstance taskInstance) 314 { 315 if (taskInstanceList instanceof SequenceInstance) { 316 addChild((SequenceInstance) taskInstanceList, index, taskInstance); 317 } 318 else if (taskInstanceList instanceof IterationInstance) { 319 addChild((IterationInstance) taskInstanceList, index, taskInstance); 320 } 321 else if (taskInstanceList instanceof UserSession) { 322 addExecutedTask((UserSession) taskInstanceList, index, taskInstance); 323 } 324 else { 325 throw new IllegalArgumentException 326 ("illegal type of task instance list provided: " + taskInstanceList.getClass()); 327 } 328 } 329 330 /* (non-Javadoc) 331 * @see ITaskBuilder#setTaskInstance(ITaskInstanceList, int, ITaskInstance) 332 */ 333 @Override 334 public void setTaskInstance(ITaskInstanceList taskInstanceList, 335 int index, 336 ITaskInstance taskInstance) 337 { 338 removeTaskInstance(taskInstanceList, index); 339 addTaskInstance(taskInstanceList, index, taskInstance); 340 } 341 342 /* (non-Javadoc) 343 * @see ITaskBuilder#setTask(ITaskInstance, ITask) 344 */ 345 @Override 346 public void setTask(ITaskInstance taskInstance, ITask task) { 347 if (!(taskInstance instanceof TaskInstance)) { 348 throw new IllegalArgumentException 349 ("illegal type of task instance provided: " + taskInstance.getClass()); 350 } 351 if (!(task instanceof Task)) { 352 throw new IllegalArgumentException("illegal type of task provided: " + task.getClass()); 353 } 354 355 if (((TaskInstance) taskInstance).getTask() instanceof Task) { 356 ((Task) ((TaskInstance) taskInstance).getTask()).removeInstance(taskInstance); 357 } 358 ((TaskInstance) taskInstance).setTask(task); 359 360 ((Task) task).addInstance(taskInstance); 361 } 362 363 /* (non-Javadoc) 364 * @see ITaskBuilder#addChild(ISequence, ITask) 365 */ 366 @Override 367 public void addChild(ISequence parent, ITask child) { 368 if (!(parent instanceof Sequence)) { 369 throw new IllegalArgumentException 370 ("illegal type of sequence provided: " + parent.getClass()); 371 } 372 373 addChildInternal((Sequence) parent, -1, child); 374 } 375 376 /* (non-Javadoc) 377 * @see ITaskBuilder#addChild(ISequence, int, ITask) 378 */ 379 @Override 380 public void addChild(ISequence parent, int index, ITask child) { 381 if (!(parent instanceof Sequence)) { 382 throw new IllegalArgumentException 383 ("illegal type of sequence provided: " + parent.getClass()); 384 } 385 386 addChildInternal((Sequence) parent, index, child); 387 } 388 389 /* (non-Javadoc) 390 * @see ITaskBuilder#setChild(ISequence, int, ITask) 391 */ 392 @Override 393 public void setChild(ISequence parent, int index, ITask child) { 394 if (!(parent instanceof Sequence)) { 395 throw new IllegalArgumentException 396 ("illegal type of sequence provided: " + parent.getClass()); 397 } 398 399 ((Sequence) parent).removeChild(index); 400 addChildInternal((Sequence) parent, index, child); 401 } 402 403 /* (non-Javadoc) 404 * @see ITaskBuilder#addChild(ISelection, ITask) 405 */ 406 @Override 407 public void addChild(ISelection parent, ITask child) { 408 if (!(parent instanceof Selection)) { 409 throw new IllegalArgumentException 410 ("illegal type of selection provided: " + parent.getClass()); 411 } 412 413 addChildInternal((Selection) parent, -1, child); 414 } 415 416 /* (non-Javadoc) 417 * @see ITaskBuilder#setMarkedTask(IIteration, ITask) 418 */ 419 @Override 420 public void setMarkedTask(IIteration iteration, ITask newChild) { 421 if (!(iteration instanceof Iteration)) { 422 throw new IllegalArgumentException 423 ("illegal type of iteration provided: " + iteration.getClass()); 424 } 425 426 if (!(newChild instanceof Task)) { 427 throw new IllegalArgumentException 428 ("illegal type of task provided: " + newChild.getClass()); 429 } 430 431 ((Iteration) iteration).setMarkedTask(newChild); 432 } 433 434 /* (non-Javadoc) 435 * @see ITaskTreeBuilder#setChild(IOptional, ITaskTreeNode) 436 */ 437 @Override 438 public void setMarkedTask(IOptional optional, ITask newChild) { 439 if (!(optional instanceof Optional)) { 440 throw new IllegalArgumentException 441 ("illegal type of optional provided: " + optional.getClass()); 442 } 443 444 if (!(newChild instanceof Task)) { 445 throw new IllegalArgumentException 446 ("illegal type of task provided: " + newChild.getClass()); 447 } 448 449 ((Optional) optional).setMarkedTask(newChild); 450 } 451 452 /* (non-Javadoc) 453 * @see ITaskBuilder#removeChild(ISequence, int) 454 */ 455 @Override 456 public void removeChild(ISequence parent, int index) { 457 if (!(parent instanceof Sequence)) { 458 throw new IllegalArgumentException 459 ("illegal type of sequence provided: " + parent.getClass()); 460 } 461 462 ((Sequence) parent).removeChild(index); 463 } 464 465 /* (non-Javadoc) 466 * @see ITaskBuilder#removeChild(ISelection, ITask) 467 */ 468 @Override 469 public void removeChild(ISelection parent, ITask child) { 470 if (!(parent instanceof Selection)) { 471 throw new IllegalArgumentException 472 ("illegal type of selection provided: " + parent.getClass()); 473 } 474 475 List<ITask> children = parent.getChildren(); 476 477 for (int i = 0; i < children.size(); i++) { 478 if ((children.get(i) == child) || 479 ((children.get(i) != null) && (children.get(i).equals(child)))) 480 { 481 ((Selection) parent).removeChild(i); 482 break; 483 } 484 } 485 } 486 487 /* (non-Javadoc) 488 * @see ITaskBuilder#removeTaskInstance(ITaskInstanceList, int) 489 */ 490 @Override 491 public void removeTaskInstance(ITaskInstanceList taskInstanceList, int index) { 492 if (taskInstanceList instanceof SequenceInstance) { 493 ((SequenceInstance) taskInstanceList).removeChild(index); 494 } 495 else if (taskInstanceList instanceof IterationInstance) { 496 ((IterationInstance) taskInstanceList).removeChild(index); 497 } 498 else if (taskInstanceList instanceof UserSession) { 499 ((UserSession) taskInstanceList).removeExecutedTask(index); 500 } 501 else { 502 throw new IllegalArgumentException 503 ("illegal type of task instance list provided: " + taskInstanceList.getClass()); 504 } 505 } 506 507 /* (non-Javadoc) 508 * @see ITaskTreeBuilder#replaceChild(ISelection, ITaskTreeNode, ITaskTreeNode) 509 */ 510 @Override 511 public void replaceChild(ISelection parent, ITask oldChild, ITask newChild) { 512 if (!(parent instanceof Selection)) { 513 throw new IllegalArgumentException 514 ("illegal type of selection provided: " + parent.getClass()); 515 } 516 517 List<ITask> children = parent.getChildren(); 518 519 for (int i = 0; i < children.size(); i++) { 520 if ((children.get(i) == oldChild) || 521 ((children.get(i) != null) && (children.get(i).equals(oldChild)))) 522 { 523 ((Selection) parent).removeChild(i); 524 ((Selection) parent).addChild(i, newChild); 525 break; 526 } 527 } 528 } 529 530 /** 531 * <p> 532 * internal convenience method for adding children to a structuring temporal relationship 533 * including a check for the child type. 534 * </p> 535 */ 536 private void addChildInternal(StructuringTemporalRelationship parent, int index, ITask child) { 537 if (!(child instanceof Task)) { 538 throw new IllegalArgumentException 539 ("illegal type of task provided: " + child.getClass()); 540 } 541 542 if (index > -1) { 543 parent.addChild(index, child); 544 } 545 else { 546 parent.addChild(child); 547 } 548 } 48 /* 49 * (non-Javadoc) 50 * 51 * @see ITaskBuilder#addChild(IIterationInstance, int, ITaskInstance) 52 */ 53 public void addChild(IIterationInstance instance, int index, 54 ITaskInstance child) throws IllegalArgumentException { 55 if (!(instance instanceof IterationInstance)) { 56 throw new IllegalArgumentException( 57 "illegal type of iteration instance provided: " 58 + instance.getClass()); 59 } 60 61 if (!(child instanceof TaskInstance)) { 62 throw new IllegalArgumentException( 63 "illegal type of task instance provided: " 64 + child.getClass()); 65 } 66 67 // check if new child instance matches the model, if this can be checked 68 final IMarkingTemporalRelationship parentTask = (IMarkingTemporalRelationship) instance 69 .getTask(); 70 71 final boolean foundChildTask = parentTask.getMarkedTask() != null ? parentTask 72 .getMarkedTask().equals(child.getTask()) : true; 73 74 if (!foundChildTask) { 75 throw new IllegalArgumentException( 76 "the task of the child instance does not match the model of the task of the " 77 + "iteration instance: " 78 + parentTask.getMarkedTask() + " <> " 79 + child.getTask()); 80 } 81 82 ((IterationInstance) instance).addChild(index, child); 83 } 84 85 /* 86 * (non-Javadoc) 87 * 88 * @see ITaskBuilder#addChild(IIterationInstance, ITaskInstance) 89 */ 90 @Override 91 public void addChild(IIterationInstance instance, ITaskInstance child) 92 throws IllegalArgumentException { 93 if (!(instance instanceof IterationInstance)) { 94 throw new IllegalArgumentException( 95 "illegal type of iteration instance provided: " 96 + instance.getClass()); 97 } 98 99 if (!(child instanceof TaskInstance)) { 100 throw new IllegalArgumentException( 101 "illegal type of task instance provided: " 102 + child.getClass()); 103 } 104 105 // check if new child instance matches the model, if this can be checked 106 final IMarkingTemporalRelationship parentTask = (IMarkingTemporalRelationship) instance 107 .getTask(); 108 109 final boolean foundChildTask = parentTask.getMarkedTask() != null ? parentTask 110 .getMarkedTask().equals(child.getTask()) : true; 111 112 if (!foundChildTask) { 113 throw new IllegalArgumentException( 114 "the task of the child instance does not match the model of the task of the " 115 + "iteration instance: " 116 + parentTask.getMarkedTask() + " <> " 117 + child.getTask()); 118 } 119 120 ((IterationInstance) instance).addChild(child); 121 } 122 123 /* 124 * (non-Javadoc) 125 * 126 * @see ITaskBuilder#addChild(ISelection, ITask) 127 */ 128 @Override 129 public void addChild(ISelection parent, ITask child) { 130 if (!(parent instanceof Selection)) { 131 throw new IllegalArgumentException( 132 "illegal type of selection provided: " + parent.getClass()); 133 } 134 135 addChildInternal((Selection) parent, -1, child); 136 } 137 138 /* 139 * (non-Javadoc) 140 * 141 * @see ITaskBuilder#addChild(ISequence, int, ITask) 142 */ 143 @Override 144 public void addChild(ISequence parent, int index, ITask child) { 145 if (!(parent instanceof Sequence)) { 146 throw new IllegalArgumentException( 147 "illegal type of sequence provided: " + parent.getClass()); 148 } 149 150 addChildInternal((Sequence) parent, index, child); 151 } 152 153 /* 154 * (non-Javadoc) 155 * 156 * @see ITaskBuilder#addChild(ISequence, ITask) 157 */ 158 @Override 159 public void addChild(ISequence parent, ITask child) { 160 if (!(parent instanceof Sequence)) { 161 throw new IllegalArgumentException( 162 "illegal type of sequence provided: " + parent.getClass()); 163 } 164 165 addChildInternal((Sequence) parent, -1, child); 166 } 167 168 /* 169 * (non-Javadoc) 170 * 171 * @see ITaskBuilder#addChild(ISequenceInstance, int, ITaskInstance) 172 */ 173 public void addChild(ISequenceInstance instance, int index, 174 ITaskInstance child) throws IllegalArgumentException { 175 if (!(instance instanceof SequenceInstance)) { 176 throw new IllegalArgumentException( 177 "illegal type of sequence instance provided: " 178 + instance.getClass()); 179 } 180 181 if (!(child instanceof TaskInstance)) { 182 throw new IllegalArgumentException( 183 "illegal type of task instance provided: " 184 + child.getClass()); 185 } 186 187 final SequenceInstance seqInstance = (SequenceInstance) instance; 188 189 // check if new child instance matches the model, if this can be checked 190 final IStructuringTemporalRelationship parentTask = (IStructuringTemporalRelationship) instance 191 .getTask(); 192 193 if (((parentTask.getChildren() != null) && (parentTask.getChildren() 194 .size() > 0)) 195 && ((parentTask.getChildren().size() <= index) || (!parentTask 196 .getChildren().get(index).equals(child.getTask())))) { 197 throw new IllegalArgumentException( 198 "the task of the child instance to be added does not belong to the children " 199 + "of the task of the parent instance"); 200 } 201 202 seqInstance.addChild(index, child); 203 } 204 205 /* 206 * (non-Javadoc) 207 * 208 * @see ITaskBuilder#addChild(ISequenceInstance, ITaskInstance) 209 */ 210 @Override 211 public void addChild(ISequenceInstance instance, ITaskInstance child) 212 throws IllegalArgumentException { 213 if (!(instance instanceof SequenceInstance)) { 214 throw new IllegalArgumentException( 215 "illegal type of sequence instance provided: " 216 + instance.getClass()); 217 } 218 219 if (!(child instanceof TaskInstance)) { 220 throw new IllegalArgumentException( 221 "illegal type of task instance provided: " 222 + child.getClass()); 223 } 224 225 final SequenceInstance seqInstance = (SequenceInstance) instance; 226 227 // check if new child instance matches the model, if this can be checked 228 final IStructuringTemporalRelationship parentTask = (IStructuringTemporalRelationship) instance 229 .getTask(); 230 231 if (((parentTask.getChildren() != null) && (parentTask.getChildren() 232 .size() > 0)) 233 && ((parentTask.getChildren().size() <= seqInstance.size()) || (!parentTask 234 .getChildren().get(seqInstance.size()) 235 .equals(child.getTask())))) { 236 throw new IllegalArgumentException( 237 "the task of the child instance to be added does not belong to the children " 238 + "of the task of the parent instance"); 239 } 240 241 seqInstance.addChild(child); 242 } 243 244 /** 245 * <p> 246 * internal convenience method for adding children to a structuring temporal 247 * relationship including a check for the child type. 248 * </p> 249 */ 250 private void addChildInternal(StructuringTemporalRelationship parent, 251 int index, ITask child) { 252 if (!(child instanceof Task)) { 253 throw new IllegalArgumentException( 254 "illegal type of task provided: " + child.getClass()); 255 } 256 257 if (index > -1) { 258 parent.addChild(index, child); 259 } else { 260 parent.addChild(child); 261 } 262 } 263 264 /* 265 * (non-Javadoc) 266 * 267 * @see ITaskBuilder#addExecutedTask(IUserSession, int, ITaskInstance) 268 */ 269 public void addExecutedTask(IUserSession session, int index, 270 ITaskInstance taskInstance) { 271 if (!(session instanceof UserSession)) { 272 throw new IllegalArgumentException( 273 "illegal type of session provided: " + session.getClass()); 274 } 275 276 if (!(taskInstance instanceof TaskInstance)) { 277 throw new IllegalArgumentException( 278 "illegal type of task instance provided: " 279 + taskInstance.getClass()); 280 } 281 282 ((UserSession) session).addExecutedTask(index, taskInstance); 283 } 284 285 /* 286 * (non-Javadoc) 287 * 288 * @see ITaskBuilder#addExecutedTask(IUserSession, ITaskInstance) 289 */ 290 @Override 291 public void addExecutedTask(IUserSession session, ITaskInstance taskInstance) { 292 if (!(session instanceof UserSession)) { 293 throw new IllegalArgumentException( 294 "illegal type of session provided: " + session.getClass()); 295 } 296 297 if (!(taskInstance instanceof TaskInstance)) { 298 throw new IllegalArgumentException( 299 "illegal type of task instance provided: " 300 + taskInstance.getClass()); 301 } 302 303 ((UserSession) session).addExecutedTask(taskInstance); 304 } 305 306 /* 307 * (non-Javadoc) 308 * 309 * @see ITaskBuilder#addTaskInstance(ITaskInstanceList, int, ITaskInstance) 310 */ 311 @Override 312 public void addTaskInstance(ITaskInstanceList taskInstanceList, int index, 313 ITaskInstance taskInstance) { 314 if (taskInstanceList instanceof SequenceInstance) { 315 addChild((SequenceInstance) taskInstanceList, index, taskInstance); 316 } else if (taskInstanceList instanceof IterationInstance) { 317 addChild((IterationInstance) taskInstanceList, index, taskInstance); 318 } else if (taskInstanceList instanceof UserSession) { 319 addExecutedTask((UserSession) taskInstanceList, index, taskInstance); 320 } else { 321 throw new IllegalArgumentException( 322 "illegal type of task instance list provided: " 323 + taskInstanceList.getClass()); 324 } 325 } 326 327 /* 328 * (non-Javadoc) 329 * 330 * @see ITaskBuilder#addTaskInstance(ITaskInstanceList, ITaskInstance) 331 */ 332 @Override 333 public void addTaskInstance(ITaskInstanceList taskInstanceList, 334 ITaskInstance taskInstance) { 335 if (taskInstanceList instanceof SequenceInstance) { 336 addChild((SequenceInstance) taskInstanceList, taskInstance); 337 } else if (taskInstanceList instanceof IterationInstance) { 338 addChild((IterationInstance) taskInstanceList, taskInstance); 339 } else if (taskInstanceList instanceof UserSession) { 340 addExecutedTask((UserSession) taskInstanceList, taskInstance); 341 } else { 342 throw new IllegalArgumentException( 343 "illegal type of task instance list provided: " 344 + taskInstanceList.getClass()); 345 } 346 } 347 348 /* 349 * (non-Javadoc) 350 * 351 * @see ITaskBuilder#removeChild(ISelection, ITask) 352 */ 353 @Override 354 public void removeChild(ISelection parent, ITask child) { 355 if (!(parent instanceof Selection)) { 356 throw new IllegalArgumentException( 357 "illegal type of selection provided: " + parent.getClass()); 358 } 359 360 final List<ITask> children = parent.getChildren(); 361 362 for (int i = 0; i < children.size(); i++) { 363 if ((children.get(i) == child) 364 || ((children.get(i) != null) && (children.get(i) 365 .equals(child)))) { 366 ((Selection) parent).removeChild(i); 367 break; 368 } 369 } 370 } 371 372 /* 373 * (non-Javadoc) 374 * 375 * @see ITaskBuilder#removeChild(ISequence, int) 376 */ 377 @Override 378 public void removeChild(ISequence parent, int index) { 379 if (!(parent instanceof Sequence)) { 380 throw new IllegalArgumentException( 381 "illegal type of sequence provided: " + parent.getClass()); 382 } 383 384 ((Sequence) parent).removeChild(index); 385 } 386 387 /* 388 * (non-Javadoc) 389 * 390 * @see ITaskBuilder#removeTaskInstance(ITaskInstanceList, int) 391 */ 392 @Override 393 public void removeTaskInstance(ITaskInstanceList taskInstanceList, int index) { 394 if (taskInstanceList instanceof SequenceInstance) { 395 ((SequenceInstance) taskInstanceList).removeChild(index); 396 } else if (taskInstanceList instanceof IterationInstance) { 397 ((IterationInstance) taskInstanceList).removeChild(index); 398 } else if (taskInstanceList instanceof UserSession) { 399 ((UserSession) taskInstanceList).removeExecutedTask(index); 400 } else { 401 throw new IllegalArgumentException( 402 "illegal type of task instance list provided: " 403 + taskInstanceList.getClass()); 404 } 405 } 406 407 /* 408 * (non-Javadoc) 409 * 410 * @see ITaskTreeBuilder#replaceChild(ISelection, ITaskTreeNode, 411 * ITaskTreeNode) 412 */ 413 @Override 414 public void replaceChild(ISelection parent, ITask oldChild, ITask newChild) { 415 if (!(parent instanceof Selection)) { 416 throw new IllegalArgumentException( 417 "illegal type of selection provided: " + parent.getClass()); 418 } 419 420 final List<ITask> children = parent.getChildren(); 421 422 for (int i = 0; i < children.size(); i++) { 423 if ((children.get(i) == oldChild) 424 || ((children.get(i) != null) && (children.get(i) 425 .equals(oldChild)))) { 426 ((Selection) parent).removeChild(i); 427 ((Selection) parent).addChild(i, newChild); 428 break; 429 } 430 } 431 } 432 433 /* 434 * (non-Javadoc) 435 * 436 * @see ITaskBuilder#setChild(IOptionalInstance, ITaskInstance) 437 */ 438 @Override 439 public void setChild(IOptionalInstance instance, ITaskInstance child) 440 throws IllegalArgumentException { 441 if (!(instance instanceof OptionalInstance)) { 442 throw new IllegalArgumentException( 443 "illegal type of optional instance provided: " 444 + instance.getClass()); 445 } 446 447 if (!(child instanceof TaskInstance)) { 448 throw new IllegalArgumentException( 449 "illegal type of task instance provided: " 450 + child.getClass()); 451 } 452 453 // check if new child instance matches the model, if this can be checked 454 final IMarkingTemporalRelationship parentTask = (IMarkingTemporalRelationship) instance 455 .getTask(); 456 457 final boolean foundChildTask = parentTask.getMarkedTask() != null ? parentTask 458 .getMarkedTask().equals(child.getTask()) : true; 459 460 if (!foundChildTask) { 461 throw new IllegalArgumentException( 462 "the task of the child instance does not match the model of the task of the " 463 + "optional instance: " 464 + parentTask.getMarkedTask() + " <> " 465 + child.getTask()); 466 } 467 468 ((OptionalInstance) instance).setChild(child); 469 } 470 471 /* 472 * (non-Javadoc) 473 * 474 * @see ITaskBuilder#setChild(ISelectionInstance, ITaskInstance) 475 */ 476 @Override 477 public void setChild(ISelectionInstance instance, ITaskInstance child) 478 throws IllegalArgumentException { 479 if (!(instance instanceof SelectionInstance)) { 480 throw new IllegalArgumentException( 481 "illegal type of selection instance provided: " 482 + instance.getClass()); 483 } 484 485 if (!(child instanceof TaskInstance)) { 486 throw new IllegalArgumentException( 487 "illegal type of task instance provided: " 488 + (child == null ? null : child.getClass())); 489 } 490 491 // check if new child instance matches the model, if this can be checked 492 final IStructuringTemporalRelationship parentTask = (IStructuringTemporalRelationship) instance 493 .getTask(); 494 495 boolean foundChildTask = false; 496 for (final ITask parentTaskChild : parentTask.getChildren()) { 497 if (parentTaskChild.equals(child.getTask())) { 498 foundChildTask = true; 499 break; 500 } 501 } 502 503 if (!foundChildTask) { 504 throw new IllegalArgumentException( 505 "the task of the child instance to be added does not belong to the children " 506 + "of the selection task model of the parent instance"); 507 } 508 509 ((SelectionInstance) instance).setChild(child); 510 } 511 512 /* 513 * (non-Javadoc) 514 * 515 * @see ITaskBuilder#setChild(ISequence, int, ITask) 516 */ 517 @Override 518 public void setChild(ISequence parent, int index, ITask child) { 519 if (!(parent instanceof Sequence)) { 520 throw new IllegalArgumentException( 521 "illegal type of sequence provided: " + parent.getClass()); 522 } 523 524 ((Sequence) parent).removeChild(index); 525 addChildInternal((Sequence) parent, index, child); 526 } 527 528 /* 529 * (non-Javadoc) 530 * 531 * @see ITaskBuilder#setMarkedTask(IIteration, ITask) 532 */ 533 @Override 534 public void setMarkedTask(IIteration iteration, ITask newChild) { 535 if (!(iteration instanceof Iteration)) { 536 throw new IllegalArgumentException( 537 "illegal type of iteration provided: " 538 + iteration.getClass()); 539 } 540 541 if (!(newChild instanceof Task)) { 542 throw new IllegalArgumentException( 543 "illegal type of task provided: " + newChild.getClass()); 544 } 545 546 ((Iteration) iteration).setMarkedTask(newChild); 547 } 548 549 /* 550 * (non-Javadoc) 551 * 552 * @see ITaskTreeBuilder#setChild(IOptional, ITaskTreeNode) 553 */ 554 @Override 555 public void setMarkedTask(IOptional optional, ITask newChild) { 556 if (!(optional instanceof Optional)) { 557 throw new IllegalArgumentException( 558 "illegal type of optional provided: " + optional.getClass()); 559 } 560 561 if (!(newChild instanceof Task)) { 562 throw new IllegalArgumentException( 563 "illegal type of task provided: " + newChild.getClass()); 564 } 565 566 ((Optional) optional).setMarkedTask(newChild); 567 } 568 569 /* 570 * (non-Javadoc) 571 * 572 * @see ITaskBuilder#setTask(ITaskInstance, ITask) 573 */ 574 @Override 575 public void setTask(ITaskInstance taskInstance, ITask task) { 576 if (!(taskInstance instanceof TaskInstance)) { 577 throw new IllegalArgumentException( 578 "illegal type of task instance provided: " 579 + taskInstance.getClass()); 580 } 581 if (!(task instanceof Task)) { 582 throw new IllegalArgumentException( 583 "illegal type of task provided: " + task.getClass()); 584 } 585 586 if (((TaskInstance) taskInstance).getTask() instanceof Task) { 587 ((Task) ((TaskInstance) taskInstance).getTask()) 588 .removeInstance(taskInstance); 589 } 590 ((TaskInstance) taskInstance).setTask(task); 591 592 ((Task) task).addInstance(taskInstance); 593 } 594 595 /* 596 * (non-Javadoc) 597 * 598 * @see ITaskBuilder#setTaskInstance(ITaskInstanceList, int, ITaskInstance) 599 */ 600 @Override 601 public void setTaskInstance(ITaskInstanceList taskInstanceList, int index, 602 ITaskInstance taskInstance) { 603 removeTaskInstance(taskInstanceList, index); 604 addTaskInstance(taskInstanceList, index, taskInstance); 605 } 549 606 550 607 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/TaskFactory.java
r1294 r1733 35 35 * <p> 36 36 * this is the default implementation of the interface {@link ITaskFactory}. It 37 * does not do anything fancy except implementing the interface. It instantiates the other38 * implementations of the tree ifc in this package.37 * does not do anything fancy except implementing the interface. It instantiates 38 * the other implementations of the tree ifc in this package. 39 39 * </p> 40 40 * … … 43 43 public class TaskFactory implements ITaskFactory { 44 44 45 /* (non-Javadoc) 46 * @see ITaskFactory#createNewEventTask(String) 47 */ 48 @Override 49 public IEventTask createNewEventTask(String description) { 50 return new EventTask(description); 51 } 52 53 /* (non-Javadoc) 54 * @see ITaskFactory#createNewSequence() 55 */ 56 @Override 57 public ISequence createNewSequence() { 58 return new Sequence(); 59 } 60 61 /* (non-Javadoc) 62 * @see ITaskFactory#createNewIteration() 63 */ 64 @Override 65 public IIteration createNewIteration() { 66 return new Iteration(); 67 } 68 69 /* (non-Javadoc) 70 * @see ITaskFactory#createNewOptional() 71 */ 72 @Override 73 public IOptional createNewOptional() { 74 return new Optional(); 75 } 76 77 /* (non-Javadoc) 78 * @see ITaskFactory#createNewSelection() 79 */ 80 @Override 81 public ISelection createNewSelection() { 82 return new Selection(); 83 } 84 85 /* (non-Javadoc) 86 * @see ITaskFactory#createNewTaskInstance(IEventTask, Event) 87 */ 88 @Override 89 public IEventTaskInstance createNewTaskInstance(IEventTask task, Event event) { 90 if (!(task instanceof EventTask)) { 91 throw new IllegalArgumentException 92 ("illegal type of event task provided: " + task.getClass()); 93 } 94 95 EventTaskInstance instance = new EventTaskInstance(task, event); 96 ((EventTask) task).addInstance(instance); 97 98 return instance; 99 } 100 101 /* (non-Javadoc) 102 * @see ITaskFactory#createNewTaskInstance(ISequence) 103 */ 104 @Override 105 public ISequenceInstance createNewTaskInstance(ISequence sequence) { 106 if (!(sequence instanceof Sequence)) { 107 throw new IllegalArgumentException 108 ("illegal type of sequence provided: " + sequence.getClass()); 109 } 110 111 SequenceInstance instance = new SequenceInstance(sequence); 112 ((Sequence) sequence).addInstance(instance); 113 114 return instance; 115 } 116 117 /* (non-Javadoc) 118 * @see ITaskFactory#createNewTaskInstance(IIteration) 119 */ 120 @Override 121 public IIterationInstance createNewTaskInstance(IIteration iteration) { 122 if (!(iteration instanceof Iteration)) { 123 throw new IllegalArgumentException 124 ("illegal type of iteration provided: " + iteration.getClass()); 125 } 126 127 IterationInstance instance = new IterationInstance(iteration); 128 ((Iteration) iteration).addInstance(instance); 129 130 return instance; 131 } 132 133 /* (non-Javadoc) 134 * @see ITaskFactory#createNewTaskInstance(IOptional) 135 */ 136 @Override 137 public IOptionalInstance createNewTaskInstance(IOptional optional) { 138 if (!(optional instanceof Optional)) { 139 throw new IllegalArgumentException 140 ("illegal type of optional provided: " + optional.getClass()); 141 } 142 143 OptionalInstance instance = new OptionalInstance(optional); 144 ((Optional) optional).addInstance(instance); 145 146 return instance; 147 } 148 149 /* (non-Javadoc) 150 * @see ITaskFactory#createNewTaskInstance(ISelection) 151 */ 152 @Override 153 public ISelectionInstance createNewTaskInstance(ISelection selection) { 154 if (!(selection instanceof Selection)) { 155 throw new IllegalArgumentException 156 ("illegal type of optional provided: " + selection.getClass()); 157 } 158 159 SelectionInstance instance = new SelectionInstance(selection); 160 ((Selection) selection).addInstance(instance); 161 162 return instance; 163 } 164 165 /* (non-Javadoc) 166 * @see ITaskFactory#createUserSession() 167 */ 168 @Override 169 public IUserSession createUserSession() { 170 return new UserSession(); 171 } 172 173 /* (non-Javadoc) 174 * @see ITaskFactory#createTaskModel(List<IUserSession>) 175 */ 176 @Override 177 public ITaskModel createTaskModel(List<IUserSession> userSessions) { 178 return new TaskModel(userSessions); 179 } 45 /* 46 * (non-Javadoc) 47 * 48 * @see ITaskFactory#createNewEventTask(String) 49 */ 50 @Override 51 public IEventTask createNewEventTask(String description) { 52 return new EventTask(description); 53 } 54 55 /* 56 * (non-Javadoc) 57 * 58 * @see ITaskFactory#createNewIteration() 59 */ 60 @Override 61 public IIteration createNewIteration() { 62 return new Iteration(); 63 } 64 65 /* 66 * (non-Javadoc) 67 * 68 * @see ITaskFactory#createNewOptional() 69 */ 70 @Override 71 public IOptional createNewOptional() { 72 return new Optional(); 73 } 74 75 /* 76 * (non-Javadoc) 77 * 78 * @see ITaskFactory#createNewSelection() 79 */ 80 @Override 81 public ISelection createNewSelection() { 82 return new Selection(); 83 } 84 85 /* 86 * (non-Javadoc) 87 * 88 * @see ITaskFactory#createNewSequence() 89 */ 90 @Override 91 public ISequence createNewSequence() { 92 return new Sequence(); 93 } 94 95 /* 96 * (non-Javadoc) 97 * 98 * @see ITaskFactory#createNewTaskInstance(IEventTask, Event) 99 */ 100 @Override 101 public IEventTaskInstance createNewTaskInstance(IEventTask task, Event event) { 102 if (!(task instanceof EventTask)) { 103 throw new IllegalArgumentException( 104 "illegal type of event task provided: " + task.getClass()); 105 } 106 107 final EventTaskInstance instance = new EventTaskInstance(task, event); 108 ((EventTask) task).addInstance(instance); 109 110 return instance; 111 } 112 113 /* 114 * (non-Javadoc) 115 * 116 * @see ITaskFactory#createNewTaskInstance(IIteration) 117 */ 118 @Override 119 public IIterationInstance createNewTaskInstance(IIteration iteration) { 120 if (!(iteration instanceof Iteration)) { 121 throw new IllegalArgumentException( 122 "illegal type of iteration provided: " 123 + iteration.getClass()); 124 } 125 126 final IterationInstance instance = new IterationInstance(iteration); 127 ((Iteration) iteration).addInstance(instance); 128 129 return instance; 130 } 131 132 /* 133 * (non-Javadoc) 134 * 135 * @see ITaskFactory#createNewTaskInstance(IOptional) 136 */ 137 @Override 138 public IOptionalInstance createNewTaskInstance(IOptional optional) { 139 if (!(optional instanceof Optional)) { 140 throw new IllegalArgumentException( 141 "illegal type of optional provided: " + optional.getClass()); 142 } 143 144 final OptionalInstance instance = new OptionalInstance(optional); 145 ((Optional) optional).addInstance(instance); 146 147 return instance; 148 } 149 150 /* 151 * (non-Javadoc) 152 * 153 * @see ITaskFactory#createNewTaskInstance(ISelection) 154 */ 155 @Override 156 public ISelectionInstance createNewTaskInstance(ISelection selection) { 157 if (!(selection instanceof Selection)) { 158 throw new IllegalArgumentException( 159 "illegal type of optional provided: " 160 + selection.getClass()); 161 } 162 163 final SelectionInstance instance = new SelectionInstance(selection); 164 ((Selection) selection).addInstance(instance); 165 166 return instance; 167 } 168 169 /* 170 * (non-Javadoc) 171 * 172 * @see ITaskFactory#createNewTaskInstance(ISequence) 173 */ 174 @Override 175 public ISequenceInstance createNewTaskInstance(ISequence sequence) { 176 if (!(sequence instanceof Sequence)) { 177 throw new IllegalArgumentException( 178 "illegal type of sequence provided: " + sequence.getClass()); 179 } 180 181 final SequenceInstance instance = new SequenceInstance(sequence); 182 ((Sequence) sequence).addInstance(instance); 183 184 return instance; 185 } 186 187 /* 188 * (non-Javadoc) 189 * 190 * @see ITaskFactory#createTaskModel(List<IUserSession>) 191 */ 192 @Override 193 public ITaskModel createTaskModel(List<IUserSession> userSessions) { 194 return new TaskModel(userSessions); 195 } 196 197 /* 198 * (non-Javadoc) 199 * 200 * @see ITaskFactory#createUserSession() 201 */ 202 @Override 203 public IUserSession createUserSession() { 204 return new UserSession(); 205 } 180 206 181 207 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/TaskInfo.java
r1428 r1733 31 31 */ 32 32 public class TaskInfo implements ITaskInfo { 33 34 /** 35 * <p> 36 * the task to which the infos belong 37 * </p> 38 */ 39 private ITask task; 40 41 /** 42 * <p> 43 * all available measures for the task 44 * </p> 45 */ 46 private ArrayList<Measure> measures = new ArrayList<Measure>(); 47 48 /** 49 * <p> 50 * initialized the task infos with the task to which they belong. 51 * </p> 52 * 53 * @param task 54 */ 55 TaskInfo(ITask task) { 56 this.task = task; 57 } 58 59 /* (non-Javadoc) 60 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo#getTask() 61 */ 62 @Override 63 public ITask getTask() { 64 return task; 65 } 66 67 /* (non-Javadoc) 68 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo#getMeasures() 69 */ 70 @Override 71 public IMeasure[] getMeasures() { 72 measures.trimToSize(); 73 return measures.toArray(new IMeasure[measures.size()]); 74 } 75 76 /* (non-Javadoc) 77 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo#getMeasureValue(java.lang.String) 78 */ 79 @Override 80 public int getMeasureValue(TaskMetric metric) { 81 Measure measure = getMeasure(metric); 82 83 if (measure == null) { 84 throw new IllegalArgumentException("unknown metric " + metric); 85 } 86 87 return measure.getValue(); 88 } 89 90 /* (non-Javadoc) 91 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo#getMeasureValue(java.lang.String, de.ugoe.cs.autoquest.tasktrees.treeifc.ITask) 92 */ 93 @Override 94 public int getMeasureValue(TaskMetric metric, ITask context) { 95 Measure measure = getMeasure(metric); 96 97 if (measure == null) { 98 throw new IllegalArgumentException("unknown metric " + metric); 99 } 100 101 return measure.getValue(context); 102 } 103 104 /* (non-Javadoc) 105 * @see java.lang.Object#toString() 106 */ 107 @Override 108 public synchronized String toString() { 109 return "TaskInfo(" + task + ")"; 110 } 111 112 /** 113 * <p> 114 * must be called to indicate that a new new measures for the provided metric are about to 115 * be calculated and added. 116 * </p> 117 * 118 * @param metric the metric for which measures are about to be provided 119 */ 120 void addMeasure(TaskMetric metric) { 121 Measure measure = getMeasure(metric); 122 123 if (measure != null) { 124 throw new IllegalArgumentException("measure for metric " + metric + " already exists."); 125 } 126 127 measure = new Measure(metric); 128 measures.add(measure); 129 } 130 131 /** 132 * <p> 133 * sets a specific value for a measure of a specific metric in the provided context of the task 134 * </p> 135 * 136 * @param metric the metric to which the value belongs 137 * @param context the context of the task in which the measure was recorded 138 * @param value the value of the measure 139 */ 140 void setCount(TaskMetric metric, ITask context, int value) { 141 Measure measure = getMeasure(metric); 142 143 if (measure == null) { 144 throw new IllegalArgumentException("unknown metric. Please create a measure " + 145 "for the metric before using it."); 146 } 147 148 measure.set(context, value); 149 } 150 151 /** 152 * <p> 153 * increases a specific value for a measure of a specific metric in the provided context of the 154 * task 155 * </p> 156 * 157 * @param metric the metric to which the value belongs 158 * @param context the context of the task in which the measure was recorded 159 * @param increment the increment to be added to the value of the measure 160 */ 161 void increaseCount(TaskMetric metric, ITask context, int increment) { 162 Measure measure = getMeasure(metric); 163 164 if (measure == null) { 165 throw new IllegalArgumentException("unknown metric. Please create a measure " + 166 "for the metric before using it."); 167 } 168 169 measure.increase(context, increment); 170 } 171 172 /** 173 * <p> 174 * convenience method to internally determine the measure for a specific metric 175 * </p> 176 */ 177 private Measure getMeasure(TaskMetric metric) { 178 for (Measure candidate : measures) { 179 if (candidate.getMetric().equals(metric)) { 180 return candidate; 181 } 182 } 183 184 return null; 185 } 186 187 /** 188 * <p> 189 * implementation for the measure interface of the task info interface. Does nothing fancy 190 * except implementing the interface 191 * </p> 192 * 193 * @author Patrick Harms 194 */ 195 private static class Measure implements IMeasure { 196 197 /** 198 * <p> 199 * the metric to which the measure belongs 200 * </p> 201 */ 202 private TaskMetric metric; 203 204 /** 205 * <p> 206 * the observed values for the difference contexts of the task 207 * </p> 208 */ 209 private HashMap<ITask, Integer> values; 210 211 /** 212 * <p> 213 * the context free value of the measure independent of the task context 214 * </p> 215 */ 216 private int contextFreeValue = 0; 217 218 /** 219 * <p> 220 * initializes the measure with a specific metric 221 * </p> 222 */ 223 private Measure(TaskMetric metric) { 224 super(); 225 this.metric = metric; 226 } 227 228 /* (non-Javadoc) 229 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo.IMeasure#getMetric() 230 */ 231 @Override 232 public TaskMetric getMetric() { 233 return metric; 234 } 235 236 /* (non-Javadoc) 237 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo.IMeasure#getValue() 238 */ 239 @Override 240 public int getValue() { 241 return contextFreeValue; 242 } 243 244 /* (non-Javadoc) 245 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo.IMeasure#getValue(de.ugoe.cs.autoquest.tasktrees.treeifc.ITask) 246 */ 247 @Override 248 public int getValue(ITask context) { 249 if ((context != null) && (values != null)) { 250 Integer currentValue = values.get(context); 251 252 if (currentValue != null) { 253 return currentValue; 254 } 255 } 256 257 return Integer.MIN_VALUE; 258 } 259 260 /** 261 * <p> 262 * sets the value of the measure context free as well as specific to the provided context 263 * </p> 264 */ 265 private void set(ITask context, int value) { 266 contextFreeValue = value; 267 268 if (context != null) { 269 if (values == null) { 270 values = new HashMap<ITask, Integer>(); 271 } 272 273 values.put(context, value); 274 } 275 } 276 277 /** 278 * <p> 279 * increases the value of the measure context free as well as specific to the provided 280 * context according to the provided increment 281 * </p> 282 */ 283 private void increase(ITask context, int increment) { 284 contextFreeValue += increment; 285 286 if (context != null) { 287 if (values == null) { 288 values = new HashMap<ITask, Integer>(); 289 } 290 291 Integer currentValue = values.get(context); 292 293 if (currentValue == null) { 294 currentValue = 0; 295 } 296 297 values.put(context, currentValue + increment); 298 } 299 } 300 301 } 33 34 /** 35 * <p> 36 * implementation for the measure interface of the task info interface. Does 37 * nothing fancy except implementing the interface 38 * </p> 39 * 40 * @author Patrick Harms 41 */ 42 private static class Measure implements IMeasure { 43 44 /** 45 * <p> 46 * the metric to which the measure belongs 47 * </p> 48 */ 49 private final TaskMetric metric; 50 51 /** 52 * <p> 53 * the observed values for the difference contexts of the task 54 * </p> 55 */ 56 private HashMap<ITask, Integer> values; 57 58 /** 59 * <p> 60 * the context free value of the measure independent of the task context 61 * </p> 62 */ 63 private int contextFreeValue = 0; 64 65 /** 66 * <p> 67 * initializes the measure with a specific metric 68 * </p> 69 */ 70 private Measure(TaskMetric metric) { 71 super(); 72 this.metric = metric; 73 } 74 75 /* 76 * (non-Javadoc) 77 * 78 * @see 79 * de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo.IMeasure#getMetric() 80 */ 81 @Override 82 public TaskMetric getMetric() { 83 return metric; 84 } 85 86 /* 87 * (non-Javadoc) 88 * 89 * @see 90 * de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo.IMeasure#getValue() 91 */ 92 @Override 93 public int getValue() { 94 return contextFreeValue; 95 } 96 97 /* 98 * (non-Javadoc) 99 * 100 * @see 101 * de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo.IMeasure#getValue 102 * (de.ugoe.cs.autoquest.tasktrees.treeifc.ITask) 103 */ 104 @Override 105 public int getValue(ITask context) { 106 if ((context != null) && (values != null)) { 107 final Integer currentValue = values.get(context); 108 109 if (currentValue != null) { 110 return currentValue; 111 } 112 } 113 114 return Integer.MIN_VALUE; 115 } 116 117 /** 118 * <p> 119 * increases the value of the measure context free as well as specific 120 * to the provided context according to the provided increment 121 * </p> 122 */ 123 private void increase(ITask context, int increment) { 124 contextFreeValue += increment; 125 126 if (context != null) { 127 if (values == null) { 128 values = new HashMap<ITask, Integer>(); 129 } 130 131 Integer currentValue = values.get(context); 132 133 if (currentValue == null) { 134 currentValue = 0; 135 } 136 137 values.put(context, currentValue + increment); 138 } 139 } 140 141 /** 142 * <p> 143 * sets the value of the measure context free as well as specific to the 144 * provided context 145 * </p> 146 */ 147 private void set(ITask context, int value) { 148 contextFreeValue = value; 149 150 if (context != null) { 151 if (values == null) { 152 values = new HashMap<ITask, Integer>(); 153 } 154 155 values.put(context, value); 156 } 157 } 158 159 } 160 161 /** 162 * <p> 163 * the task to which the infos belong 164 * </p> 165 */ 166 private final ITask task; 167 168 /** 169 * <p> 170 * all available measures for the task 171 * </p> 172 */ 173 private final ArrayList<Measure> measures = new ArrayList<Measure>(); 174 175 /** 176 * <p> 177 * initialized the task infos with the task to which they belong. 178 * </p> 179 * 180 * @param task 181 */ 182 TaskInfo(ITask task) { 183 this.task = task; 184 } 185 186 /** 187 * <p> 188 * must be called to indicate that a new new measures for the provided 189 * metric are about to be calculated and added. 190 * </p> 191 * 192 * @param metric 193 * the metric for which measures are about to be provided 194 */ 195 void addMeasure(TaskMetric metric) { 196 Measure measure = getMeasure(metric); 197 198 if (measure != null) { 199 throw new IllegalArgumentException("measure for metric " + metric 200 + " already exists."); 201 } 202 203 measure = new Measure(metric); 204 measures.add(measure); 205 } 206 207 /** 208 * <p> 209 * convenience method to internally determine the measure for a specific 210 * metric 211 * </p> 212 */ 213 private Measure getMeasure(TaskMetric metric) { 214 for (final Measure candidate : measures) { 215 if (candidate.getMetric().equals(metric)) { 216 return candidate; 217 } 218 } 219 220 return null; 221 } 222 223 /* 224 * (non-Javadoc) 225 * 226 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo#getMeasures() 227 */ 228 @Override 229 public IMeasure[] getMeasures() { 230 measures.trimToSize(); 231 return measures.toArray(new IMeasure[measures.size()]); 232 } 233 234 /* 235 * (non-Javadoc) 236 * 237 * @see 238 * de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo#getMeasureValue(java 239 * .lang.String) 240 */ 241 @Override 242 public int getMeasureValue(TaskMetric metric) { 243 final Measure measure = getMeasure(metric); 244 245 if (measure == null) { 246 throw new IllegalArgumentException("unknown metric " + metric); 247 } 248 249 return measure.getValue(); 250 } 251 252 /* 253 * (non-Javadoc) 254 * 255 * @see 256 * de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo#getMeasureValue(java 257 * .lang.String, de.ugoe.cs.autoquest.tasktrees.treeifc.ITask) 258 */ 259 @Override 260 public int getMeasureValue(TaskMetric metric, ITask context) { 261 final Measure measure = getMeasure(metric); 262 263 if (measure == null) { 264 throw new IllegalArgumentException("unknown metric " + metric); 265 } 266 267 return measure.getValue(context); 268 } 269 270 /* 271 * (non-Javadoc) 272 * 273 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo#getTask() 274 */ 275 @Override 276 public ITask getTask() { 277 return task; 278 } 279 280 /** 281 * <p> 282 * increases a specific value for a measure of a specific metric in the 283 * provided context of the task 284 * </p> 285 * 286 * @param metric 287 * the metric to which the value belongs 288 * @param context 289 * the context of the task in which the measure was recorded 290 * @param increment 291 * the increment to be added to the value of the measure 292 */ 293 void increaseCount(TaskMetric metric, ITask context, int increment) { 294 final Measure measure = getMeasure(metric); 295 296 if (measure == null) { 297 throw new IllegalArgumentException( 298 "unknown metric. Please create a measure " 299 + "for the metric before using it."); 300 } 301 302 measure.increase(context, increment); 303 } 304 305 /** 306 * <p> 307 * sets a specific value for a measure of a specific metric in the provided 308 * context of the task 309 * </p> 310 * 311 * @param metric 312 * the metric to which the value belongs 313 * @param context 314 * the context of the task in which the measure was recorded 315 * @param value 316 * the value of the measure 317 */ 318 void setCount(TaskMetric metric, ITask context, int value) { 319 final Measure measure = getMeasure(metric); 320 321 if (measure == null) { 322 throw new IllegalArgumentException( 323 "unknown metric. Please create a measure " 324 + "for the metric before using it."); 325 } 326 327 measure.set(context, value); 328 } 329 330 /* 331 * (non-Javadoc) 332 * 333 * @see java.lang.Object#toString() 334 */ 335 @Override 336 public synchronized String toString() { 337 return "TaskInfo(" + task + ")"; 338 } 302 339 303 340 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/TaskInstance.java
r1405 r1733 28 28 */ 29 29 class TaskInstance implements ITaskInstance { 30 31 /**32 * <p>33 * default serial version UID34 * </p>35 */36 private static final long serialVersionUID = 1L;37 30 38 /** 39 * <p> 40 * used as a counter to generate new ids for each newly created task instance. May overflow. 41 * </p> 42 */ 43 private static int temporalId = 0; 31 /** 32 * <p> 33 * creates a new id for a task instance using {@link #temporalId} by 34 * incrementing it an returning its current value. Resets the counter if 35 * {@link Integer.MAX_VALUE} is reached. 36 * </p> 37 * 38 * @return a new unique id for a task instance as long as 39 * {@link #temporalId} does not overflow 40 */ 41 private static synchronized int getNewId() { 42 if (temporalId == Integer.MAX_VALUE) { 43 temporalId = 0; 44 } 44 45 45 /** 46 * <p> 47 * the task instantiated by this task instance 48 * </p> 49 */ 50 private ITask task; 51 52 /** 53 * <p> 54 * the id of the task instance (unique throughout the system as long as {@link #temporalId} 55 * does not overflow. 56 * </p> 57 */ 58 private int id; 46 return temporalId++; 47 } 59 48 60 /** 61 * <p> 62 * instantiated the task instance with the task that is instantiated by the instance. It also 63 * assigns a unique id to the instance using {@link #getNewId()}. 64 * </p> 65 */ 66 TaskInstance(ITask task) { 67 this.task = task; 68 id = getNewId(); 69 } 49 /** 50 * <p> 51 * default serial version UID 52 * </p> 53 */ 54 private static final long serialVersionUID = 1L; 70 55 71 /** 72 * <p> 73 * creates a new id for a task instance using {@link #temporalId} by incrementing it an 74 * returning its current value. Resets the counter if {@link Integer.MAX_VALUE} is reached. 75 * </p> 76 * 77 * @return a new unique id for a task instance as long as {@link #temporalId} does not overflow 78 */ 79 private static synchronized int getNewId() { 80 if (temporalId == Integer.MAX_VALUE) { 81 temporalId = 0; 82 } 56 /** 57 * <p> 58 * used as a counter to generate new ids for each newly created task 59 * instance. May overflow. 60 * </p> 61 */ 62 private static int temporalId = 0; 83 63 84 return temporalId++; 85 } 64 /** 65 * <p> 66 * the task instantiated by this task instance 67 * </p> 68 */ 69 private ITask task; 86 70 87 /* (non-Javadoc) 88 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance#getTask() 89 */ 90 @Override 91 public ITask getTask() { 92 return task; 93 } 71 /** 72 * <p> 73 * the id of the task instance (unique throughout the system as long as 74 * {@link #temporalId} does not overflow. 75 * </p> 76 */ 77 private final int id; 94 78 95 /*96 * (non-Javadoc) 97 * 98 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.TaskTreeNode#equals(TaskTreeNode) 99 */ 100 @Override 101 public boolean equals(ITaskInstance taskInstance) { 102 // task instances are only equal if they are identical or if they have the same id 103 // (may happen, if they are cloned) 104 return (this == taskInstance) || (this.hashCode() == taskInstance.hashCode());105 79 /** 80 * <p> 81 * instantiated the task instance with the task that is instantiated by the 82 * instance. It also assigns a unique id to the instance using 83 * {@link #getNewId()}. 84 * </p> 85 */ 86 TaskInstance(ITask task) { 87 this.task = task; 88 id = getNewId(); 89 } 106 90 107 /* (non-Javadoc) 108 * @see java.lang.Object#hashCode() 109 */ 110 @Override 111 public synchronized int hashCode() { 112 return id; 113 } 91 /* 92 * (non-Javadoc) 93 * 94 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance#accept( 95 * ITaskInstanceVisitor) 96 */ 97 @Override 98 public void accept(ITaskInstanceVisitor visitor) { 99 visitor.visit(this); 100 } 114 101 115 /* (non-Javadoc) 116 * @see java.lang.Object#toString() 117 */ 118 @Override 119 public synchronized String toString() { 120 StringBuffer result = new StringBuffer(); 121 result.append(task.getType()); 122 result.append(" #"); 123 result.append(task.getId()); 124 125 if (task.getDescription() != null) { 126 result.append(" ("); 127 result.append(task.getDescription()); 128 result.append(')'); 129 } 130 131 /*if (children != null) { 132 result.append(", "); 133 result.append(children.size()); 134 result.append(" children"); 135 }*/ 136 137 return result.toString(); 138 } 102 /* 103 * (non-Javadoc) 104 * 105 * @see java.lang.Object#clone() 106 */ 107 @Override 108 public synchronized ITaskInstance clone() { 109 TaskInstance clone = null; 110 try { 111 clone = (TaskInstance) super.clone(); 112 } catch (final CloneNotSupportedException e) { 113 // this should never happen. Therefore simply dump the exception 114 e.printStackTrace(); 115 } 139 116 140 /* (non-Javadoc) 141 * @see java.lang.Object#clone() 142 */ 143 @Override 144 public synchronized ITaskInstance clone() { 145 TaskInstance clone = null; 146 try { 147 clone = (TaskInstance) super.clone(); 148 } 149 catch (CloneNotSupportedException e) { 150 // this should never happen. Therefore simply dump the exception 151 e.printStackTrace(); 152 } 117 return clone; 118 } 153 119 154 return clone; 155 } 120 /* 121 * (non-Javadoc) 122 * 123 * @see 124 * de.ugoe.cs.autoquest.tasktrees.treeifc.TaskTreeNode#equals(TaskTreeNode) 125 */ 126 @Override 127 public boolean equals(ITaskInstance taskInstance) { 128 // task instances are only equal if they are identical or if they have 129 // the same id 130 // (may happen, if they are cloned) 131 return (this == taskInstance) 132 || (this.hashCode() == taskInstance.hashCode()); 133 } 156 134 157 /* (non-Javadoc) 158 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance#accept(ITaskInstanceVisitor) 159 */ 160 @Override 161 public void accept(ITaskInstanceVisitor visitor) { 162 visitor.visit(this); 163 } 135 /* 136 * (non-Javadoc) 137 * 138 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance#getTask() 139 */ 140 @Override 141 public ITask getTask() { 142 return task; 143 } 164 144 165 /** 166 * <p> 167 * used to update the task represented through this instance 168 * </p> 169 * 170 * @param task the task to set 171 */ 172 void setTask(ITask task) { 173 this.task = task; 174 } 145 /* 146 * (non-Javadoc) 147 * 148 * @see java.lang.Object#hashCode() 149 */ 150 @Override 151 public synchronized int hashCode() { 152 return id; 153 } 154 155 /** 156 * <p> 157 * used to update the task represented through this instance 158 * </p> 159 * 160 * @param task 161 * the task to set 162 */ 163 void setTask(ITask task) { 164 this.task = task; 165 } 166 167 /* 168 * (non-Javadoc) 169 * 170 * @see java.lang.Object#toString() 171 */ 172 @Override 173 public synchronized String toString() { 174 final StringBuffer result = new StringBuffer(); 175 result.append(task.getType()); 176 result.append(" #"); 177 result.append(task.getId()); 178 179 if (task.getDescription() != null) { 180 result.append(" ("); 181 result.append(task.getDescription()); 182 result.append(')'); 183 } 184 185 /* 186 * if (children != null) { result.append(", "); 187 * result.append(children.size()); result.append(" children"); } 188 */ 189 190 return result.toString(); 191 } 175 192 176 193 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/TaskModel.java
r1494 r1733 43 43 * <p> 44 44 * this is the default implementation of the interface {@link ITaskModel}. It 45 * does not do anything fancy except implementing the interface. It also calculates on 46 * initialisations the measures for diverse metrics of the task belonging to the model 45 * does not do anything fancy except implementing the interface. It also 46 * calculates on initialisations the measures for diverse metrics of the task 47 * belonging to the model 47 48 * </p> 48 49 * … … 50 51 */ 51 52 class TaskModel implements ITaskModel { 52 53 /** 54 * <p> 55 * default serial version UID 56 * </p> 57 */ 58 private static final long serialVersionUID = 1L; 59 60 /** 61 * <p> 62 * all metrics calculated by this type of task model 63 * </p> 64 */ 65 private static final TaskMetric[] taskMetrics = new TaskMetric[] 66 { TaskMetric.COUNT, 67 TaskMetric.DEPTH, 68 TaskMetric.EVENT_COVERAGE, 69 TaskMetric.EVENT_COVERAGE_RATIO, 70 TaskMetric.EVENT_COVERAGE_QUANTILE }; 71 72 /** 73 * <p> 74 * the user sessions belonging to the model 75 * </p> 76 */ 77 private List<IUserSession> userSessions; 78 79 /** 80 * <p> 81 * index for effectively accessing the model and calculating statistics about it 82 * </p> 83 */ 84 private transient TaskModelIndex index = null; 85 86 /** 87 * <p> 88 * initializes the task model with the user sessions out of which the tasks are extracted 89 * </p> 90 * 91 * @param userSessions as described 92 */ 93 TaskModel(List<IUserSession> userSessions) { 94 if ((userSessions == null) || (userSessions.size() == 0)) { 95 throw new IllegalArgumentException("user sessions must not be null"); 96 } 97 98 this.userSessions = userSessions; 99 } 100 101 102 /* (non-Javadoc) 103 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel#getUserSessions() 104 */ 105 @Override 106 public List<IUserSession> getUserSessions() { 107 ensureInitialized(); 108 return Collections.unmodifiableList(userSessions); 109 } 110 111 112 /* (non-Javadoc) 113 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel#getTasks() 114 */ 115 @Override 116 public Collection<ITask> getTasks() { 117 ensureInitialized(); 118 return Collections.unmodifiableCollection(index.taskMap.keySet()); 119 } 120 121 122 /* (non-Javadoc) 123 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel#getTaskInfo(ITask) 124 */ 125 @Override 126 public ITaskInfo getTaskInfo(ITask task) { 127 ensureInitialized(); 128 return index.taskMap.get(task); 129 } 130 131 /* (non-Javadoc) 132 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel#getAllMetrics() 133 */ 134 @Override 135 public TaskMetric[] getAllMetrics() { 136 return taskMetrics; 137 } 138 139 140 /* (non-Javadoc) 141 * @see java.lang.Object#clone() 142 */ 143 @Override 144 public TaskModel clone() { 145 return new TaskModel(userSessions); 146 } 147 148 /** 149 * <p> 150 * internal convenience method that initializes the internal index and calculates all measures 151 * for metrics available for the tasks 152 * </p> 153 */ 154 private synchronized void ensureInitialized() { 155 if (index == null) { 156 index = new TaskModelIndex(); 157 158 for (IUserSession session : this.userSessions) { 159 for (ITaskInstance taskInstance : session) { 160 index.handleTaskInstance(taskInstance, null); 161 } 162 } 163 164 // count all events covered 165 int allEventsCovered = 0; 166 Collection<ITask> tasks = getTasks(); 167 for (ITask task : tasks) { 168 if (task instanceof IEventTask) { 169 allEventsCovered += task.getInstances().size(); 170 } 171 } 172 173 int[] eventCoverageRatios = new int[tasks.size()]; 174 int i = 0; 175 176 // add some further measures 177 for (ITask task : tasks) { 178 TaskInfo info = index.taskMap.get(task); 179 info.addMeasure(TaskMetric.EVENT_COVERAGE_RATIO); 180 181 int coveredEvents = info.getMeasureValue(TaskMetric.EVENT_COVERAGE); 182 int coverageRatio = 0; 183 184 if (allEventsCovered > 0) { 185 coverageRatio = (coveredEvents * 1000) / allEventsCovered; 186 } 187 188 eventCoverageRatios[i++] = coverageRatio; 189 info.setCount(TaskMetric.EVENT_COVERAGE_RATIO, null, coverageRatio); 190 } 191 192 Arrays.sort(eventCoverageRatios); 193 194 // add some further measures 195 for (ITask task : tasks) { 196 TaskInfo info = index.taskMap.get(task); 197 info.addMeasure(TaskMetric.EVENT_COVERAGE_QUANTILE); 198 int quantile = Arrays.binarySearch 199 (eventCoverageRatios, info.getMeasureValue(TaskMetric.EVENT_COVERAGE_RATIO)); 200 201 quantile = 1000 * quantile / eventCoverageRatios.length; 202 203 info.setCount(TaskMetric.EVENT_COVERAGE_QUANTILE, null, quantile); 204 } 205 206 //index.dumpToCSV(System.out); 207 /*try { 208 OutputStream stream = new FileOutputStream(new File("tasks.csv")); 209 index.dumpToCSV(new PrintStream(stream)); 210 stream.close(); 211 } 212 catch (FileNotFoundException e) { 213 e.printStackTrace(); 214 }*/ 215 } 216 217 } 218 219 /** 220 * <p> 221 * the index of task infos used internally. The index is created once and while that filled 222 * with task infos for each observed task containing all measures for metrics belonging 223 * to the tasks. 224 * </p> 225 * 226 * @author Patrick Harms 227 */ 228 private static class TaskModelIndex { 229 230 /** 231 * <p> 232 * the tasks contained in the user session belonging to the model as well as statistical 233 * infos about them 234 * </p> 235 */ 236 private Map<ITask, TaskInfo> taskMap = new HashMap<ITask, TaskInfo>(); 237 238 /** 239 * <p> 240 * called on initialization to fill the index with infos about the given task instance 241 * as well as to calculate the appropriate metrics 242 * </p> 243 */ 244 private int[] handleTaskInstance(ITaskInstance taskInstance, ITask context) { 245 int eventTaskInstancesCovered = 0; 246 int depth = 0; 247 248 if (taskInstance instanceof ITaskInstanceList) { 249 for (ITaskInstance child : (ITaskInstanceList) taskInstance) { 250 int[] measures = handleTaskInstance(child, taskInstance.getTask()); 251 eventTaskInstancesCovered += measures[0]; 252 depth = Math.max(depth, measures[1]); 253 } 254 255 if ((((ITaskInstanceList) taskInstance).size() == 0) && 256 (taskInstance instanceof IIterationInstance)) 257 { 258 // ensure also empty task infos for unselected variants 259 ensureTaskInfo(((IIteration) taskInstance.getTask()).getMarkedTask(), context); 260 } 261 } 262 else if (taskInstance instanceof ISelectionInstance) { 263 ITaskInstance child = ((ISelectionInstance) taskInstance).getChild(); 264 int[] measures = handleTaskInstance(child, taskInstance.getTask()); 265 eventTaskInstancesCovered += measures[0]; 266 depth = Math.max(depth, measures[1]); 267 268 // ensure also empty task infos for unselected variants 269 for (ITask otherChildTask : ((ISelection) taskInstance.getTask()).getChildren()) { 270 ensureTaskInfo(otherChildTask, context); 271 } 272 } 273 else if (taskInstance instanceof IOptionalInstance) { 274 ITaskInstance child = ((IOptionalInstance) taskInstance).getChild(); 275 if (child != null) { 276 int[] measures = handleTaskInstance(child, taskInstance.getTask()); 277 eventTaskInstancesCovered += measures[0]; 278 depth = Math.max(depth, measures[1]); 279 } 280 else { 281 // ensure also empty task infos for unselected variants 282 ensureTaskInfo(((IOptional) taskInstance.getTask()).getMarkedTask(), context); 283 } 284 } 285 else if (taskInstance instanceof IEventTaskInstance) { 286 eventTaskInstancesCovered = 1; 287 } 288 289 depth++; 290 291 ensureTaskInfo(taskInstance.getTask(), context, eventTaskInstancesCovered, depth); 292 293 return new int[] { eventTaskInstancesCovered, depth }; 294 } 295 296 /** 297 * <p> 298 * internal convenience method to build the task model during initialization 299 * </p> 300 */ 301 private void ensureTaskInfo(ITask task, ITask context) { 302 ensureTaskInfo(task, context, 0, 0); 303 304 if (task instanceof IStructuringTemporalRelationship) { 305 for (ITask child : ((IStructuringTemporalRelationship) task).getChildren()) { 306 ensureTaskInfo(child, task); 307 } 308 } 309 else if (task instanceof IMarkingTemporalRelationship) { 310 ensureTaskInfo(((IMarkingTemporalRelationship) task).getMarkedTask(), task); 311 } 312 313 } 314 315 /** 316 * <p> 317 * internal convenience method to build the task model during initialization. Adds a new 318 * task info object to the map for the provided task and fills it with measures. If there 319 * are already some task infos for the task, the contained measures are updated according 320 * to the parameters. 321 * </p> 322 */ 323 private void ensureTaskInfo(ITask task, 324 ITask context, 325 int eventTaskInstancesCovered, 326 int depth) 327 { 328 TaskInfo taskInfo = taskMap.get(task); 329 330 if (taskInfo == null) { 331 taskInfo = new TaskInfo(task); 332 taskInfo.addMeasure(TaskMetric.COUNT); 333 taskInfo.addMeasure(TaskMetric.EVENT_COVERAGE); 334 taskInfo.addMeasure(TaskMetric.DEPTH); 335 taskMap.put(task, taskInfo); 336 337 taskInfo.setCount(TaskMetric.DEPTH, null, getDepth(task)); 338 } 339 340 taskInfo.increaseCount(TaskMetric.COUNT, context, 1); 341 taskInfo.increaseCount(TaskMetric.EVENT_COVERAGE, context, eventTaskInstancesCovered); 342 343 taskInfo.setCount(TaskMetric.DEPTH, context, depth); 344 } 345 346 /** 347 * <p> 348 * internal convenience method to calculate the maximum depth of a task 349 * </p> 350 */ 351 private int getDepth(ITask task) { 352 if (task instanceof IMarkingTemporalRelationship) { 353 return getDepth(((IMarkingTemporalRelationship) task).getMarkedTask()) + 1; 354 } 355 else if (task instanceof IStructuringTemporalRelationship) { 356 int maxDepth = 0; 357 358 for (ITask child : ((IStructuringTemporalRelationship) task).getChildren()) { 359 maxDepth = Math.max(maxDepth, getDepth(child)); 360 } 361 362 return maxDepth + 1; 363 } 364 else { 365 // event tasks 366 return 1; 367 } 368 } 369 370 /** 371 * 372 */ 373 /*private void dumpToCSV(PrintStream out) { 374 out.println("taskid;depth;count;eventcoverage;eventcoverageratio"); 375 376 for (Map.Entry<ITask, TaskInfo> entry : taskMap.entrySet()) { 377 out.print(entry.getKey().getId()); 378 out.print(';'); 379 out.print(entry.getValue().getMeasureValue(TaskMetric.DEPTH)); 380 out.print(';'); 381 out.print(entry.getValue().getMeasureValue(TaskMetric.COUNT)); 382 out.print(';'); 383 out.print(entry.getValue().getMeasureValue(TaskMetric.EVENT_COVERAGE)); 384 out.print(';'); 385 out.print(entry.getValue().getMeasureValue(TaskMetric.EVENT_COVERAGE_RATIO)); 386 out.println(); 387 } 388 }*/ 389 390 } 391 53 54 /** 55 * <p> 56 * the index of task infos used internally. The index is created once and 57 * while that filled with task infos for each observed task containing all 58 * measures for metrics belonging to the tasks. 59 * </p> 60 * 61 * @author Patrick Harms 62 */ 63 private static class TaskModelIndex { 64 65 /** 66 * <p> 67 * the tasks contained in the user session belonging to the model as 68 * well as statistical infos about them 69 * </p> 70 */ 71 private final Map<ITask, TaskInfo> taskMap = new HashMap<ITask, TaskInfo>(); 72 73 /** 74 * <p> 75 * internal convenience method to build the task model during 76 * initialization 77 * </p> 78 */ 79 private void ensureTaskInfo(ITask task, ITask context) { 80 ensureTaskInfo(task, context, 0, 0); 81 82 if (task instanceof IStructuringTemporalRelationship) { 83 for (final ITask child : ((IStructuringTemporalRelationship) task) 84 .getChildren()) { 85 ensureTaskInfo(child, task); 86 } 87 } else if (task instanceof IMarkingTemporalRelationship) { 88 ensureTaskInfo( 89 ((IMarkingTemporalRelationship) task).getMarkedTask(), 90 task); 91 } 92 93 } 94 95 /** 96 * <p> 97 * internal convenience method to build the task model during 98 * initialization. Adds a new task info object to the map for the 99 * provided task and fills it with measures. If there are already some 100 * task infos for the task, the contained measures are updated according 101 * to the parameters. 102 * </p> 103 */ 104 private void ensureTaskInfo(ITask task, ITask context, 105 int eventTaskInstancesCovered, int depth) { 106 TaskInfo taskInfo = taskMap.get(task); 107 108 if (taskInfo == null) { 109 taskInfo = new TaskInfo(task); 110 taskInfo.addMeasure(TaskMetric.COUNT); 111 taskInfo.addMeasure(TaskMetric.EVENT_COVERAGE); 112 taskInfo.addMeasure(TaskMetric.DEPTH); 113 taskMap.put(task, taskInfo); 114 115 taskInfo.setCount(TaskMetric.DEPTH, null, getDepth(task)); 116 } 117 118 taskInfo.increaseCount(TaskMetric.COUNT, context, 1); 119 taskInfo.increaseCount(TaskMetric.EVENT_COVERAGE, context, 120 eventTaskInstancesCovered); 121 122 taskInfo.setCount(TaskMetric.DEPTH, context, depth); 123 } 124 125 /** 126 * <p> 127 * internal convenience method to calculate the maximum depth of a task 128 * </p> 129 */ 130 private int getDepth(ITask task) { 131 if (task instanceof IMarkingTemporalRelationship) { 132 return getDepth(((IMarkingTemporalRelationship) task) 133 .getMarkedTask()) + 1; 134 } else if (task instanceof IStructuringTemporalRelationship) { 135 int maxDepth = 0; 136 137 for (final ITask child : ((IStructuringTemporalRelationship) task) 138 .getChildren()) { 139 maxDepth = Math.max(maxDepth, getDepth(child)); 140 } 141 142 return maxDepth + 1; 143 } else { 144 // event tasks 145 return 1; 146 } 147 } 148 149 /** 150 * <p> 151 * called on initialization to fill the index with infos about the given 152 * task instance as well as to calculate the appropriate metrics 153 * </p> 154 */ 155 private int[] handleTaskInstance(ITaskInstance taskInstance, 156 ITask context) { 157 int eventTaskInstancesCovered = 0; 158 int depth = 0; 159 160 if (taskInstance instanceof ITaskInstanceList) { 161 for (final ITaskInstance child : (ITaskInstanceList) taskInstance) { 162 final int[] measures = handleTaskInstance(child, 163 taskInstance.getTask()); 164 eventTaskInstancesCovered += measures[0]; 165 depth = Math.max(depth, measures[1]); 166 } 167 168 if ((((ITaskInstanceList) taskInstance).size() == 0) 169 && (taskInstance instanceof IIterationInstance)) { 170 // ensure also empty task infos for unselected variants 171 ensureTaskInfo( 172 ((IIteration) taskInstance.getTask()) 173 .getMarkedTask(), 174 context); 175 } 176 } else if (taskInstance instanceof ISelectionInstance) { 177 final ITaskInstance child = ((ISelectionInstance) taskInstance) 178 .getChild(); 179 final int[] measures = handleTaskInstance(child, 180 taskInstance.getTask()); 181 eventTaskInstancesCovered += measures[0]; 182 depth = Math.max(depth, measures[1]); 183 184 // ensure also empty task infos for unselected variants 185 for (final ITask otherChildTask : ((ISelection) taskInstance 186 .getTask()).getChildren()) { 187 ensureTaskInfo(otherChildTask, context); 188 } 189 } else if (taskInstance instanceof IOptionalInstance) { 190 final ITaskInstance child = ((IOptionalInstance) taskInstance) 191 .getChild(); 192 if (child != null) { 193 final int[] measures = handleTaskInstance(child, 194 taskInstance.getTask()); 195 eventTaskInstancesCovered += measures[0]; 196 depth = Math.max(depth, measures[1]); 197 } else { 198 // ensure also empty task infos for unselected variants 199 ensureTaskInfo( 200 ((IOptional) taskInstance.getTask()) 201 .getMarkedTask(), 202 context); 203 } 204 } else if (taskInstance instanceof IEventTaskInstance) { 205 eventTaskInstancesCovered = 1; 206 } 207 208 depth++; 209 210 ensureTaskInfo(taskInstance.getTask(), context, 211 eventTaskInstancesCovered, depth); 212 213 return new int[] { eventTaskInstancesCovered, depth }; 214 } 215 216 /** 217 * 218 */ 219 /* 220 * private void dumpToCSV(PrintStream out) { 221 * out.println("taskid;depth;count;eventcoverage;eventcoverageratio"); 222 * 223 * for (Map.Entry<ITask, TaskInfo> entry : taskMap.entrySet()) { 224 * out.print(entry.getKey().getId()); out.print(';'); 225 * out.print(entry.getValue().getMeasureValue(TaskMetric.DEPTH)); 226 * out.print(';'); 227 * out.print(entry.getValue().getMeasureValue(TaskMetric.COUNT)); 228 * out.print(';'); 229 * out.print(entry.getValue().getMeasureValue(TaskMetric. 230 * EVENT_COVERAGE)); out.print(';'); 231 * out.print(entry.getValue().getMeasureValue 232 * (TaskMetric.EVENT_COVERAGE_RATIO)); out.println(); } } 233 */ 234 235 } 236 237 /** 238 * <p> 239 * default serial version UID 240 * </p> 241 */ 242 private static final long serialVersionUID = 1L; 243 244 /** 245 * <p> 246 * all metrics calculated by this type of task model 247 * </p> 248 */ 249 private static final TaskMetric[] taskMetrics = new TaskMetric[] { 250 TaskMetric.COUNT, TaskMetric.DEPTH, TaskMetric.EVENT_COVERAGE, 251 TaskMetric.EVENT_COVERAGE_RATIO, TaskMetric.EVENT_COVERAGE_QUANTILE }; 252 253 /** 254 * <p> 255 * the user sessions belonging to the model 256 * </p> 257 */ 258 private final List<IUserSession> userSessions; 259 260 /** 261 * <p> 262 * index for effectively accessing the model and calculating statistics 263 * about it 264 * </p> 265 */ 266 private transient TaskModelIndex index = null; 267 268 /** 269 * <p> 270 * initializes the task model with the user sessions out of which the tasks 271 * are extracted 272 * </p> 273 * 274 * @param userSessions 275 * as described 276 */ 277 TaskModel(List<IUserSession> userSessions) { 278 if ((userSessions == null) || (userSessions.size() == 0)) { 279 throw new IllegalArgumentException("user sessions must not be null"); 280 } 281 282 this.userSessions = userSessions; 283 } 284 285 /* 286 * (non-Javadoc) 287 * 288 * @see java.lang.Object#clone() 289 */ 290 @Override 291 public TaskModel clone() { 292 return new TaskModel(userSessions); 293 } 294 295 /** 296 * <p> 297 * internal convenience method that initializes the internal index and 298 * calculates all measures for metrics available for the tasks 299 * </p> 300 */ 301 private synchronized void ensureInitialized() { 302 if (index == null) { 303 index = new TaskModelIndex(); 304 305 for (final IUserSession session : this.userSessions) { 306 for (final ITaskInstance taskInstance : session) { 307 index.handleTaskInstance(taskInstance, null); 308 } 309 } 310 311 // count all events covered 312 int allEventsCovered = 0; 313 final Collection<ITask> tasks = getTasks(); 314 for (final ITask task : tasks) { 315 if (task instanceof IEventTask) { 316 allEventsCovered += task.getInstances().size(); 317 } 318 } 319 320 final int[] eventCoverageRatios = new int[tasks.size()]; 321 int i = 0; 322 323 // add some further measures 324 for (final ITask task : tasks) { 325 final TaskInfo info = index.taskMap.get(task); 326 info.addMeasure(TaskMetric.EVENT_COVERAGE_RATIO); 327 328 final int coveredEvents = info 329 .getMeasureValue(TaskMetric.EVENT_COVERAGE); 330 int coverageRatio = 0; 331 332 if (allEventsCovered > 0) { 333 coverageRatio = (coveredEvents * 1000) / allEventsCovered; 334 } 335 336 eventCoverageRatios[i++] = coverageRatio; 337 info.setCount(TaskMetric.EVENT_COVERAGE_RATIO, null, 338 coverageRatio); 339 } 340 341 Arrays.sort(eventCoverageRatios); 342 343 // add some further measures 344 for (final ITask task : tasks) { 345 final TaskInfo info = index.taskMap.get(task); 346 info.addMeasure(TaskMetric.EVENT_COVERAGE_QUANTILE); 347 int quantile = Arrays.binarySearch(eventCoverageRatios, 348 info.getMeasureValue(TaskMetric.EVENT_COVERAGE_RATIO)); 349 350 quantile = (1000 * quantile) / eventCoverageRatios.length; 351 352 info.setCount(TaskMetric.EVENT_COVERAGE_QUANTILE, null, 353 quantile); 354 } 355 356 // index.dumpToCSV(System.out); 357 /* 358 * try { OutputStream stream = new FileOutputStream(new 359 * File("tasks.csv")); index.dumpToCSV(new PrintStream(stream)); 360 * stream.close(); } catch (FileNotFoundException e) { 361 * e.printStackTrace(); } 362 */ 363 } 364 365 } 366 367 /* 368 * (non-Javadoc) 369 * 370 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel#getAllMetrics() 371 */ 372 @Override 373 public TaskMetric[] getAllMetrics() { 374 return taskMetrics; 375 } 376 377 /* 378 * (non-Javadoc) 379 * 380 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel#getTaskInfo(ITask) 381 */ 382 @Override 383 public ITaskInfo getTaskInfo(ITask task) { 384 ensureInitialized(); 385 return index.taskMap.get(task); 386 } 387 388 /* 389 * (non-Javadoc) 390 * 391 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel#getTasks() 392 */ 393 @Override 394 public Collection<ITask> getTasks() { 395 ensureInitialized(); 396 return Collections.unmodifiableCollection(index.taskMap.keySet()); 397 } 398 399 /* 400 * (non-Javadoc) 401 * 402 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel#getUserSessions() 403 */ 404 @Override 405 public List<IUserSession> getUserSessions() { 406 ensureInitialized(); 407 return Collections.unmodifiableList(userSessions); 408 } 392 409 393 410 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/UserSession.java
r1407 r1733 33 33 */ 34 34 class UserSession implements IUserSession { 35 36 /**37 * <p>38 * default serial version UID39 * </p>40 */41 private static final long serialVersionUID = 1L;42 43 /**44 * <p>45 * the task instances belonging to the user session46 * </p>47 */48 private List<ITaskInstance> executedTasks = new ArrayList<ITaskInstance>();49 35 50 /* (non-Javadoc) 51 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList#get(int) 52 */ 53 @Override 54 public ITaskInstance get(int index) { 55 return executedTasks.get(index); 56 } 36 /** 37 * <p> 38 * default serial version UID 39 * </p> 40 */ 41 private static final long serialVersionUID = 1L; 57 42 58 /* (non-Javadoc) 59 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList#size() 60 */ 61 @Override 62 public int size() { 63 return executedTasks.size(); 64 } 43 /** 44 * <p> 45 * the task instances belonging to the user session 46 * </p> 47 */ 48 private List<ITaskInstance> executedTasks = new ArrayList<ITaskInstance>(); 65 49 66 /* (non-Javadoc) 67 * @see java.lang.Iterable#iterator() 68 */ 69 @Override 70 public Iterator<ITaskInstance> iterator() { 71 return executedTasks.iterator(); 72 } 50 /** 51 * <p> 52 * used internally to add a task instance to the user session at a specific 53 * position 54 * </p> 55 * 56 * @param index 57 * the index the task instance shall be added to 58 * @param taskInstance 59 * the task instance to be added 60 */ 61 void addExecutedTask(int index, ITaskInstance taskInstance) { 62 executedTasks.add(index, taskInstance); 63 } 73 64 74 /* (non-Javadoc) 75 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession#getExecutedTasks() 76 */ 77 @Override 78 public List<ITaskInstance> getExecutedTasks() { 79 return Collections.unmodifiableList(executedTasks); 80 } 65 /** 66 * <p> 67 * used internally to add a task instance to the user session 68 * </p> 69 * 70 * @param taskInstance 71 * the task instance to be added 72 */ 73 void addExecutedTask(ITaskInstance taskInstance) { 74 executedTasks.add(taskInstance); 75 } 81 76 82 /* (non-Javadoc) 83 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession#equals(IUserSession) 84 */ 85 @Override 86 public boolean equals(IUserSession userSession) { 87 // task instances are only equal if they are identical or if they have the same id 88 // (may happen, if they are cloned) 89 return (this == userSession) || (this.hashCode() == userSession.hashCode()); 90 } 77 /* 78 * (non-Javadoc) 79 * 80 * @see java.lang.Object#clone() 81 */ 82 @Override 83 public synchronized IUserSession clone() { 84 UserSession clone = null; 85 try { 86 clone = (UserSession) super.clone(); 91 87 92 /* (non-Javadoc) 93 * @see java.lang.Object#hashCode() 94 */ 95 @Override 96 public synchronized int hashCode() { 97 return super.hashCode(); 98 } 88 clone.executedTasks = new LinkedList<ITaskInstance>(); 99 89 100 /* (non-Javadoc) 101 * @see java.lang.Object#toString() 102 */ 103 @Override 104 public synchronized String toString() { 105 return "session (" + executedTasks.size() + " task instances)"; 106 } 90 for (final ITaskInstance child : executedTasks) { 91 clone.executedTasks.add(child.clone()); 92 } 107 93 108 /* (non-Javadoc) 109 * @see java.lang.Object#clone() 110 */ 111 @Override 112 public synchronized IUserSession clone() { 113 UserSession clone = null; 114 try { 115 clone = (UserSession) super.clone(); 94 } catch (final CloneNotSupportedException e) { 95 // this should never happen. Therefore simply dump the exception 96 e.printStackTrace(); 97 } 116 98 117 clone.executedTasks = new LinkedList<ITaskInstance>(); 118 119 for (ITaskInstance child : executedTasks) { 120 clone.executedTasks.add(child.clone()); 121 } 99 return clone; 100 } 122 101 123 } 124 catch (CloneNotSupportedException e) { 125 // this should never happen. Therefore simply dump the exception 126 e.printStackTrace(); 127 } 102 /* 103 * (non-Javadoc) 104 * 105 * @see 106 * de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession#equals(IUserSession) 107 */ 108 @Override 109 public boolean equals(IUserSession userSession) { 110 // task instances are only equal if they are identical or if they have 111 // the same id 112 // (may happen, if they are cloned) 113 return (this == userSession) 114 || (this.hashCode() == userSession.hashCode()); 115 } 128 116 129 return clone; 130 } 117 /* 118 * (non-Javadoc) 119 * 120 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList#get(int) 121 */ 122 @Override 123 public ITaskInstance get(int index) { 124 return executedTasks.get(index); 125 } 131 126 132 /**133 * <p> 134 * used internally to add a task instance to the user session 135 * </p> 136 * 137 * @param taskInstance the task instance to be added 138 */ 139 void addExecutedTask(ITaskInstance taskInstance) {140 executedTasks.add(taskInstance);141 127 /* 128 * (non-Javadoc) 129 * 130 * @see 131 * de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession#getExecutedTasks() 132 */ 133 @Override 134 public List<ITaskInstance> getExecutedTasks() { 135 return Collections.unmodifiableList(executedTasks); 136 } 142 137 143 /** 144 * <p> 145 * used internally to add a task instance to the user session at a specific position 146 * </p> 147 * 148 * @param index the index the task instance shall be added to 149 * @param taskInstance the task instance to be added 150 */ 151 void addExecutedTask(int index, ITaskInstance taskInstance) { 152 executedTasks.add(index, taskInstance); 153 } 138 /* 139 * (non-Javadoc) 140 * 141 * @see java.lang.Object#hashCode() 142 */ 143 @Override 144 public synchronized int hashCode() { 145 return super.hashCode(); 146 } 154 147 155 /** 156 * <p> 157 * used internally to remove a task instance from the user session 158 * </p> 159 * 160 * @param index the index of the task instance to be removed 161 */ 162 void removeExecutedTask(int index) { 163 executedTasks.remove(index); 164 } 148 /* 149 * (non-Javadoc) 150 * 151 * @see java.lang.Iterable#iterator() 152 */ 153 @Override 154 public Iterator<ITaskInstance> iterator() { 155 return executedTasks.iterator(); 156 } 157 158 /** 159 * <p> 160 * used internally to remove a task instance from the user session 161 * </p> 162 * 163 * @param index 164 * the index of the task instance to be removed 165 */ 166 void removeExecutedTask(int index) { 167 executedTasks.remove(index); 168 } 169 170 /* 171 * (non-Javadoc) 172 * 173 * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList#size() 174 */ 175 @Override 176 public int size() { 177 return executedTasks.size(); 178 } 179 180 /* 181 * (non-Javadoc) 182 * 183 * @see java.lang.Object#toString() 184 */ 185 @Override 186 public synchronized String toString() { 187 return "session (" + executedTasks.size() + " task instances)"; 188 } 165 189 166 190 }
Note: See TracChangeset
for help on using the changeset viewer.