source: trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TemporalRelationshipRuleManager.java @ 987

Last change on this file since 987 was 987, checked in by pharms, 12 years ago
  • improvement and documentation of the creation of sub sequences based on the GUI hierarchy
  • Property svn:executable set to *
File size: 10.3 KB
Line 
1package de.ugoe.cs.autoquest.tasktrees.temporalrelation;
2
3import java.util.ArrayList;
4import java.util.List;
5import java.util.logging.Level;
6
7import de.ugoe.cs.autoquest.eventcore.guimodel.IDialog;
8import de.ugoe.cs.autoquest.eventcore.guimodel.IFrame;
9import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement;
10import de.ugoe.cs.autoquest.tasktrees.nodeequality.NodeEquality;
11import de.ugoe.cs.autoquest.tasktrees.nodeequality.NodeEqualityRuleManager;
12import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeBuilder;
13import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNode;
14import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNodeFactory;
15import de.ugoe.cs.util.console.Console;
16
17/**
18 * <p>
19 * This class is responsible for applying temporal relationship rules on a task tree. Through this,
20 * a flat task tree is restructured to have more depth but to include more temporal relationships
21 * between task tree nodes which are not only a major sequence. I.e. through the application of
22 * rule iterations and selections of task tree nodes are detected. Which kind of temporal relations
23 * between task tree nodes are detected depends on the {@link TemporalRelationshipRule}s known to
24 * this class.
25 * </p>
26 * <p>The class holds references to the appropriate {@link TemporalRelationshipRule}s and calls
27 * their {@link TemporalRelationshipRule#apply(ITaskTreeNode, ITaskTreeBuilder, ITaskTreeNodeFactory, boolean)}
28 * method for each node in the task tree it is needed for. The general behavior of this class is
29 * the following:
30 * <ol>
31 *   <li>
32 *     An instance of this class is created using the constructor and calling the
33 *     {@link #init()} method afterwards
34 *   </li>
35 *   <li>
36 *     then the {@link #applyRules(ITaskTreeNode, ITaskTreeBuilder, ITaskTreeNodeFactory, boolean)}
37 *     method is called for a so far unstructured task tree node
38 *   </li>
39 *   <li>
40 *     the class iterates its internal list of rules and calls their
41 *     {@link TemporalRelationshipRule#apply(ITaskTreeNode, ITaskTreeBuilder, ITaskTreeNodeFactory, boolean)}
42 *     method.
43 *   </li>
44 *   <li>
45 *     the class evaluates the rule application result
46 *     <ul>
47 *       <li>
48 *         if a rule returns a rule application result that is null, the next rule is tried
49 *       </li>
50 *       <li>
51 *         if a rule returns that it would be feasible if more data was available and the rule
52 *         application shall not be finalized (see finalize parameter of the applyRules method)
53 *         the rule application is broken up
54 *       </li>
55 *       <li>
56 *         if a rule returns, that it was applied, the same rule is applied again until it returns
57 *         null or feasible. For each newly created parent node provided in the rule application
58 *         result, the {@link #applyRules(ITaskTreeNode, ITaskTreeBuilder, ITaskTreeNodeFactory, boolean)}
59 *         method is called.
60 *       </li>
61 *     </ul>
62 *   </li>
63 * </ol>
64 * Through this, all rules are tried to be applied at least once to the provided parent node and
65 * all parent nodes created during the rule application.
66 * </p>
67 *
68 * @author Patrick Harms
69 */
70public class TemporalRelationshipRuleManager {
71   
72    /**
73     * <p>
74     * the node equality manager needed by the rules to compare task tree nodes with each other
75     * </p>
76     */
77    private NodeEqualityRuleManager nodeEqualityRuleManager;
78
79    /**
80     * <p>
81     * the temporal relationship rule known to the manager. The rules are applied in the order
82     * they occur in this list.
83     * </p>
84     */
85    private List<TemporalRelationshipRule> rules = new ArrayList<TemporalRelationshipRule>();
86
87    /**
88     * <p>
89     * initialize the manager with a node equality rule manager to be used by the known rules
90     * for task tree node comparison.
91     * </p>
92     */
93    public TemporalRelationshipRuleManager(NodeEqualityRuleManager nodeEqualityRuleManager) {
94        super();
95        this.nodeEqualityRuleManager = nodeEqualityRuleManager;
96    }
97
98    /**
99     * <p>
100     * initialized the temporal relationship rule manager by instantiating the known rules and
101     * providing them with a reference to the node equality manager or other information they need.
102     * </p>
103     */
104    public void init() {
105        List<Class<? extends IGUIElement>> frameFilter =
106            new ArrayList<Class<? extends IGUIElement>>();
107        frameFilter.add(IFrame.class);
108        frameFilter.add(IDialog.class);
109
110        rules.add(new DefaultGuiElementSequenceDetectionRule(frameFilter));
111        rules.add(new DefaultGuiElementSequenceDetectionRule());
112        rules.add(new DefaultEventTargetSequenceDetectionRule());
113        rules.add(new TrackBarSelectionDetectionRule(nodeEqualityRuleManager));
114        //rules.add(new DefaultGuiEventSequenceDetectionRule());
115       
116        rules.add(new DefaultIterationDetectionRule
117                      (nodeEqualityRuleManager, NodeEquality.LEXICALLY_EQUAL));
118        rules.add(new DefaultIterationDetectionRule
119                      (nodeEqualityRuleManager, NodeEquality.SYNTACTICALLY_EQUAL));
120        rules.add(new DefaultIterationDetectionRule
121                      (nodeEqualityRuleManager, NodeEquality.SEMANTICALLY_EQUAL));
122    }
123
124    /**
125     * <p>
126     * applies the known rules to the provided parent node. For the creation of further nodes,
127     * the provided builder and node factory are utilized. If the finalize parameter is true, the
128     * rule application is finalized as far as possible without waiting for further data. If it is
129     * false, the rule application is broken up at the first rule returning, that its application
130     * would be feasible.
131     * </p>
132     *
133     * @param parent       the parent node to apply the rules on
134     * @param builder      the task tree builder to be used for linking task tree nodes with each
135     *                     other
136     * @param nodeFactory  the node factory to be used for instantiating new task tree nodes.
137     * @param finalize     used to indicate, if the rule application shall break up if a rule would
138     *                     be feasible if further data was available, or not.
139     */
140    public void applyRules(ITaskTreeNode        parent,
141                           ITaskTreeBuilder     builder,
142                           ITaskTreeNodeFactory nodeFactory,
143                           boolean              finalize)
144    {
145        applyRules(parent, builder, nodeFactory, finalize, "");
146    }
147
148    /**
149     * <p>
150     * applies the known rules to the provided parent node. For the creation of further nodes,
151     * the provided builder and node factory are utilized. If the finalize parameter is true, the
152     * rule application is finalized as far as possible without waiting for further data. If it is
153     * false, the rule application is broken up at the first rule returning, that its application
154     * would be feasible. The method calls itself for each parent node created through the rule
155     * application. In this case, the finalize parameter is always true.
156     * </p>
157     *
158     * @param parent       the parent node to apply the rules on
159     * @param builder      the task tree builder to be used for linking task tree nodes with each
160     *                     other
161     * @param nodeFactory  the node factory to be used for instantiating new task tree nodes.
162     * @param finalize     used to indicate, if the rule application shall break up if a rule would
163     *                     be feasible if further data was available, or not.
164     * @param logIndent    simply used for logging purposes to indent the log messages depending
165     *                     on the recursion depth of calling this method.
166     */
167    private int applyRules(ITaskTreeNode        parent,
168                           ITaskTreeBuilder     builder,
169                           ITaskTreeNodeFactory nodeFactory,
170                           boolean              finalize,
171                           String               logIndent)
172    {
173        Console.traceln(Level.FINER, logIndent + "applying rules for " + parent);
174
175        int noOfRuleApplications = 0;
176
177        for (TemporalRelationshipRule rule : rules) {
178            RuleApplicationResult result;
179            do {
180                Console.traceln(Level.FINER, logIndent + "trying rule " + rule + " on " + parent);
181                result = rule.apply(parent, builder, nodeFactory, finalize);
182
183                if ((result != null) &&
184                    (result.getRuleApplicationStatus() ==
185                     RuleApplicationStatus.RULE_APPLICATION_FINISHED))
186                {
187                    Console.traceln
188                        (Level.FINE, logIndent + "applied rule " + rule + " on " + parent);
189                    noOfRuleApplications++;
190                   
191                    dumpTask(parent, "");
192
193                    for (ITaskTreeNode newParent : result.getNewlyCreatedParentNodes()) {
194                        noOfRuleApplications +=
195                            applyRules(newParent, builder, nodeFactory, true, logIndent + "  ");
196                    }
197                }
198            }
199            while ((result != null) &&
200                   (result.getRuleApplicationStatus() ==
201                    RuleApplicationStatus.RULE_APPLICATION_FINISHED));
202
203            if ((!finalize) &&
204                (result != null) &&
205                (result.getRuleApplicationStatus() ==
206                 RuleApplicationStatus.RULE_APPLICATION_FEASIBLE))
207            {
208                // in this case, don't go on applying rules, which should not be applied yet
209                break;
210            }
211        }
212
213        if (noOfRuleApplications <= 0) {
214            Console.traceln(Level.INFO, logIndent + "no rules applied --> no temporal " +
215                            "relationship generated");
216        }
217
218        return noOfRuleApplications;
219    }
220
221    /**
222     *
223     */
224    private void dumpTask(ITaskTreeNode task, String indent) {
225        StringBuffer message = new StringBuffer();
226        message.append(indent);
227        message.append(task);
228        if (task.getDescription() != null) {
229            message.append('(');
230            message.append(task.getDescription());
231            message.append(')');
232        }
233       
234        Console.traceln(Level.FINER, message.toString());
235       
236        if ((task.getChildren() != null) && (task.getChildren().size() > 0)) {
237            for (ITaskTreeNode child : task.getChildren()) {
238                dumpTask(child, indent + "  ");
239            }
240        }
241    }
242
243}
Note: See TracBrowser for help on using the repository browser.