package de.ugoe.cs.autoquest.tasktrees.temporalrelation; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import de.ugoe.cs.autoquest.tasktrees.nodeequality.NodeEquality; import de.ugoe.cs.autoquest.tasktrees.nodeequality.NodeEqualityRuleManager; import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeBuilder; import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNode; import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNodeFactory; import de.ugoe.cs.util.console.Console; /** *

* This class is responsible for applying temporal relationship rules on a task tree. Through this, * a flat task tree is restructured to have more depth but to include more temporal relationships * between task tree nodes which are not only a major sequence. I.e. through the application of * rule iterations and selections of task tree nodes are detected. Which kind of temporal relations * between task tree nodes are detected depends on the {@link TemporalRelationshipRule}s known to * this class. *

*

The class holds references to the appropriate {@link TemporalRelationshipRule}s and calls * their {@link TemporalRelationshipRule#apply(ITaskTreeNode, ITaskTreeBuilder, ITaskTreeNodeFactory, boolean)} * method for each node in the task tree it is needed for. The general behavior of this class is * the following: *

    *
  1. * An instance of this class is created using the constructor and calling the * {@link #init()} method afterwards *
  2. *
  3. * then the {@link #applyRules(ITaskTreeNode, ITaskTreeBuilder, ITaskTreeNodeFactory, boolean)} * method is called for a so far unstructured task tree node *
  4. *
  5. * the class iterates its internal list of rules and calls their * {@link TemporalRelationshipRule#apply(ITaskTreeNode, ITaskTreeBuilder, ITaskTreeNodeFactory, boolean)} * method. *
  6. *
  7. * the class evaluates the rule application result * *
  8. *
* Through this, all rules are tried to be applied at least once to the provided parent node and * all parent nodes created during the rule application. *

* * @author Patrick Harms */ public class TemporalRelationshipRuleManager { /** *

* the node equality manager needed by the rules to compare task tree nodes with each other *

*/ private NodeEqualityRuleManager nodeEqualityRuleManager; /** *

* the temporal relationship rule known to the manager. The rules are applied in the order * they occur in this list. *

*/ private List rules = new ArrayList(); /** *

* initialize the manager with a node equality rule manager to be used by the known rules * for task tree node comparison. *

*/ public TemporalRelationshipRuleManager(NodeEqualityRuleManager nodeEqualityRuleManager) { super(); this.nodeEqualityRuleManager = nodeEqualityRuleManager; } /** *

* initialized the temporal relationship rule manager by instantiating the known rules and * providing them with a reference to the node equality manager or other information they need. *

*/ public void init() { rules.add(new DefaultGuiElementSequenceDetectionRule()); rules.add(new DefaultEventTargetSequenceDetectionRule()); rules.add(new TrackBarSelectionDetectionRule(nodeEqualityRuleManager)); rules.add(new DefaultGuiEventSequenceDetectionRule()); rules.add(new DefaultIterationDetectionRule (nodeEqualityRuleManager, NodeEquality.LEXICALLY_EQUAL)); rules.add(new DefaultIterationDetectionRule (nodeEqualityRuleManager, NodeEquality.SYNTACTICALLY_EQUAL)); rules.add(new DefaultIterationDetectionRule (nodeEqualityRuleManager, NodeEquality.SEMANTICALLY_EQUAL)); } /** *

* applies the known rules to the provided parent node. For the creation of further nodes, * the provided builder and node factory are utilized. If the finalize parameter is true, the * rule application is finalized as far as possible without waiting for further data. If it is * false, the rule application is broken up at the first rule returning, that its application * would be feasible. *

* * @param parent the parent node to apply the rules on * @param builder the task tree builder to be used for linking task tree nodes with each * other * @param nodeFactory the node factory to be used for instantiating new task tree nodes. * @param finalize used to indicate, if the rule application shall break up if a rule would * be feasible if further data was available, or not. */ public void applyRules(ITaskTreeNode parent, ITaskTreeBuilder builder, ITaskTreeNodeFactory nodeFactory, boolean finalize) { applyRules(parent, builder, nodeFactory, finalize, ""); } /** *

* applies the known rules to the provided parent node. For the creation of further nodes, * the provided builder and node factory are utilized. If the finalize parameter is true, the * rule application is finalized as far as possible without waiting for further data. If it is * false, the rule application is broken up at the first rule returning, that its application * would be feasible. The method calls itself for each parent node created through the rule * application. In this case, the finalize parameter is always true. *

* * @param parent the parent node to apply the rules on * @param builder the task tree builder to be used for linking task tree nodes with each * other * @param nodeFactory the node factory to be used for instantiating new task tree nodes. * @param finalize used to indicate, if the rule application shall break up if a rule would * be feasible if further data was available, or not. * @param logIndent simply used for loggin purposes to indent the log messages depending * on the recursion depth of calling this method. */ private int applyRules(ITaskTreeNode parent, ITaskTreeBuilder builder, ITaskTreeNodeFactory nodeFactory, boolean finalize, String logIndent) { Console.traceln(Level.FINER, logIndent + "applying rules for " + parent); int noOfRuleApplications = 0; for (TemporalRelationshipRule rule : rules) { RuleApplicationResult result; do { // LOG.info(logIndent + "trying to apply rule " + rule + " on " + parent); result = rule.apply(parent, builder, nodeFactory, finalize); if ((result != null) && (result.getRuleApplicationStatus() == RuleApplicationStatus.RULE_APPLICATION_FINISHED)) { Console.traceln (Level.FINE, logIndent + "applied rule " + rule + " on " + parent); noOfRuleApplications++; for (ITaskTreeNode newParent : result.getNewlyCreatedParentNodes()) { noOfRuleApplications += applyRules(newParent, builder, nodeFactory, true, logIndent + " "); } } } while ((result != null) && (result.getRuleApplicationStatus() == RuleApplicationStatus.RULE_APPLICATION_FINISHED)); if ((!finalize) && (result != null) && (result.getRuleApplicationStatus() == RuleApplicationStatus.RULE_APPLICATION_FEASIBLE)) { // in this case, don't go on applying rules, which should not be applied yet break; } } if (noOfRuleApplications <= 0) { Console.traceln(Level.INFO, logIndent + "no rules applied --> no temporal " + "relationship generated"); } return noOfRuleApplications; } /** * */ /* * private void dumpTask(TaskTreeNode task, String indent) { System.err.print(indent); * System.err.print(task); System.err.println(" "); * * if ((task.getChildren() != null) && (task.getChildren().size() > 0)) { for (TaskTreeNode * child : task.getChildren()) { dumpTask(child, indent + " "); } } } */ }