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

Last change on this file since 1107 was 1107, checked in by pharms, 11 years ago
  • changed rules to be testable on their own
  • added first version for a task detection rule
  • refactored rules to have a simpler interface
  • Property svn:executable set to *
File size: 12.0 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 task tree node factory to be used during rule application
82     * </p>
83     */
84    private ITaskTreeNodeFactory taskTreeNodeFactory;
85
86    /**
87     * <p>
88     * the task tree builder to be used during rule application
89     * </p>
90     */
91    private ITaskTreeBuilder taskTreeBuilder;
92
93    /**
94     * <p>
95     * the temporal relationship rules known to the manager that are executed on whole sub trees.
96     * The rules are applied in the order they occur in this list.
97     * </p>
98     */
99    private TemporalRelationshipRule[] treeScopeRules;
100
101    /**
102     * <p>
103     * the temporal relationship rules known to the manager that are executed on whole sub trees.
104     * The rules are applied in the order they occur in this list.
105     * </p>
106     */
107    private TemporalRelationshipRule[] nodeScopeRules;
108
109    /**
110     * <p>
111     * initialize the manager
112     * </p>
113     *
114     * @param nodeEqualityRuleManager the node equality rule manager to be used by the known rules
115     *                                for task tree node comparison during rule application
116     * @param taskTreeNodeFactory     the node factory to be used for instantiating new task tree
117     *                                nodes during rule application
118     * @param taskTreeBuilder         the task tree builder to be used for linking task tree nodes
119     *                                with each other during rule application
120     */
121    public TemporalRelationshipRuleManager(NodeEqualityRuleManager nodeEqualityRuleManager,
122                                           ITaskTreeNodeFactory    taskTreeNodeFactory,
123                                           ITaskTreeBuilder        taskTreeBuilder)
124    {
125        super();
126        this.nodeEqualityRuleManager = nodeEqualityRuleManager;
127        this.taskTreeNodeFactory = taskTreeNodeFactory;
128        this.taskTreeBuilder = taskTreeBuilder;
129    }
130
131    /**
132     * <p>
133     * initialized the temporal relationship rule manager by instantiating the known rules and
134     * providing them with a reference to the node equality manager or other information they need.
135     * </p>
136     */
137    public void init() {
138        List<Class<? extends IGUIElement>> frameFilter =
139            new ArrayList<Class<? extends IGUIElement>>();
140        frameFilter.add(IFrame.class);
141        frameFilter.add(IDialog.class);
142        //frameFilter.add(ICanvas.class);
143
144        treeScopeRules = new TemporalRelationshipRule[] {
145            new DefaultTaskSequenceDetectionRule
146                (nodeEqualityRuleManager, NodeEquality.SEMANTICALLY_EQUAL,
147                 taskTreeNodeFactory, taskTreeBuilder)
148        };
149       
150        //treeScopeRules.add(new DefaultGuiElementSequenceDetectionRule(frameFilter));
151
152        nodeScopeRules = new TemporalRelationshipRule[] {
153            //new DefaultGuiElementSequenceDetectionRule(taskTreeNodeFactory, taskTreeBuilder),
154            //new DefaultEventTargetSequenceDetectionRule(taskTreeNodeFactory, taskTreeBuilder),
155            new TrackBarSelectionDetectionRule
156                (nodeEqualityRuleManager, taskTreeNodeFactory, taskTreeBuilder),
157            //new DefaultGuiEventSequenceDetectionRule(taskTreeNodeFactory, taskTreeBuilder),
158            new DefaultIterationDetectionRule
159                (nodeEqualityRuleManager, NodeEquality.LEXICALLY_EQUAL,
160                 taskTreeNodeFactory, taskTreeBuilder),
161            new DefaultIterationDetectionRule
162                (nodeEqualityRuleManager, NodeEquality.SYNTACTICALLY_EQUAL,
163                 taskTreeNodeFactory, taskTreeBuilder),
164            new DefaultIterationDetectionRule
165                (nodeEqualityRuleManager, NodeEquality.SEMANTICALLY_EQUAL,
166                 taskTreeNodeFactory, taskTreeBuilder)
167        };
168
169    }
170
171    /**
172     * <p>
173     * applies the known rules to the provided parent node. For the creation of further nodes,
174     * the provided builder and node factory are utilized. The method expectes, that no more data
175     * is available and, therefore, finalizes the rule application.
176     * </p>
177     *
178     * @param nodeFactory  the node factory to be used for instantiating new task tree nodes.
179     */
180    public void applyRules(ITaskTreeNode parent) {
181        applyRules(parent, true);
182    }
183
184    /**
185     * <p>
186     * applies the known rules to the provided parent node. For the creation of further nodes,
187     * the provided builder and node factory are utilized. If the finalize parameter is true, the
188     * rule application is finalized as far as possible without waiting for further data. If it is
189     * false, the rule application is broken up at the first rule returning, that its application
190     * would be feasible.
191     * </p>
192     *
193     * @param parent       the parent node to apply the rules on
194     * @param finalize     used to indicate, if the rule application shall break up if a rule would
195     *                     be feasible if further data was available, or not.
196     */
197    public void applyRules(ITaskTreeNode parent, boolean finalize) {
198        applyRules(treeScopeRules, parent, finalize, "");
199    }
200
201    /**
202     * <p>
203     * applies the known rules to the provided parent node. For the creation of further nodes,
204     * the provided builder and node factory are utilized. If the finalize parameter is true, the
205     * rule application is finalized as far as possible without waiting for further data. If it is
206     * false, the rule application is broken up at the first rule returning, that its application
207     * would be feasible. The method calls itself for each parent node created through the rule
208     * application. In this case, the finalize parameter is always true.
209     * </p>
210     *
211     * @param parent       the parent node to apply the rules on
212     * @param finalize     used to indicate, if the rule application shall break up if a rule would
213     *                     be feasible if further data was available, or not.
214     * @param logIndent    simply used for logging purposes to indent the log messages depending
215     *                     on the recursion depth of calling this method.
216     */
217    private int applyRules(TemporalRelationshipRule[] rules,
218                           ITaskTreeNode              parent,
219                           boolean                    finalize,
220                           String                     logIndent)
221    {
222        Console.traceln(Level.FINER, logIndent + "applying rules for " + parent);
223
224        int noOfRuleApplications = 0;
225
226        for (TemporalRelationshipRule rule : rules) {
227            RuleApplicationResult result;
228            do {
229                Console.traceln(Level.FINER, logIndent + "trying rule " + rule + " on " + parent);
230                result = rule.apply(parent, finalize);
231
232                if ((result != null) &&
233                    (result.getRuleApplicationStatus() ==
234                     RuleApplicationStatus.RULE_APPLICATION_FINISHED))
235                {
236                    Console.traceln
237                        (Level.FINE, logIndent + "applied rule " + rule + " on " + parent);
238                    noOfRuleApplications++;
239                   
240                    dumpTask(parent, "");
241
242                    for (ITaskTreeNode newParent : result.getNewlyCreatedParentNodes()) {
243                        noOfRuleApplications +=
244                            applyRules(nodeScopeRules, newParent, true, logIndent + "  ");
245                    }
246                }
247            }
248            while ((result != null) &&
249                   (result.getRuleApplicationStatus() ==
250                    RuleApplicationStatus.RULE_APPLICATION_FINISHED));
251
252            if ((!finalize) &&
253                (result != null) &&
254                (result.getRuleApplicationStatus() ==
255                 RuleApplicationStatus.RULE_APPLICATION_FEASIBLE))
256            {
257                // in this case, don't go on applying rules, which should not be applied yet
258                break;
259            }
260        }
261
262        if (noOfRuleApplications <= 0) {
263            Console.traceln(Level.INFO, logIndent + "no rules applied --> no temporal " +
264                            "relationship generated");
265        }
266
267        return noOfRuleApplications;
268    }
269
270    /**
271     *
272     */
273    private void dumpTask(ITaskTreeNode task, String indent) {
274        StringBuffer message = new StringBuffer();
275        message.append(indent);
276        message.append(task);
277        if (task.getDescription() != null) {
278            message.append('(');
279            message.append(task.getDescription());
280            message.append(')');
281        }
282       
283        Console.traceln(Level.FINER, message.toString());
284       
285        if ((task.getChildren() != null) && (task.getChildren().size() > 0)) {
286            for (ITaskTreeNode child : task.getChildren()) {
287                dumpTask(child, indent + "  ");
288            }
289        }
290    }
291
292}
Note: See TracBrowser for help on using the repository browser.