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

Last change on this file since 1891 was 1889, checked in by pharms, 9 years ago
  • added support for separating task tree generation and merging
  • Property svn:executable set to *
File size: 14.3 KB
Line 
1//   Copyright 2012 Georg-August-Universität Göttingen, Germany
2//
3//   Licensed under the Apache License, Version 2.0 (the "License");
4//   you may not use this file except in compliance with the License.
5//   You may obtain a copy of the License at
6//
7//       http://www.apache.org/licenses/LICENSE-2.0
8//
9//   Unless required by applicable law or agreed to in writing, software
10//   distributed under the License is distributed on an "AS IS" BASIS,
11//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//   See the License for the specific language governing permissions and
13//   limitations under the License.
14
15package de.ugoe.cs.autoquest.tasktrees.temporalrelation;
16
17import java.util.ArrayList;
18import java.util.List;
19import java.util.logging.Level;
20
21import de.ugoe.cs.autoquest.eventcore.guimodel.IDialog;
22import de.ugoe.cs.autoquest.eventcore.guimodel.IFrame;
23import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement;
24import de.ugoe.cs.autoquest.tasktrees.taskequality.TaskEquality;
25import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskBuilder;
26import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskFactory;
27import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
28import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession;
29import de.ugoe.cs.util.console.Console;
30
31/**
32 * TODO update comment
33 *
34 * <p>
35 * This class is responsible for applying temporal relationship rules on a task tree. Through this,
36 * a flat task tree is restructured to have more depth but to include more temporal relationships
37 * between tasks which are not only a major sequence. I.e. through the application of the
38 * rules iterations and selections of tasks are detected. Which kind of temporal relations
39 * between tasks are detected depends on the {@link ITaskInstanceScopeRule}s known to
40 * this class.
41 * </p>
42 * <p>The class holds references to the appropriate {@link ITaskInstanceScopeRule}s and calls
43 * their {@link ITaskInstanceScopeRule#apply(ITask, ITaskBuilder, ITaskFactory, boolean)}
44 * method for each task in the task tree it is needed for. The general behavior of this class is
45 * the following:
46 * <ol>
47 *   <li>
48 *     An instance of this class is created using the constructor and calling the
49 *     {@link #init()} method afterwards
50 *   </li>
51 *   <li>
52 *     then the {@link #applyRules(ITask, ITaskBuilder, ITaskFactory, boolean)}
53 *     method is called for a so far unstructured task
54 *   </li>
55 *   <li>
56 *     the class iterates its internal list of rules and calls their
57 *     {@link ITaskInstanceScopeRule#apply(ITask, ITaskBuilder, ITaskFactory, boolean)}
58 *     method.
59 *   </li>
60 *   <li>
61 *     the class evaluates the rule application result
62 *     <ul>
63 *       <li>
64 *         if a rule returns a rule application result that is null, the next rule is tried
65 *       </li>
66 *       <li>
67 *         if a rule returns that it would be feasible if more data was available and the rule
68 *         application shall not be finalized (see finalize parameter of the applyRules method)
69 *         the rule application is broken up
70 *       </li>
71 *       <li>
72 *         if a rule returns, that it was applied, the same rule is applied again until it returns
73 *         null or feasible. For each newly created parent task provided in the rule application
74 *         result, the {@link #applyRules(ITask, ITaskBuilder, ITaskFactory, boolean)}
75 *         method is called.
76 *       </li>
77 *     </ul>
78 *   </li>
79 * </ol>
80 * Through this, all rules are tried to be applied at least once to the provided parent task and
81 * all parent tasks created during the rule application.
82 * </p>
83 *
84 * @author Patrick Harms
85 */
86public class TemporalRelationshipRuleManager {
87   
88    /**
89     * <p>
90     * the task factory to be used during rule application
91     * </p>
92     */
93    private ITaskFactory taskFactory;
94
95    /**
96     * <p>
97     * the task builder to be used during rule application
98     * </p>
99     */
100    private ITaskBuilder taskBuilder;
101
102    /**
103     * <p>
104     * the temporal relationship rules known to the manager that are executed on whole sessions.
105     * The rules are applied in the order they occur in this list.
106     * </p>
107     */
108    private ISessionScopeRule[] sessionScopeRules;
109
110    /**
111     * <p>
112     * the temporal relationship rules known to the manager that are executed on whole sub trees.
113     * The rules are applied in the order they occur in this list.
114     * </p>
115     */
116    private ITaskInstanceScopeRule[] taskScopeRules;
117
118    /**
119     * <p>
120     * initialize the manager
121     * </p>
122     *
123     * @param taskFactory             the task factory to be used for instantiating new task tree
124     *                                tasks during rule application
125     * @param taskBuilder             the task builder to be used for linking tasks
126     *                                with each other during rule application
127     */
128    public TemporalRelationshipRuleManager(ITaskFactory taskFactory, ITaskBuilder taskBuilder) {
129        super();
130        this.taskFactory = taskFactory;
131        this.taskBuilder = taskBuilder;
132    }
133
134    /**
135     * <p>
136     * initialized the temporal relationship rule manager by instantiating the known rules and
137     * providing them with a reference to the task equality manager or other information they need.
138     * </p>
139     */
140    public void init() {
141        List<Class<? extends IGUIElement>> frameFilter =
142            new ArrayList<Class<? extends IGUIElement>>();
143        frameFilter.add(IFrame.class);
144        frameFilter.add(IDialog.class);
145        //frameFilter.add(ICanvas.class);
146
147        sessionScopeRules = new ISessionScopeRule[] {
148            new SequenceForTaskDetectionRule
149                (TaskEquality.SEMANTICALLY_EQUAL, taskFactory, taskBuilder),
150            new CondenseSimilarTasksRule
151                (TaskEquality.SEMANTICALLY_EQUAL, taskFactory, taskBuilder),
152            /*new DefaultTaskSequenceDetectionRule
153                (NodeEquality.SYNTACTICALLY_EQUAL, taskFactory, taskTreeBuilder),
154            new DefaultTaskSequenceDetectionRule
155                (NodeEquality.LEXICALLY_EQUAL, taskFactory, taskTreeBuilder),*/
156            /*new TreeScopeWrapperRule
157                (new DefaultIterationDetectionRule
158                    (NodeEquality.LEXICALLY_EQUAL, taskFactory, taskTreeBuilder)),
159            new TreeScopeWrapperRule
160                (new DefaultIterationDetectionRule
161                    (NodeEquality.SYNTACTICALLY_EQUAL, taskFactory, taskTreeBuilder)),
162            new TreeScopeWrapperRule
163                (new DefaultIterationDetectionRule
164                    (NodeEquality.SEMANTICALLY_EQUAL, taskFactory, taskTreeBuilder))*/
165        };
166       
167        //treeScopeRules.add(new DefaultGuiElementSequenceDetectionRule(frameFilter));
168
169        taskScopeRules = new ITaskInstanceScopeRule[] {
170            //new SequenceOnGuiElementDetectionRule(taskFactory, taskTreeBuilder),
171            //new EventSequenceOnSameTargetDetectionRule(taskFactory, taskTreeBuilder),
172            //new TrackBarSelectionDetectionRule(taskFactory, taskBuilder),
173            //new DefaultGuiEventSequenceDetectionRule(taskFactory, taskTreeBuilder),
174        };
175
176    }
177
178    /**
179     * <p>
180     * applies the known rules to the provided sessions. For the creation of further tasks,
181     * the provided builder and task factory are utilized. The method expects, that no more data
182     * is available and, therefore, finalizes the rule application.
183     * </p>
184     *
185     * @param sessions  the sessions to be processed
186     */
187    public void applyRules(List<IUserSession> sessions) {
188        applyRules(sessionScopeRules, sessions, "");
189    }
190
191    /**
192     * <p>
193     * applies only the known rules for task detection, i.e., currently only the sequence for task
194     * detection rule
195     * </p>
196     *
197     * @param sessions  the sessions to be processed
198     */
199    public void applyTaskDetectionRule(List<IUserSession> sessions) {
200        ISessionScopeRule[] rules = new ISessionScopeRule[] {
201            new SequenceForTaskDetectionRule
202                (TaskEquality.SEMANTICALLY_EQUAL, taskFactory, taskBuilder)
203        };
204       
205        applyRules(rules, sessions, "");
206    }
207
208    /**
209     * <p>
210     * applies only the known rules for task merging, i.e., currently only the condense similar task
211     * rule
212     * </p>
213     *
214     * @param sessions  the sessions to be processed
215     */
216    public void applyTaskMergingRule(List<IUserSession> sessions) {
217        ISessionScopeRule[] rules = new ISessionScopeRule[] {
218            new CondenseSimilarTasksRule
219                (TaskEquality.SEMANTICALLY_EQUAL, taskFactory, taskBuilder)
220        };
221       
222        applyRules(rules, sessions, "");
223    }
224
225    /**
226     * <p>
227     * applies the known rules to the provided parent task. For the creation of further tasks,
228     * the provided builder and task factory are utilized. If the finalize parameter is true, the
229     * rule application is finalized as far as possible without waiting for further data. If it is
230     * false, the rule application is broken up at the first rule returning, that its application
231     * would be feasible. The method calls itself for each parent task created through the rule
232     * application. In this case, the finalize parameter is always true.
233     * </p>
234     *
235     * @param parent       the parent task to apply the rules on
236     * @param finalize     used to indicate, if the rule application shall break up if a rule would
237     *                     be feasible if further data was available, or not.
238     * @param logIndent    simply used for logging purposes to indent the log messages depending
239     *                     on the recursion depth of calling this method.
240     */
241    private int applyRules(ISessionScopeRule[] rules,
242                           List<IUserSession>  sessions,
243                           String              logIndent)
244    {
245        Console.traceln
246            (Level.FINER, logIndent + "applying rules for " + sessions.size() + " sessions");
247
248        int noOfRuleApplications = 0;
249
250        for (ISessionScopeRule rule : rules) {
251            RuleApplicationResult result;
252            do {
253                Console.traceln(Level.FINER, logIndent + "trying rule " + rule);
254                result = rule.apply(sessions);
255
256                if ((result != null) &&
257                    (result.getRuleApplicationStatus() == RuleApplicationStatus.FINISHED))
258                {
259                    Console.traceln(Level.FINE, logIndent + "applied rule " + rule);
260                    noOfRuleApplications++;
261                   
262                    //dumpTask(parent, "");
263
264                    for (ITaskInstance newParent : result.getNewlyCreatedTaskInstances()) {
265                        noOfRuleApplications +=
266                            applyRules(taskScopeRules, newParent, logIndent + "  ");
267                    }
268                }
269            }
270            while ((result != null) &&
271                   (result.getRuleApplicationStatus() == RuleApplicationStatus.FINISHED));
272
273        }
274
275        if (noOfRuleApplications <= 0) {
276            Console.traceln(Level.FINE, logIndent + "no rules applied --> no temporal " +
277                            "relationship generated");
278        }
279
280        return noOfRuleApplications;
281    }
282
283    /**
284     * <p>
285     * applies the known rules to the provided parent task. For the creation of further tasks,
286     * the provided builder and task factory are utilized. If the finalize parameter is true, the
287     * rule application is finalized as far as possible without waiting for further data. If it is
288     * false, the rule application is broken up at the first rule returning, that its application
289     * would be feasible. The method calls itself for each parent task created through the rule
290     * application. In this case, the finalize parameter is always true.
291     * </p>
292     *
293     * @param parent       the parent task to apply the rules on
294     * @param finalize     used to indicate, if the rule application shall break up if a rule would
295     *                     be feasible if further data was available, or not.
296     * @param logIndent    simply used for logging purposes to indent the log messages depending
297     *                     on the recursion depth of calling this method.
298     */
299    private int applyRules(ITaskInstanceScopeRule[] rules,
300                           ITaskInstance                taskInstance,
301                           String                       logIndent)
302    {
303        Console.traceln(Level.FINER, logIndent + "applying rules on " + taskInstance);
304
305        int noOfRuleApplications = 0;
306
307        for (ITaskInstanceScopeRule rule : rules) {
308            RuleApplicationResult result;
309            do {
310                Console.traceln
311                    (Level.FINER, logIndent + "trying rule " + rule + " on " + taskInstance);
312                result = rule.apply(taskInstance);
313
314                if ((result != null) &&
315                    (result.getRuleApplicationStatus() == RuleApplicationStatus.FINISHED))
316                {
317                    Console.traceln
318                        (Level.FINE, logIndent + "applied rule " + rule + " on " + taskInstance);
319                    noOfRuleApplications++;
320                   
321                    //dumpTask(parent, "");
322
323                    for (ITaskInstance newParent : result.getNewlyCreatedTaskInstances()) {
324                        noOfRuleApplications +=
325                            applyRules(taskScopeRules, newParent, logIndent + "  ");
326                    }
327                }
328            }
329            while ((result != null) &&
330                   (result.getRuleApplicationStatus() == RuleApplicationStatus.FINISHED));
331        }
332
333        if (noOfRuleApplications <= 0) {
334            Console.traceln(Level.FINE, logIndent + "no rules applied --> no temporal " +
335                            "relationship generated");
336        }
337
338        return noOfRuleApplications;
339    }
340
341    /**
342     *
343     */
344    /*private void dumpTask(ITask task, String indent) {
345        StringBuffer message = new StringBuffer();
346        message.append(indent);
347        message.append(task);
348        if (task.getDescription() != null) {
349            message.append('(');
350            message.append(task.getDescription());
351            message.append(')');
352        }
353       
354        Console.traceln(Level.FINER, message.toString());
355       
356        if ((task.getChildren() != null) && (task.getChildren().size() > 0)) {
357            for (ITask child : task.getChildren()) {
358                dumpTask(child, indent + "  ");
359            }
360        }
361    }*/
362
363}
Note: See TracBrowser for help on using the repository browser.