Changeset 1146 for trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation
- Timestamp:
- 04/04/13 16:06:07 (11 years ago)
- Location:
- trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation
- Files:
-
- 2 added
- 8 deleted
- 5 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/ITaskInstanceListScopeRule.java
r1113 r1146 15 15 package de.ugoe.cs.autoquest.tasktrees.temporalrelation; 16 16 17 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask TreeNode;17 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList; 18 18 19 19 /** 20 20 * <p> 21 * a temporal relationship rule is able to detected temporal relationships between the child nodes 22 * of the parent node provided to the {@link #apply(ITaskTreeNode, boolean)} method. A rule 23 * creates temporal relationships between the child nodes, i.e. substructures in the task tree, if 24 * it detects a temporal relationship and it can be sure that it is complete. Incomplete but 25 * detected temporal relationships may occur, if there can be more children expected to be added 26 * to the provided parent node. This could be the case during parsing a interaction log file of 27 * a GUI. 21 * a task instance list scope rule is able to detected temporal relationships between a list of task 22 * instances provided to the {@link #apply(ITaskInstanceList)} 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. 28 25 * </p> 29 26 * 30 27 * @author Patrick Harms 31 28 */ 32 interface TemporalRelationshipRule {29 interface ITaskInstanceListScopeRule extends ITemporalRelationshipRule { 33 30 34 31 /** 35 32 * <p> 36 * applies the rule to the given parent node. The finalize parameter is used to command the rule 37 * to finish rule applications, in the case it is known that no further data will be available. 38 * </p> 39 * <p> 40 * The returned rule application result is null, if the rule can not be applied, i.e. it does not 41 * detect a temporal relationship. It returns a rule application result with a status 42 * {@link RuleApplicationStatus#RULE_APPLICATION_FINISHED} if the rule was applied. The result 43 * contains all newly created parent nodes. It returns a rule application result with status 44 * {@link RuleApplicationStatus#RULE_APPLICATION_FEASIBLE} if the rule would be applicable if 45 * further children would be available in the parent node. This status MUST not be returned if 46 * the finalize parameter is true. In this case the rule must be applied or not. 33 * applies the rule to the given task instance list. 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. 47 37 * </p> 48 38 * 49 * @param parent the parent node with the children to apply the rule on 50 * @param finalize true, if the rule shall not expect further children to come and that it 51 * should therefore be applied in any case 39 * @param taskInstances the list of task instances to apply the rule on 52 40 * 53 41 * @return the rule application result as described. 54 42 */ 55 RuleApplicationResult apply(ITaskTreeNode parent, 56 boolean finalize); 43 RuleApplicationResult apply(ITaskInstanceList taskInstances); 57 44 58 45 } -
trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/RuleApplicationResult.java
r1127 r1146 18 18 import java.util.List; 19 19 20 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNode; 20 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask; 21 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance; 21 22 22 23 /** 23 24 * <p> 24 * The rule application result describes the result of applying a {@link TemporalRelationshipRule}25 * on a task tree node. It contains a {@link RuleApplicationStatus} and a list of all parent26 * t ask tree nodes that were created during a rule application. See the description of27 * {@link TemporalRelationshipRule} for more details.25 * The rule application result describes the result of applying a {@link ITemporalRelationshipRule}. 26 * It contains a {@link RuleApplicationStatus} and a list of all parent task instances and tasks 27 * that were created during a rule application. See the description of 28 * {@link ITemporalRelationshipRule} for more details. 28 29 * </p> 29 30 * … … 36 37 37 38 /** */ 38 private List<ITaskTreeNode> newParents = new ArrayList<ITaskTreeNode>(); 39 private List<ITask> newParentTasks = new ArrayList<ITask>(); 40 41 /** */ 42 private List<ITaskInstance> newParentInstances = new ArrayList<ITaskInstance>(); 39 43 40 44 /** … … 67 71 /** 68 72 * <p> 69 * add a further parent nodecreated during the rule application73 * add a further parent task created during the rule application 70 74 * </p> 71 75 */ 72 void addNewlyCreated ParentNode(ITaskTreeNodenewParent) {73 newParent s.add(newParent);76 void addNewlyCreatedTask(ITask newParent) { 77 newParentTasks.add(newParent); 74 78 } 75 79 76 80 /** 77 81 * <p> 78 * return all parent nodes created during the rule application82 * return all parent tasks created during the rule application 79 83 * </p> 80 84 */ 81 List<ITaskTreeNode> getNewlyCreatedParentNodes() { 82 return newParents; 85 List<ITask> getNewlyCreatedTasks() { 86 return newParentTasks; 87 } 88 89 /** 90 * <p> 91 * add a further parent task instance created during the rule application 92 * </p> 93 */ 94 void addNewlyCreatedTaskInstance(ITaskInstance newParent) { 95 newParentInstances.add(newParent); 96 } 97 98 /** 99 * <p> 100 * return all parent task instances created during the rule application 101 * </p> 102 */ 103 List<ITaskInstance> getNewlyCreatedTaskInstances() { 104 return newParentInstances; 83 105 } 84 106 -
trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/RuleApplicationStatus.java
r1127 r1146 17 17 /** 18 18 * <p> 19 * The rule application status describes the result of applying a {@link TemporalRelationshipRule}20 * on a task tree node. See the description of {@linkTemporalRelationshipRule} for more details.19 * The rule application status describes the result of applying a {@link ITemporalRelationshipRule}. 20 * See the description of {@link ITemporalRelationshipRule} for more details. 21 21 * </p> 22 22 * … … 25 25 enum RuleApplicationStatus { 26 26 FINISHED, 27 // TODO drop feasible 27 28 FEASIBLE, 28 29 NOT_APPLIED; -
trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/RuleUtils.java
r1127 r1146 15 15 package de.ugoe.cs.autoquest.tasktrees.temporalrelation; 16 16 17 import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence; 18 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeBuilder; 19 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNode; 20 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNodeFactory; 17 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask; 18 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskBuilder; 19 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance; 20 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList; 21 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskFactory; 21 22 22 23 /** … … 35 36 * 36 37 */ 37 static I Sequence getSubSequenceInRange(ITaskTreeNodeparent,38 intstartIndex,39 intendIndex,40 String description,41 ITaskTreeNodeFactory nodeFactory,42 ITaskTreeBuilder builder)38 static ITaskInstance getSubSequenceInRange(ITaskInstanceList parent, 39 int startIndex, 40 int endIndex, 41 ITask model, 42 ITaskFactory taskFactory, 43 ITaskBuilder taskBuilder) 43 44 { 44 ISequence sequence = nodeFactory.createNewSequence(); 45 if (description != null) { 46 builder.setDescription(sequence, description); 45 ITaskInstance subsequence = taskFactory.createNewTaskInstance(model); 46 47 for (int i = startIndex; i <= endIndex; i++) { 48 taskBuilder.addChild(subsequence, parent.get(i)); 47 49 } 48 50 49 for (int i = startIndex; i <= endIndex; i++) { 50 builder.addChild(sequence, parent.getChildren().get(i)); 51 } 52 53 return sequence; 51 return subsequence; 54 52 } 55 53 … … 57 55 * 58 56 */ 59 static I Sequence createNewSubSequenceInRange(ITaskTreeNodeparent,60 intstartIndex,61 intendIndex,62 String description,63 ITaskTreeNodeFactory nodeFactory,64 ITaskTreeBuilder builder)57 static ITaskInstance createNewSubSequenceInRange(ITaskInstanceList parent, 58 int startIndex, 59 int endIndex, 60 ITask model, 61 ITaskFactory taskFactory, 62 ITaskBuilder taskBuilder) 65 63 { 66 ISequence sequence = nodeFactory.createNewSequence(); 67 if (description != null) { 68 builder.setDescription(sequence, description); 64 ITaskInstance subsequence = taskFactory.createNewTaskInstance(model); 65 66 for (int i = startIndex; i <= endIndex; i++) { 67 taskBuilder.addChild(subsequence, parent.get(startIndex)); 68 taskBuilder.removeTaskInstance(parent, startIndex); 69 69 } 70 70 71 for (int i = startIndex; i <= endIndex; i++) {72 builder.addChild(sequence, parent.getChildren().get(startIndex));73 builder.removeChild((ISequence) parent, startIndex);74 }75 71 76 builder.addChild((ISequence) parent, startIndex,sequence);72 taskBuilder.addTaskInstance(parent, startIndex, subsequence); 77 73 78 return s equence;74 return subsequence; 79 75 } 80 76 -
trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/SequenceForTaskDetectionRule.java
r1133 r1146 15 15 package de.ugoe.cs.autoquest.tasktrees.temporalrelation; 16 16 17 import java.util.HashMap; 17 18 import java.util.Iterator; 18 19 import java.util.LinkedList; 19 20 import java.util.List; 20 21 21 import de.ugoe.cs.autoquest.tasktrees.nodeequality.NodeEquality; 22 import de.ugoe.cs.autoquest.tasktrees.nodeequality.NodeEqualityRuleManager; 22 import de.ugoe.cs.autoquest.tasktrees.taskequality.TaskEquality; 23 import de.ugoe.cs.autoquest.tasktrees.taskequality.TaskEqualityRuleManager; 24 import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask; 23 25 import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration; 24 26 import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelection; 25 27 import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence; 26 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeBuilder; 27 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNode; 28 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNodeFactory; 28 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask; 29 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskBuilder; 30 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskFactory; 31 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance; 32 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList; 33 import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession; 34 import de.ugoe.cs.autoquest.usageprofiles.SymbolComparator; 29 35 import de.ugoe.cs.autoquest.usageprofiles.Trie; 30 36 import de.ugoe.cs.autoquest.usageprofiles.TrieProcessor; 31 37 import de.ugoe.cs.util.StopWatch; 32 import de.ugoe.cs.util.console.Console;33 38 34 39 /** … … 39 44 * @author Patrick Harms 40 45 */ 41 class SequenceForTaskDetectionRule implements TemporalRelationshipRule {46 class SequenceForTaskDetectionRule implements ISessionScopeRule { 42 47 43 48 /** 44 49 * <p> 45 * the task tree nodefactory to be used for creating substructures for the temporal50 * the task factory to be used for creating substructures for the temporal 46 51 * relationships identified during rule 47 52 * </p> 48 53 */ 49 private ITask TreeNodeFactory taskTreeNodeFactory;54 private ITaskFactory taskFactory; 50 55 /** 51 56 * <p> 52 * the task treebuilder to be used for creating substructures for the temporal relationships57 * the task builder to be used for creating substructures for the temporal relationships 53 58 * identified during rule application 54 59 * </p> 55 60 */ 56 private ITask TreeBuilder taskTreeBuilder;61 private ITaskBuilder taskBuilder; 57 62 58 63 /** 59 64 * <p> 60 * the node comparator to be used for comparing task tree nodes65 * the task comparator to be used for comparing tasks 61 66 * </p> 62 67 */ 63 private Task TreeNodeComparator nodeComparator;68 private TaskComparator taskComparator; 64 69 65 70 /** 66 71 * <p> 67 * instantiates the rule and initializes it with a nodeequality rule manager and the minimal68 * nodeequality identified sublist must have to consider them as iterated.72 * instantiates the rule and initializes it with a task equality rule manager and the minimal 73 * task equality identified sublist must have to consider them as iterated. 69 74 * </p> 70 75 */ 71 SequenceForTaskDetectionRule( NodeEqualityRuleManager nodeEqualityRuleManager,72 NodeEquality minimalNodeEquality,73 ITask TreeNodeFactory taskTreeNodeFactory,74 ITask TreeBuilder taskTreeBuilder)76 SequenceForTaskDetectionRule(TaskEqualityRuleManager taskEqualityRuleManager, 77 TaskEquality minimalTaskEquality, 78 ITaskFactory taskFactory, 79 ITaskBuilder taskBuilder) 75 80 { 76 this.taskTreeNodeFactory = taskTreeNodeFactory; 77 this.taskTreeBuilder = taskTreeBuilder; 78 79 this.nodeComparator = 80 new TaskTreeNodeComparator(nodeEqualityRuleManager, minimalNodeEquality); 81 this.taskFactory = taskFactory; 82 this.taskBuilder = taskBuilder; 83 84 this.taskComparator = new TaskComparator(taskEqualityRuleManager, minimalTaskEquality); 81 85 } 82 86 … … 89 93 } 90 94 91 /* 92 * (non-Javadoc) 93 * 94 * @see de.ugoe.cs.tasktree.temporalrelation.TemporalRelationshipRule#apply(TaskTreeNode, 95 * boolean) 95 /* (non-Javadoc) 96 * @see de.ugoe.cs.autoquest.tasktrees.temporalrelation.ISessionScopeRule#apply(java.util.List) 96 97 */ 97 98 @Override 98 public RuleApplicationResult apply(ITaskTreeNode parent, boolean finalize) { 99 if (!(parent instanceof ISequence)) { 100 return null; 101 } 102 103 if (!finalize) { 104 // the rule is always feasible as tasks may occur at any time 105 RuleApplicationResult result = new RuleApplicationResult(); 106 result.setRuleApplicationStatus(RuleApplicationStatus.FEASIBLE); 107 return result; 108 } 109 110 List<ITaskTreeNode> children = parent.getChildren(); 111 List<ISequence> sessions = new LinkedList<ISequence>(); 112 113 for (ITaskTreeNode child : children) { 114 if (child instanceof ISequence) { 115 sessions.add((ISequence) child); 116 } 117 else { 118 Console.println("provided parent is no parent of sessions"); 119 return null; 120 } 121 } 122 99 public RuleApplicationResult apply(List<IUserSession> sessions) { 123 100 RuleApplicationData appData = new RuleApplicationData(sessions); 124 101 125 boolean finished = false;126 127 102 // this is the real rule application. Loop while something is replaced. 128 103 do { … … 137 112 appData.getStopWatch().stop("whole loop"); 138 113 139 //((TaskTreeNodeComparator) nodeComparator).getStopWatch().dumpStatistics(System.out);140 //((TaskTreeNodeComparator) nodeComparator).getStopWatch().reset();114 //((TaskTreeNodeComparator) taskComparator).getStopWatch().dumpStatistics(System.out); 115 //((TaskTreeNodeComparator) taskComparator).getStopWatch().reset(); 141 116 142 117 appData.getStopWatch().dumpStatistics(System.out); 143 118 appData.getStopWatch().reset(); 144 119 145 finished = (appData.getReplacementCounter() == 0); 146 } 147 while (!finished); 148 149 System.out.println("created " + appData.getResult().getNewlyCreatedParentNodes().size() + 150 " new parent nodes\n"); 151 152 if (appData.getResult().getNewlyCreatedParentNodes().size() > 0) { 120 } 121 while (appData.detectedAndReplacedTasks()); 122 123 System.out.println 124 ("created " + appData.getResult().getNewlyCreatedTasks().size() + 125 " new tasks and " + appData.getResult().getNewlyCreatedTaskInstances().size() + 126 " appropriate instances\n"); 127 128 if ((appData.getResult().getNewlyCreatedTasks().size() > 0) || 129 (appData.getResult().getNewlyCreatedTaskInstances().size() > 0)) 130 { 153 131 appData.getResult().setRuleApplicationStatus(RuleApplicationStatus.FINISHED); 154 132 } … … 164 142 appData.getStopWatch().start("detecting iterations"); 165 143 166 List<ISequence> sessions = appData.getSessions(); 167 int foundIterations = 0; 168 169 for (ISequence session : sessions) { 170 foundIterations += detectAndReplaceIterations(session, appData); 171 } 144 List<IUserSession> sessions = appData.getSessions(); 145 int iteratedTasks = 0; 146 147 ITask iteratedTask = null; 148 149 do { 150 iteratedTask = searchIteratedTask(sessions); 151 152 if (iteratedTask != null) { 153 replaceIterationsOf(iteratedTask, sessions, appData); 154 iteratedTasks++; 155 } 156 } 157 while (iteratedTask != null); 172 158 173 159 appData.getStopWatch().stop("detecting iterations"); 174 System.out.println(" --> found " + foundIterations); 175 } 176 177 /** 178 * @param appData 179 */ 180 private int detectAndReplaceIterations(ISequence session, 181 RuleApplicationData appData) 160 System.out.println(" --> found " + iteratedTasks + " iterated tasks"); 161 } 162 163 /** 164 * 165 */ 166 private ITask searchIteratedTask(List<IUserSession> sessions) { 167 for (IUserSession session : sessions) { 168 for (int i = 0; i < (session.size() - 1); i++) { 169 if (taskComparator.equals(session.get(i).getTask(), session.get(i + 1).getTask())) { 170 return session.get(i).getTask(); 171 } 172 } 173 } 174 175 return null; 176 } 177 178 /** 179 * 180 */ 181 private void replaceIterationsOf(ITask iteratedTask, 182 List<IUserSession> sessions, 183 RuleApplicationData appData) 182 184 { 183 int count = 0; 184 185 TemporalRelationshipRule rule = new SimpleIterationDetectionRule 186 (nodeComparator, taskTreeNodeFactory, taskTreeBuilder); 187 188 RuleApplicationResult result = rule.apply(session, true); 189 190 if ((result != null) && (result.getNewlyCreatedParentNodes() != null)) { 191 for (ITaskTreeNode newParent : result.getNewlyCreatedParentNodes()) { 192 appData.getResult().addNewlyCreatedParentNode(newParent); 193 if (newParent instanceof IIteration) { 194 count++; 195 } 196 } 197 } 198 199 return count; 185 IIteration iteration = taskFactory.createNewIteration(); 186 ITaskInstance iterationInstance = null; 187 188 List<ITaskInstance> iterationInstances = new LinkedList<ITaskInstance>(); 189 190 for (IUserSession session : sessions) { 191 int index = 0; 192 while (index < session.size()) { 193 if (taskComparator.equals(iteratedTask, session.get(index).getTask())) { 194 if (iterationInstance == null) { 195 iterationInstance = taskFactory.createNewTaskInstance(iteration); 196 iterationInstances.add(iterationInstance); 197 taskBuilder.addTaskInstance(session, index, iterationInstance); 198 index++; 199 } 200 201 taskBuilder.addChild(iterationInstance, session.get(index)); 202 taskBuilder.removeTaskInstance(session, index); 203 } 204 else { 205 if (iterationInstance != null) { 206 iterationInstance = null; 207 } 208 index++; 209 } 210 } 211 } 212 213 harmonizeIterationInstancesModel(iteration, iterationInstances); 214 } 215 216 /** 217 * <p> 218 * TODO: comment 219 * </p> 220 * 221 * @param iteratedTaskVariants 222 */ 223 private void harmonizeIterationInstancesModel(IIteration iteration, 224 List<ITaskInstance> iterationInstances) 225 { 226 List<ITask> iteratedTaskVariants = new LinkedList<ITask>(); 227 228 // merge the lexically different variants of iterated task to a unique list 229 for (ITaskInstance iterationInstance : iterationInstances) { 230 for (ITaskInstance executionVariant : iterationInstance) { 231 ITask candidate = executionVariant.getTask(); 232 233 boolean found = false; 234 for (ITask taskVariant : iteratedTaskVariants) { 235 if (taskComparator.areLexicallyEqual(taskVariant, candidate)) { 236 taskBuilder.setTask(executionVariant, taskVariant); 237 found = true; 238 break; 239 } 240 } 241 242 if (!found) { 243 iteratedTaskVariants.add(candidate); 244 } 245 } 246 } 247 248 // if there are more than one lexically different variant of iterated tasks, adapt the 249 // iteration model to be a selection of different variants. In this case also adapt 250 // the generated iteration instances to correctly contain selection instances. If there 251 // is only one variant of an iterated task, simply set this as the marked task of the 252 // iteration. In this case, the instances can be preserved as is 253 if (iteratedTaskVariants.size() > 1) { 254 ISelection selection = taskFactory.createNewSelection(); 255 256 for (ITask variant : iteratedTaskVariants) { 257 taskBuilder.addChild(selection, variant); 258 } 259 260 taskBuilder.setMarkedTask(iteration, selection); 261 262 for (ITaskInstance instance : iterationInstances) { 263 for (int i = 0; i < instance.size(); i++) { 264 ITaskInstance selectionInstance = taskFactory.createNewTaskInstance(selection); 265 taskBuilder.addChild(selectionInstance, instance.get(i)); 266 taskBuilder.setTaskInstance(instance, i, selectionInstance); 267 } 268 } 269 } 270 else { 271 taskBuilder.setMarkedTask(iteration, iteratedTaskVariants.get(0)); 272 } 200 273 } 201 274 … … 226 299 Tasks tasks; 227 300 boolean createNewTrie = (appData.getLastTrie() == null) || 228 appData. getReplacementCounter() > 0; // tree has changed301 appData.detectedAndReplacedTasks(); // tree has changed 229 302 230 303 do { … … 240 313 createNewTrie = false; 241 314 242 for (List<ITask TreeNode> task : tasks) {315 for (List<ITaskInstance> task : tasks) { 243 316 if (task.size() >= appData.getTrainedSequenceLength()) { 244 317 // Trie must be recreated with a longer sequence length to be sure that … … 267 340 268 341 appData.getStopWatch().start("training trie"); 269 appData.setLastTrie(new Trie<ITask TreeNode>(nodeComparator));342 appData.setLastTrie(new Trie<ITaskInstance>(taskComparator)); 270 343 271 List<I Sequence> sessions = appData.getSessions();272 273 for (I Sequencesession : sessions) {344 List<IUserSession> sessions = appData.getSessions(); 345 346 for (IUserSession session : sessions) { 274 347 trainTrie(session, appData); 275 348 } … … 282 355 * @param parent 283 356 */ 284 private void trainTrie(I Sequencesession, RuleApplicationData appData) {285 List<ITask TreeNode> children = session.getChildren();357 private void trainTrie(IUserSession session, RuleApplicationData appData) { 358 List<ITaskInstance> children = session.getExecutedTasks(); 286 359 287 360 if ((children != null) && (children.size() > 0)) { … … 294 367 */ 295 368 private void replaceSequencesOccurringMostOften(RuleApplicationData appData) { 296 appData. resetReplacementCounter();369 appData.detectedAndReplacedTasks(false); 297 370 298 371 if ((appData.getLastFoundTasks().size() > 0) && 299 372 (appData.getLastFoundTasks().getOccurrenceCount() > 1)) 300 373 { 301 System.out.println("replacing tasks occurrences with merged variants of all versions"); 302 303 for (List<ITaskTreeNode> task : appData.getLastFoundTasks()) { 304 String taskId = "task " + RuleUtils.getNewId(); 305 System.out.println("replacing " + taskId + ": " + task); 306 307 appData.clearTaskOccurrences(); 308 determineVariantsOfTaskOccurrences(task, appData.getSessions(), appData); 309 310 appData.getStopWatch().start("merging task nodes"); 311 ITaskTreeNode taskReplacement = mergeVariantsOfTaskOccurrence(taskId, appData); 312 appData.getStopWatch().stop("merging task nodes"); 313 314 appData.resetReplacementCounter(); 315 replaceTaskOccurrences(task, taskReplacement, appData.getSessions(), appData); 316 317 if (appData.getReplacementCounter() > 0) { 318 appData.getResult().addNewlyCreatedParentNode(taskReplacement); 319 } 320 321 if (appData.getReplacementCounter() < 322 appData.getLastFoundTasks().getOccurrenceCount()) 323 { 324 System.out.println(taskId + ": replaced task only " + 325 appData.getReplacementCounter() + 326 " times instead of expected " + 374 System.out.println("replacing tasks occurrences"); 375 376 for (List<ITaskInstance> task : appData.getLastFoundTasks()) { 377 ISequence sequence = taskFactory.createNewSequence(); 378 379 System.out.println("replacing " + sequence.getId() + ": " + task); 380 381 List<ITaskInstance> sequenceInstances = 382 replaceTaskOccurrences(task, appData.getSessions(), sequence); 383 384 harmonizeSequenceInstancesModel(sequence, sequenceInstances,task.size()); 385 appData.detectedAndReplacedTasks(sequenceInstances.size() > 0); 386 387 if (sequenceInstances.size() < appData.getLastFoundTasks().getOccurrenceCount()) { 388 System.out.println(sequence.getId() + ": replaced task only " + 389 sequenceInstances.size() + " times instead of expected " + 327 390 appData.getLastFoundTasks().getOccurrenceCount()); 328 391 } … … 333 396 334 397 /** 335 * @param tree336 */ 337 private void determineVariantsOfTaskOccurrences(List<ITaskTreeNode> task,338 List<ISequence> sessions,339 RuleApplicationData appData)398 * 399 */ 400 private void harmonizeSequenceInstancesModel(ISequence sequence, 401 List<ITaskInstance> sequenceInstances, 402 int sequenceLength) 340 403 { 341 for (ISequence session : sessions) { 342 int index = -1; 343 344 List<ITaskTreeNode> children = session.getChildren(); 345 346 do { 347 index = getSubListIndex(children, task, ++index); 348 349 if (index > -1) { 350 ISequence taskOccurrence = RuleUtils.getSubSequenceInRange 351 (session, index, index + task.size() - 1, null, 352 taskTreeNodeFactory, taskTreeBuilder); 353 354 appData.addTaskOccurrence(taskOccurrence); 355 356 // let the index point to the last element the belongs the identified occurrence 357 index += task.size() - 1; 358 } 359 } 360 while (index > -1); 361 } 362 } 363 364 /** 365 * @param appData 366 * @return 367 */ 368 private ITaskTreeNode mergeVariantsOfTaskOccurrence(String taskId, 369 RuleApplicationData appData) 370 { 371 return mergeVariantsOfTasks(taskId, appData.getTaskOccurrences()); 372 } 373 374 /** 375 * @param appData 376 * @return 377 */ 378 private ITaskTreeNode mergeVariantsOfTasks(String description, List<ITaskTreeNode> variants) { 379 // merge but preserve lexically distinct variants 380 TaskTreeNodeMerger merger = new TaskTreeNodeMerger 381 (taskTreeNodeFactory, taskTreeBuilder, nodeComparator); 382 383 merger.mergeTaskNodes(variants); 384 385 if (variants.size() == 1) { 386 ITaskTreeNode replacement = variants.get(0); 387 taskTreeBuilder.setDescription(replacement, description); 388 return replacement; 389 } 390 else { 391 ISelection selection = taskTreeNodeFactory.createNewSelection(); 392 taskTreeBuilder.setDescription(selection, "variants of task " + description); 393 394 for (ITaskTreeNode variant : variants) { 395 taskTreeBuilder.addChild(selection, variant); 396 } 397 398 return selection; 399 } 400 } 401 402 /** 403 * @param task 404 * @param parent 405 * @param treeBuilder 406 * @param nodeFactory 407 * @param result 408 */ 409 private void replaceTaskOccurrences(List<ITaskTreeNode> task, 410 ITaskTreeNode replacement, 411 List<ISequence> sessions, 412 RuleApplicationData appData) 413 { 414 // now check the children themselves for an occurrence of the task 415 for (int i = 0; i < sessions.size(); i++) { 416 ISequence session = sessions.get(i); 417 418 int index = -1; 419 420 List<ITaskTreeNode> children = session.getChildren(); 421 422 do { 423 index = getSubListIndex(children, task, ++index); 424 425 if (index > -1) { 426 if ((!(replacement instanceof ISequence)) || 427 (task.size() < children.size())) 428 { 429 for (int j = index; j < index + task.size(); j++) { 430 taskTreeBuilder.removeChild(session, index); 431 } 432 433 taskTreeBuilder.addChild(session, index, replacement); 434 appData.incrementReplacementCounter(); 435 436 children = session.getChildren(); 437 } 438 else { 439 // the whole list of children is an occurrence of this task. So ask the 440 // caller of the method to replace the whole node 441 sessions.set(i, (ISequence) replacement); 442 appData.incrementReplacementCounter(); 404 405 // ensure for each subtask that lexically different variants are preserved 406 for (int subTaskIndex = 0; subTaskIndex < sequenceLength; subTaskIndex++) { 407 List<ITask> subTaskVariants = new LinkedList<ITask>(); 408 409 for (ITaskInstance sequenceInstance : sequenceInstances) { 410 ITask candidate = sequenceInstance.get(subTaskIndex).getTask(); 411 412 boolean found = false; 413 414 for (int i = 0; i < subTaskVariants.size(); i++) { 415 if (taskComparator.areLexicallyEqual(subTaskVariants.get(i), candidate)) { 416 taskBuilder.setTask 417 (sequenceInstance.get(subTaskIndex), subTaskVariants.get(i)); 418 419 found = true; 443 420 break; 444 421 } 445 422 } 423 424 if (!found) { 425 subTaskVariants.add(candidate); 426 } 427 } 428 429 // if there are more than one lexically different variant of the sub task at 430 // the considered position, adapt the sequence model at that position to have 431 // a selection of the different variants. In this case also adapt the 432 // generated sequence instances to correctly contain selection instances. If 433 // there is only one variant of sub tasks at the given position, simply set 434 // this variant as the sub task of the selection. In this case, the instances 435 // can be preserved as is 436 if (subTaskVariants.size() > 1) { 437 ISelection selection = taskFactory.createNewSelection(); 438 439 for (ITask variant : subTaskVariants) { 440 taskBuilder.addChild(selection, variant); 441 } 442 443 taskBuilder.addChild(sequence, selection); 444 445 for (ITaskInstance instance : sequenceInstances) { 446 ITaskInstance selectionInstance = 447 taskFactory.createNewTaskInstance(selection); 448 taskBuilder.addChild(selectionInstance, instance.get(subTaskIndex)); 449 taskBuilder.setTaskInstance(instance, subTaskIndex, selectionInstance); 450 } 451 } 452 else if (subTaskVariants.size() == 1) { 453 taskBuilder.addChild(sequence, subTaskVariants.get(0)); 454 } 455 } 456 } 457 458 /** 459 * @param tree 460 */ 461 private List<ITaskInstance> replaceTaskOccurrences(List<ITaskInstance> task, 462 List<IUserSession> sessions, 463 ISequence temporalTaskModel) 464 { 465 List<ITaskInstance> sequenceInstances = new LinkedList<ITaskInstance>(); 466 467 for (IUserSession session : sessions) { 468 int index = -1; 469 470 do { 471 index = getSubListIndex(session, task, ++index); 472 473 if (index > -1) { 474 sequenceInstances.add 475 (RuleUtils.createNewSubSequenceInRange 476 (session, index, index + task.size() - 1, temporalTaskModel, 477 taskFactory, taskBuilder)); 478 } 446 479 } 447 480 while (index > -1); 448 481 } 482 483 return sequenceInstances; 449 484 } 450 485 … … 454 489 * @return 455 490 */ 456 private int getSubListIndex( List<ITaskTreeNode>list,457 List<ITask TreeNode> subList,491 private int getSubListIndex(ITaskInstanceList list, 492 List<ITaskInstance> subList, 458 493 int startIndex) 459 494 { … … 465 500 466 501 for (int j = 0; j < subList.size(); j++) { 467 if (! nodeComparator.equals(list.get(i + j), subList.get(j))) {502 if (!taskComparator.equals(list.get(i + j), subList.get(j))) { 468 503 matchFound = false; 469 504 break; … … 479 514 return result; 480 515 } 516 517 /** 518 * @param trie 519 * @param object 520 * @return 521 */ 522 private int getSubListIndex(List<ITaskInstance> list, 523 List<ITaskInstance> subList, 524 int startIndex) 525 { 526 boolean matchFound; 527 int result = -1; 528 529 for (int i = startIndex; i <= list.size() - subList.size(); i++) { 530 matchFound = true; 531 532 for (int j = 0; j < subList.size(); j++) { 533 if (!taskComparator.equals(list.get(i + j), subList.get(j))) { 534 matchFound = false; 535 break; 536 } 537 } 538 539 if (matchFound) { 540 result = i; 541 break; 542 } 543 } 544 545 return result; 546 } 481 547 482 548 /** 483 549 * @author Patrick Harms 484 550 */ 485 private class MaxCountAndLongestTasksFinder implements TrieProcessor<ITask TreeNode> {551 private class MaxCountAndLongestTasksFinder implements TrieProcessor<ITaskInstance> { 486 552 487 553 /** … … 493 559 * 494 560 */ 495 private List<List<ITask TreeNode>> foundTasks = new LinkedList<List<ITaskTreeNode>>();561 private List<List<ITaskInstance>> foundTasks = new LinkedList<List<ITaskInstance>>(); 496 562 497 563 /** … … 507 573 */ 508 574 @Override 509 public TrieProcessor.Result process(List<ITask TreeNode> task, int count) {510 if ( task.size() < 2) {511 // ignore single nodes575 public TrieProcessor.Result process(List<ITaskInstance> foundTask, int count) { 576 if (foundTask.size() < 2) { 577 // ignore single tasks 512 578 return TrieProcessor.Result.CONTINUE; 513 579 } … … 519 585 520 586 if (this.currentCount > count) { 521 // ignore this children of this node, as they may have only smaller counts than587 // ignore this children of this task, as they may have only smaller counts than 522 588 // the already found tasks 523 589 return TrieProcessor.Result.SKIP_NODE; … … 536 602 boolean added = false; 537 603 for (int i = 0; i < foundTasks.size(); i++) { 538 if (foundTasks.get(i).size() < task.size()) {604 if (foundTasks.get(i).size() < foundTask.size()) { 539 605 // defensive copy 540 foundTasks.add(i, new LinkedList<ITask TreeNode>(task)); // defensive copy606 foundTasks.add(i, new LinkedList<ITaskInstance>(foundTask)); // defensive copy 541 607 added = true; 542 608 break; … … 545 611 546 612 if (!added) { 547 foundTasks.add(new LinkedList<ITask TreeNode>(task)); // defensive copy613 foundTasks.add(new LinkedList<ITaskInstance>(foundTask)); // defensive copy 548 614 } 549 615 } … … 571 637 // found a task that is a potential subtask. Check for this and remove the 572 638 // subtask if needed 573 List<ITask TreeNode> longTask = foundTasks.get(i);574 List<ITask TreeNode> shortTask = foundTasks.get(j);639 List<ITaskInstance> longTask = foundTasks.get(i); 640 List<ITaskInstance> shortTask = foundTasks.get(j); 575 641 576 642 if (getSubListIndex(longTask, shortTask, 0) > -1) { … … 598 664 * 599 665 */ 600 private List<I Sequence> sessions;601 602 /** 603 * 604 */ 605 private Trie<ITask TreeNode> lastTrie;666 private List<IUserSession> sessions; 667 668 /** 669 * 670 */ 671 private Trie<ITaskInstance> lastTrie; 606 672 607 673 /** … … 618 684 * 619 685 */ 620 private List<ITaskTreeNode> taskOccurrences = new LinkedList<ITaskTreeNode>(); 621 622 /** 623 * 624 */ 625 private int replacementCounter; 686 private boolean detectedAndReplacedTasks; 626 687 627 688 /** … … 638 699 * 639 700 */ 640 private RuleApplicationData(List<I Sequence> sessions) {701 private RuleApplicationData(List<IUserSession> sessions) { 641 702 this.sessions = sessions; 642 703 } … … 645 706 * @return the tree 646 707 */ 647 private List<I Sequence> getSessions() {708 private List<IUserSession> getSessions() { 648 709 return sessions; 649 710 } … … 652 713 * @param lastTrie the lastTrie to set 653 714 */ 654 private void setLastTrie(Trie<ITask TreeNode> lastTrie) {715 private void setLastTrie(Trie<ITaskInstance> lastTrie) { 655 716 this.lastTrie = lastTrie; 656 717 } … … 659 720 * @return the lastTrie 660 721 */ 661 private Trie<ITask TreeNode> getLastTrie() {722 private Trie<ITaskInstance> getLastTrie() { 662 723 return lastTrie; 663 724 } … … 692 753 693 754 /** 694 * @return the taskOccurrences695 */696 private void clearTaskOccurrences() {697 taskOccurrences.clear();698 }699 700 /**701 * @return the taskOccurrences702 */703 private void addTaskOccurrence(ITaskTreeNode taskOccurrence) {704 taskOccurrences.add(taskOccurrence);705 }706 707 /**708 * @return the taskOccurrences709 */710 private List<ITaskTreeNode> getTaskOccurrences() {711 return taskOccurrences;712 }713 714 /**715 755 * 716 756 */ 717 private void resetReplacementCounter() {718 replacementCounter = 0;757 private void detectedAndReplacedTasks(boolean detectedAndReplacedTasks) { 758 this.detectedAndReplacedTasks = detectedAndReplacedTasks; 719 759 } 720 760 … … 722 762 * 723 763 */ 724 private void incrementReplacementCounter() { 725 replacementCounter++; 726 } 727 728 /** 729 * 730 */ 731 private int getReplacementCounter() { 732 return replacementCounter; 764 private boolean detectedAndReplacedTasks() { 765 return detectedAndReplacedTasks; 733 766 } 734 767 … … 753 786 * @author Patrick Harms 754 787 */ 755 private static class Tasks implements Iterable<List<ITask TreeNode>> {788 private static class Tasks implements Iterable<List<ITaskInstance>> { 756 789 757 790 /** … … 763 796 * 764 797 */ 765 private List<List<ITask TreeNode>> sequences;798 private List<List<ITaskInstance>> sequences; 766 799 767 800 /** … … 769 802 * @param sequences 770 803 */ 771 private Tasks(int occurrenceCount, List<List<ITask TreeNode>> sequences) {804 private Tasks(int occurrenceCount, List<List<ITaskInstance>> sequences) { 772 805 super(); 773 806 this.occurrenceCount = occurrenceCount; … … 797 830 */ 798 831 @Override 799 public Iterator<List<ITask TreeNode>> iterator() {832 public Iterator<List<ITaskInstance>> iterator() { 800 833 return this.sequences.iterator(); 801 834 } … … 803 836 } 804 837 838 /** 839 * 840 */ 841 private class TaskComparator implements SymbolComparator<ITaskInstance> { 842 843 /** */ 844 private Comparer comparer; 845 846 /** */ 847 private Comparer lexicalComparer; 848 849 /** */ 850 private HashMap<Long, Boolean> equalityBuffer = new HashMap<Long, Boolean>(); 851 852 /** */ 853 private HashMap<Long, Boolean> lexicalEqualityBuffer; 854 855 /** 856 * 857 */ 858 public TaskComparator(TaskEqualityRuleManager taskEqualityRuleManager, 859 TaskEquality minimalNodeEquality) 860 { 861 super(); 862 863 if (minimalNodeEquality == TaskEquality.LEXICALLY_EQUAL) { 864 comparer = new LexicalComparer(taskEqualityRuleManager); 865 } 866 else if (minimalNodeEquality == TaskEquality.SYNTACTICALLY_EQUAL) { 867 comparer = new SyntacticalComparer(taskEqualityRuleManager); 868 } 869 else if (minimalNodeEquality == TaskEquality.SEMANTICALLY_EQUAL) { 870 comparer = new SemanticalComparer(taskEqualityRuleManager); 871 } 872 else { 873 comparer = new DefaultComparer(taskEqualityRuleManager, minimalNodeEquality); 874 } 875 876 if (minimalNodeEquality == TaskEquality.LEXICALLY_EQUAL) { 877 lexicalComparer = comparer; 878 lexicalEqualityBuffer = equalityBuffer; 879 } 880 else { 881 lexicalComparer = new LexicalComparer(taskEqualityRuleManager); 882 lexicalEqualityBuffer = new HashMap<Long, Boolean>(); 883 } 884 } 885 886 /* (non-Javadoc) 887 * @see de.ugoe.cs.autoquest.tasktrees.temporalrelation.SymbolComparator#equals(java.lang.Object, java.lang.Object) 888 */ 889 @Override 890 public boolean equals(ITaskInstance taskInstance1, ITaskInstance taskInstance2) { 891 return equals(taskInstance1.getTask(), taskInstance2.getTask()); 892 } 893 894 /** 895 * 896 */ 897 public boolean equals(ITask task1, ITask task2) { 898 Boolean result; 899 900 if (task1 != task2) { 901 if ((task1 instanceof IEventTask) && (task2 instanceof IEventTask)) { 902 long key = ((long) System.identityHashCode(task1)) << 32; 903 key += System.identityHashCode(task2); 904 905 result = equalityBuffer.get(key); 906 907 if (result == null) { 908 result = comparer.compare(task1, task2); 909 equalityBuffer.put(key, result); 910 } 911 } 912 else { 913 result = false; 914 } 915 } 916 else { 917 result = true; 918 } 919 920 return result; 921 } 922 923 /** 924 * 925 */ 926 public boolean areLexicallyEqual(ITask task1, ITask task2) { 927 Boolean result; 928 929 if (task1 != task2) { 930 long key = ((long) System.identityHashCode(task1)) << 32; 931 key += System.identityHashCode(task2); 932 933 result = lexicalEqualityBuffer.get(key); 934 935 if (result == null) { 936 result = lexicalComparer.compare(task1, task2); 937 lexicalEqualityBuffer.put(key, result); 938 } 939 } 940 else { 941 result = true; 942 } 943 944 return result; 945 } 946 } 947 948 /** 949 * 950 */ 951 private interface Comparer { 952 953 /** 954 * 955 */ 956 boolean compare(ITask task1, ITask task2); 957 } 958 959 /** 960 * 961 */ 962 private class LexicalComparer implements Comparer { 963 964 /** 965 * <p> 966 * the task equality manager needed for comparing tasks with each other 967 * </p> 968 */ 969 private TaskEqualityRuleManager taskEqualityRuleManager; 970 971 /** 972 * 973 */ 974 public LexicalComparer(TaskEqualityRuleManager taskEqualityRuleManager) { 975 this.taskEqualityRuleManager = taskEqualityRuleManager; 976 } 977 978 /** 979 * 980 */ 981 public boolean compare(ITask task1, ITask task2) { 982 return taskEqualityRuleManager.areLexicallyEqual(task1, task2); 983 } 984 } 985 986 /** 987 * 988 */ 989 private class SyntacticalComparer implements Comparer { 990 991 /** 992 * <p> 993 * the task equality manager needed for comparing tasks with each other 994 * </p> 995 */ 996 private TaskEqualityRuleManager taskEqualityRuleManager; 997 998 /** 999 * 1000 */ 1001 public SyntacticalComparer(TaskEqualityRuleManager taskEqualityRuleManager) { 1002 this.taskEqualityRuleManager = taskEqualityRuleManager; 1003 } 1004 1005 /** 1006 * 1007 */ 1008 public boolean compare(ITask task1, ITask task2) { 1009 return taskEqualityRuleManager.areSyntacticallyEqual(task1, task2); 1010 } 1011 } 1012 1013 /** 1014 * 1015 */ 1016 private class SemanticalComparer implements Comparer { 1017 1018 /** 1019 * <p> 1020 * the task equality manager needed for comparing tasks with each other 1021 * </p> 1022 */ 1023 private TaskEqualityRuleManager taskEqualityRuleManager; 1024 1025 /** 1026 * 1027 */ 1028 public SemanticalComparer(TaskEqualityRuleManager taskEqualityRuleManager) { 1029 this.taskEqualityRuleManager = taskEqualityRuleManager; 1030 } 1031 1032 /** 1033 * 1034 */ 1035 public boolean compare(ITask task1, ITask task2) { 1036 return taskEqualityRuleManager.areSemanticallyEqual(task1, task2); 1037 } 1038 } 1039 1040 /** 1041 * 1042 */ 1043 private class DefaultComparer implements Comparer { 1044 1045 /** 1046 * <p> 1047 * the task equality manager needed for comparing tasks with each other 1048 * </p> 1049 */ 1050 private TaskEqualityRuleManager taskEqualityRuleManager; 1051 1052 /** 1053 * <p> 1054 * the minimal task equality two identified sublists need to have to consider them as equal 1055 * </p> 1056 */ 1057 private TaskEquality minimalNodeEquality; 1058 1059 /** 1060 * 1061 */ 1062 public DefaultComparer(TaskEqualityRuleManager taskEqualityRuleManager, 1063 TaskEquality minimalNodeEquality) 1064 { 1065 this.taskEqualityRuleManager = taskEqualityRuleManager; 1066 this.minimalNodeEquality = minimalNodeEquality; 1067 } 1068 1069 /** 1070 * 1071 */ 1072 public boolean compare(ITask task1, ITask task2) { 1073 return taskEqualityRuleManager.areAtLeastEqual(task1, task2, minimalNodeEquality); 1074 } 1075 } 805 1076 } -
trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TemporalRelationshipRuleManager.java
r1131 r1146 22 22 import de.ugoe.cs.autoquest.eventcore.guimodel.IFrame; 23 23 import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement; 24 import de.ugoe.cs.autoquest.tasktrees.nodeequality.NodeEquality; 25 import de.ugoe.cs.autoquest.tasktrees.nodeequality.NodeEqualityRuleManager; 26 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeBuilder; 27 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNode; 28 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNodeFactory; 24 import de.ugoe.cs.autoquest.tasktrees.taskequality.TaskEquality; 25 import de.ugoe.cs.autoquest.tasktrees.taskequality.TaskEqualityRuleManager; 26 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskBuilder; 27 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskFactory; 28 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance; 29 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList; 30 import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession; 29 31 import de.ugoe.cs.util.console.Console; 30 32 31 33 /** 34 * TODO update comment 35 * 32 36 * <p> 33 37 * This class is responsible for applying temporal relationship rules on a task tree. Through this, 34 38 * a flat task tree is restructured to have more depth but to include more temporal relationships 35 * between task tree nodes which are not only a major sequence. I.e. through the application of36 * rule iterations and selections of task tree nodes are detected. Which kind of temporal relations37 * between task tree nodes are detected depends on the {@link TemporalRelationshipRule}s known to39 * between tasks which are not only a major sequence. I.e. through the application of the 40 * rules iterations and selections of tasks are detected. Which kind of temporal relations 41 * between tasks are detected depends on the {@link ITaskInstanceListScopeRule}s known to 38 42 * this class. 39 43 * </p> 40 * <p>The class holds references to the appropriate {@link TemporalRelationshipRule}s and calls41 * their {@link TemporalRelationshipRule#apply(ITaskTreeNode, ITaskTreeBuilder, ITaskTreeNodeFactory, boolean)}42 * method for each nodein the task tree it is needed for. The general behavior of this class is44 * <p>The class holds references to the appropriate {@link ITaskInstanceListScopeRule}s and calls 45 * their {@link ITaskInstanceListScopeRule#apply(ITask, ITaskBuilder, ITaskFactory, boolean)} 46 * method for each task in the task tree it is needed for. The general behavior of this class is 43 47 * the following: 44 48 * <ol> … … 48 52 * </li> 49 53 * <li> 50 * then the {@link #applyRules(ITask TreeNode, ITaskTreeBuilder, ITaskTreeNodeFactory, boolean)}51 * method is called for a so far unstructured task tree node54 * then the {@link #applyRules(ITask, ITaskBuilder, ITaskFactory, boolean)} 55 * method is called for a so far unstructured task 52 56 * </li> 53 57 * <li> 54 58 * the class iterates its internal list of rules and calls their 55 * {@link TemporalRelationshipRule#apply(ITaskTreeNode, ITaskTreeBuilder, ITaskTreeNodeFactory, boolean)}59 * {@link ITaskInstanceListScopeRule#apply(ITask, ITaskBuilder, ITaskFactory, boolean)} 56 60 * method. 57 61 * </li> … … 69 73 * <li> 70 74 * if a rule returns, that it was applied, the same rule is applied again until it returns 71 * null or feasible. For each newly created parent nodeprovided in the rule application72 * result, the {@link #applyRules(ITask TreeNode, ITaskTreeBuilder, ITaskTreeNodeFactory, boolean)}75 * null or feasible. For each newly created parent task provided in the rule application 76 * result, the {@link #applyRules(ITask, ITaskBuilder, ITaskFactory, boolean)} 73 77 * method is called. 74 78 * </li> … … 76 80 * </li> 77 81 * </ol> 78 * Through this, all rules are tried to be applied at least once to the provided parent nodeand79 * all parent nodes created during the rule application.82 * Through this, all rules are tried to be applied at least once to the provided parent task and 83 * all parent tasks created during the rule application. 80 84 * </p> 81 85 * … … 86 90 /** 87 91 * <p> 88 * the node equality manager needed by the rules to compare task tree nodes with each other 89 * </p> 90 */ 91 private NodeEqualityRuleManager nodeEqualityRuleManager; 92 93 /** 94 * <p> 95 * the task tree node factory to be used during rule application 96 * </p> 97 */ 98 private ITaskTreeNodeFactory taskTreeNodeFactory; 99 100 /** 101 * <p> 102 * the task tree builder to be used during rule application 103 * </p> 104 */ 105 private ITaskTreeBuilder taskTreeBuilder; 92 * the task equality manager needed by the rules to compare tasks with each other 93 * </p> 94 */ 95 private TaskEqualityRuleManager taskEqualityRuleManager; 96 97 /** 98 * <p> 99 * the task factory to be used during rule application 100 * </p> 101 */ 102 private ITaskFactory taskFactory; 103 104 /** 105 * <p> 106 * the task builder to be used during rule application 107 * </p> 108 */ 109 private ITaskBuilder taskBuilder; 110 111 /** 112 * <p> 113 * the temporal relationship rules known to the manager that are executed on whole sessions. 114 * The rules are applied in the order they occur in this list. 115 * </p> 116 */ 117 private ISessionScopeRule[] sessionScopeRules; 106 118 107 119 /** … … 111 123 * </p> 112 124 */ 113 private TemporalRelationshipRule[] treeScopeRules; 114 115 /** 116 * <p> 117 * the temporal relationship rules known to the manager that are executed on whole sub trees. 118 * The rules are applied in the order they occur in this list. 119 * </p> 120 */ 121 private TemporalRelationshipRule[] nodeScopeRules; 125 private ITaskInstanceListScopeRule[] taskScopeRules; 122 126 123 127 /** … … 126 130 * </p> 127 131 * 128 * @param nodeEqualityRuleManager the nodeequality rule manager to be used by the known rules129 * for task tree nodecomparison during rule application130 * @param task TreeNodeFactory the nodefactory to be used for instantiating new task tree131 * nodes during rule application132 * @param task TreeBuilder the task tree builder to be used for linking task tree nodes132 * @param taskEqualityRuleManager the task equality rule manager to be used by the known rules 133 * for task comparison during rule application 134 * @param taskFactory the task factory to be used for instantiating new task tree 135 * tasks during rule application 136 * @param taskBuilder the task builder to be used for linking tasks 133 137 * with each other during rule application 134 138 */ 135 public TemporalRelationshipRuleManager( NodeEqualityRuleManager nodeEqualityRuleManager,136 ITask TreeNodeFactory taskTreeNodeFactory,137 ITask TreeBuilder taskTreeBuilder)139 public TemporalRelationshipRuleManager(TaskEqualityRuleManager taskEqualityRuleManager, 140 ITaskFactory taskFactory, 141 ITaskBuilder taskBuilder) 138 142 { 139 143 super(); 140 this. nodeEqualityRuleManager = nodeEqualityRuleManager;141 this.task TreeNodeFactory = taskTreeNodeFactory;142 this.task TreeBuilder = taskTreeBuilder;144 this.taskEqualityRuleManager = taskEqualityRuleManager; 145 this.taskFactory = taskFactory; 146 this.taskBuilder = taskBuilder; 143 147 } 144 148 … … 146 150 * <p> 147 151 * initialized the temporal relationship rule manager by instantiating the known rules and 148 * providing them with a reference to the nodeequality manager or other information they need.152 * providing them with a reference to the task equality manager or other information they need. 149 153 * </p> 150 154 */ … … 156 160 //frameFilter.add(ICanvas.class); 157 161 158 treeScopeRules = new TemporalRelationshipRule[] {162 sessionScopeRules = new ISessionScopeRule[] { 159 163 new SequenceForTaskDetectionRule 160 ( nodeEqualityRuleManager, NodeEquality.SEMANTICALLY_EQUAL,161 task TreeNodeFactory, taskTreeBuilder),164 (taskEqualityRuleManager, TaskEquality.SEMANTICALLY_EQUAL, 165 taskFactory, taskBuilder), 162 166 /*new DefaultTaskSequenceDetectionRule 163 ( nodeEqualityRuleManager, NodeEquality.SYNTACTICALLY_EQUAL,164 task TreeNodeFactory, taskTreeBuilder),167 (taskEqualityRuleManager, NodeEquality.SYNTACTICALLY_EQUAL, 168 taskFactory, taskTreeBuilder), 165 169 new DefaultTaskSequenceDetectionRule 166 ( nodeEqualityRuleManager, NodeEquality.LEXICALLY_EQUAL,167 task TreeNodeFactory, taskTreeBuilder),*/170 (taskEqualityRuleManager, NodeEquality.LEXICALLY_EQUAL, 171 taskFactory, taskTreeBuilder),*/ 168 172 /*new TreeScopeWrapperRule 169 173 (new DefaultIterationDetectionRule 170 ( nodeEqualityRuleManager, NodeEquality.LEXICALLY_EQUAL,171 task TreeNodeFactory, taskTreeBuilder)),174 (taskEqualityRuleManager, NodeEquality.LEXICALLY_EQUAL, 175 taskFactory, taskTreeBuilder)), 172 176 new TreeScopeWrapperRule 173 177 (new DefaultIterationDetectionRule 174 ( nodeEqualityRuleManager, NodeEquality.SYNTACTICALLY_EQUAL,175 task TreeNodeFactory, taskTreeBuilder)),178 (taskEqualityRuleManager, NodeEquality.SYNTACTICALLY_EQUAL, 179 taskFactory, taskTreeBuilder)), 176 180 new TreeScopeWrapperRule 177 181 (new DefaultIterationDetectionRule 178 ( nodeEqualityRuleManager, NodeEquality.SEMANTICALLY_EQUAL,179 task TreeNodeFactory, taskTreeBuilder))*/182 (taskEqualityRuleManager, NodeEquality.SEMANTICALLY_EQUAL, 183 taskFactory, taskTreeBuilder))*/ 180 184 }; 181 185 182 186 //treeScopeRules.add(new DefaultGuiElementSequenceDetectionRule(frameFilter)); 183 187 184 nodeScopeRules = new TemporalRelationshipRule[] { 185 //new SequenceOnGuiElementDetectionRule(taskTreeNodeFactory, taskTreeBuilder), 186 //new EventSequenceOnSameTargetDetectionRule(taskTreeNodeFactory, taskTreeBuilder), 187 new TrackBarSelectionDetectionRule 188 (nodeEqualityRuleManager, taskTreeNodeFactory, taskTreeBuilder), 189 //new DefaultGuiEventSequenceDetectionRule(taskTreeNodeFactory, taskTreeBuilder), 188 taskScopeRules = new ITaskInstanceListScopeRule[] { 189 //new SequenceOnGuiElementDetectionRule(taskFactory, taskTreeBuilder), 190 //new EventSequenceOnSameTargetDetectionRule(taskFactory, taskTreeBuilder), 191 //new TrackBarSelectionDetectionRule(taskEqualityRuleManager, taskFactory, taskBuilder), 192 //new DefaultGuiEventSequenceDetectionRule(taskFactory, taskTreeBuilder), 190 193 }; 191 194 … … 194 197 /** 195 198 * <p> 196 * applies the known rules to the provided parent node. For the creation of further nodes,197 * the provided builder and node factory are utilized. The method expectes, that no more data199 * applies the known rules to the provided sessions. For the creation of further tasks, 200 * the provided builder and task factory are utilized. The method expects, that no more data 198 201 * is available and, therefore, finalizes the rule application. 199 202 * </p> 200 203 * 201 * @param nodeFactory the node factory to be used for instantiating new task tree nodes.202 */ 203 public void applyRules( ITaskTreeNode parent) {204 applyRules( parent, true);205 } 206 207 /** 208 * <p> 209 * applies the known rules to the provided parent node. For the creation of further nodes,210 * the provided builder and nodefactory are utilized. If the finalize parameter is true, the204 * @param taskFactory the task factory to be used for instantiating new tasks. 205 */ 206 public void applyRules(List<IUserSession> sessions) { 207 applyRules(sessionScopeRules, sessions, ""); 208 } 209 210 /** 211 * <p> 212 * applies the known rules to the provided parent task. For the creation of further tasks, 213 * the provided builder and task factory are utilized. If the finalize parameter is true, the 211 214 * rule application is finalized as far as possible without waiting for further data. If it is 212 215 * false, the rule application is broken up at the first rule returning, that its application 213 * would be feasible. 216 * would be feasible. The method calls itself for each parent task created through the rule 217 * application. In this case, the finalize parameter is always true. 214 218 * </p> 215 219 * 216 * @param parent the parent node to apply the rules on 217 * @param finalize used to indicate, if the rule application shall break up if a rule would 218 * be feasible if further data was available, or not. 219 */ 220 public void applyRules(ITaskTreeNode parent, boolean finalize) { 221 applyRules(treeScopeRules, parent, finalize, ""); 222 } 223 224 /** 225 * <p> 226 * applies the known rules to the provided parent node. For the creation of further nodes, 227 * the provided builder and node factory are utilized. If the finalize parameter is true, the 228 * rule application is finalized as far as possible without waiting for further data. If it is 229 * false, the rule application is broken up at the first rule returning, that its application 230 * would be feasible. The method calls itself for each parent node created through the rule 231 * application. In this case, the finalize parameter is always true. 232 * </p> 233 * 234 * @param parent the parent node to apply the rules on 220 * @param parent the parent task to apply the rules on 235 221 * @param finalize used to indicate, if the rule application shall break up if a rule would 236 222 * be feasible if further data was available, or not. … … 238 224 * on the recursion depth of calling this method. 239 225 */ 240 private int applyRules(TemporalRelationshipRule[] rules, 241 ITaskTreeNode parent, 242 boolean finalize, 243 String logIndent) 226 private int applyRules(ISessionScopeRule[] rules, 227 List<IUserSession> sessions, 228 String logIndent) 244 229 { 245 Console.traceln(Level.FINER, logIndent + "applying rules for " + parent); 230 Console.traceln 231 (Level.FINER, logIndent + "applying rules for " + sessions.size() + " sessions"); 246 232 247 233 int noOfRuleApplications = 0; 248 234 249 for ( TemporalRelationshipRule rule : rules) {235 for (ISessionScopeRule rule : rules) { 250 236 RuleApplicationResult result; 251 237 do { 252 Console.traceln(Level.FINER, logIndent + "trying rule " + rule + " on " + parent);253 result = rule.apply( parent, finalize);238 Console.traceln(Level.FINER, logIndent + "trying rule " + rule); 239 result = rule.apply(sessions); 254 240 255 241 if ((result != null) && 256 242 (result.getRuleApplicationStatus() == RuleApplicationStatus.FINISHED)) 257 243 { 258 Console.traceln 259 (Level.FINE, logIndent + "applied rule " + rule + " on " + parent); 244 Console.traceln(Level.FINE, logIndent + "applied rule " + rule); 260 245 noOfRuleApplications++; 261 246 262 247 //dumpTask(parent, ""); 263 248 264 for (ITask TreeNode newParent : result.getNewlyCreatedParentNodes()) {249 for (ITaskInstance newParent : result.getNewlyCreatedTaskInstances()) { 265 250 noOfRuleApplications += 266 applyRules( nodeScopeRules, newParent, true, logIndent + " ");251 applyRules(taskScopeRules, newParent, logIndent + " "); 267 252 } 268 253 } … … 271 256 (result.getRuleApplicationStatus() == RuleApplicationStatus.FINISHED)); 272 257 273 if ((!finalize) &&274 (result != null) &&275 (result.getRuleApplicationStatus() == RuleApplicationStatus.FEASIBLE))276 {277 // in this case, don't go on applying rules, which should not be applied yet278 break;279 }280 258 } 281 259 … … 289 267 290 268 /** 269 * <p> 270 * applies the known rules to the provided parent task. For the creation of further tasks, 271 * the provided builder and task factory are utilized. If the finalize parameter is true, the 272 * rule application is finalized as far as possible without waiting for further data. If it is 273 * false, the rule application is broken up at the first rule returning, that its application 274 * would be feasible. The method calls itself for each parent task created through the rule 275 * application. In this case, the finalize parameter is always true. 276 * </p> 277 * 278 * @param parent the parent task to apply the rules on 279 * @param finalize used to indicate, if the rule application shall break up if a rule would 280 * be feasible if further data was available, or not. 281 * @param logIndent simply used for logging purposes to indent the log messages depending 282 * on the recursion depth of calling this method. 283 */ 284 private int applyRules(ITaskInstanceListScopeRule[] rules, 285 ITaskInstanceList taskInstances, 286 String logIndent) 287 { 288 Console.traceln(Level.FINER, logIndent + "applying rules for " + taskInstances.size() + 289 " task instances"); 290 291 int noOfRuleApplications = 0; 292 293 for (ITaskInstanceListScopeRule rule : rules) { 294 RuleApplicationResult result; 295 do { 296 Console.traceln 297 (Level.FINER, logIndent + "trying rule " + rule + " on " + taskInstances); 298 result = rule.apply(taskInstances); 299 300 if ((result != null) && 301 (result.getRuleApplicationStatus() == RuleApplicationStatus.FINISHED)) 302 { 303 Console.traceln 304 (Level.FINE, logIndent + "applied rule " + rule + " on " + taskInstances); 305 noOfRuleApplications++; 306 307 //dumpTask(parent, ""); 308 309 for (ITaskInstance newParent : result.getNewlyCreatedTaskInstances()) { 310 noOfRuleApplications += 311 applyRules(taskScopeRules, newParent, logIndent + " "); 312 } 313 } 314 } 315 while ((result != null) && 316 (result.getRuleApplicationStatus() == RuleApplicationStatus.FINISHED)); 317 } 318 319 if (noOfRuleApplications <= 0) { 320 Console.traceln(Level.FINE, logIndent + "no rules applied --> no temporal " + 321 "relationship generated"); 322 } 323 324 return noOfRuleApplications; 325 } 326 327 /** 291 328 * 292 329 */ 293 /*private void dumpTask(ITask TreeNodetask, String indent) {330 /*private void dumpTask(ITask task, String indent) { 294 331 StringBuffer message = new StringBuffer(); 295 332 message.append(indent); … … 304 341 305 342 if ((task.getChildren() != null) && (task.getChildren().size() > 0)) { 306 for (ITask TreeNodechild : task.getChildren()) {343 for (ITask child : task.getChildren()) { 307 344 dumpTask(child, indent + " "); 308 345 }
Note: See TracChangeset
for help on using the changeset viewer.