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

Last change on this file since 1146 was 1146, checked in by pharms, 11 years ago
  • complete refactoring of task tree model with a separation of task models and task instances
  • appropriate adaptation of task tree generation process
  • appropriate adaptation of commands and task tree visualization
  • Property svn:executable set to *
File size: 14.3 KB
RevLine 
[1113]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
[922]15package de.ugoe.cs.autoquest.tasktrees.temporalrelation;
[439]16
17import java.util.ArrayList;
18import java.util.List;
[725]19import java.util.logging.Level;
[439]20
[987]21import de.ugoe.cs.autoquest.eventcore.guimodel.IDialog;
22import de.ugoe.cs.autoquest.eventcore.guimodel.IFrame;
23import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement;
[1146]24import de.ugoe.cs.autoquest.tasktrees.taskequality.TaskEquality;
25import de.ugoe.cs.autoquest.tasktrees.taskequality.TaskEqualityRuleManager;
26import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskBuilder;
27import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskFactory;
28import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
29import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList;
30import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession;
[725]31import de.ugoe.cs.util.console.Console;
[439]32
33/**
[1146]34 * TODO update comment
35 *
[809]36 * <p>
37 * This class is responsible for applying temporal relationship rules on a task tree. Through this,
38 * a flat task tree is restructured to have more depth but to include more temporal relationships
[1146]39 * 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
[809]42 * this class.
43 * </p>
[1146]44 * <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
[809]47 * the following:
48 * <ol>
49 *   <li>
50 *     An instance of this class is created using the constructor and calling the
51 *     {@link #init()} method afterwards
52 *   </li>
53 *   <li>
[1146]54 *     then the {@link #applyRules(ITask, ITaskBuilder, ITaskFactory, boolean)}
55 *     method is called for a so far unstructured task
[809]56 *   </li>
57 *   <li>
58 *     the class iterates its internal list of rules and calls their
[1146]59 *     {@link ITaskInstanceListScopeRule#apply(ITask, ITaskBuilder, ITaskFactory, boolean)}
[809]60 *     method.
61 *   </li>
62 *   <li>
63 *     the class evaluates the rule application result
64 *     <ul>
65 *       <li>
66 *         if a rule returns a rule application result that is null, the next rule is tried
67 *       </li>
68 *       <li>
69 *         if a rule returns that it would be feasible if more data was available and the rule
70 *         application shall not be finalized (see finalize parameter of the applyRules method)
71 *         the rule application is broken up
72 *       </li>
73 *       <li>
74 *         if a rule returns, that it was applied, the same rule is applied again until it returns
[1146]75 *         null or feasible. For each newly created parent task provided in the rule application
76 *         result, the {@link #applyRules(ITask, ITaskBuilder, ITaskFactory, boolean)}
[809]77 *         method is called.
78 *       </li>
79 *     </ul>
80 *   </li>
81 * </ol>
[1146]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.
[809]84 * </p>
[439]85 *
[809]86 * @author Patrick Harms
[439]87 */
[557]88public class TemporalRelationshipRuleManager {
89   
[809]90    /**
91     * <p>
[1146]92     * the task equality manager needed by the rules to compare tasks with each other
[809]93     * </p>
94     */
[1146]95    private TaskEqualityRuleManager taskEqualityRuleManager;
[439]96
[809]97    /**
98     * <p>
[1146]99     * the task factory to be used during rule application
[809]100     * </p>
101     */
[1146]102    private ITaskFactory taskFactory;
[439]103
[557]104    /**
[809]105     * <p>
[1146]106     * the task builder to be used during rule application
[809]107     * </p>
[557]108     */
[1146]109    private ITaskBuilder taskBuilder;
[1107]110
111    /**
112     * <p>
[1146]113     * the temporal relationship rules known to the manager that are executed on whole sessions.
[1107]114     * The rules are applied in the order they occur in this list.
115     * </p>
116     */
[1146]117    private ISessionScopeRule[] sessionScopeRules;
[1107]118
119    /**
120     * <p>
121     * the temporal relationship rules known to the manager that are executed on whole sub trees.
122     * The rules are applied in the order they occur in this list.
123     * </p>
124     */
[1146]125    private ITaskInstanceListScopeRule[] taskScopeRules;
[1107]126
127    /**
128     * <p>
129     * initialize the manager
130     * </p>
131     *
[1146]132     * @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
[1107]137     *                                with each other during rule application
138     */
[1146]139    public TemporalRelationshipRuleManager(TaskEqualityRuleManager taskEqualityRuleManager,
140                                           ITaskFactory            taskFactory,
141                                           ITaskBuilder            taskBuilder)
[1107]142    {
[557]143        super();
[1146]144        this.taskEqualityRuleManager = taskEqualityRuleManager;
145        this.taskFactory = taskFactory;
146        this.taskBuilder = taskBuilder;
[557]147    }
[439]148
[557]149    /**
[809]150     * <p>
151     * initialized the temporal relationship rule manager by instantiating the known rules and
[1146]152     * providing them with a reference to the task equality manager or other information they need.
[809]153     * </p>
[557]154     */
155    public void init() {
[987]156        List<Class<? extends IGUIElement>> frameFilter =
157            new ArrayList<Class<? extends IGUIElement>>();
158        frameFilter.add(IFrame.class);
159        frameFilter.add(IDialog.class);
[1107]160        //frameFilter.add(ICanvas.class);
[987]161
[1146]162        sessionScopeRules = new ISessionScopeRule[] {
[1127]163            new SequenceForTaskDetectionRule
[1146]164                (taskEqualityRuleManager, TaskEquality.SEMANTICALLY_EQUAL,
165                 taskFactory, taskBuilder),
[1127]166            /*new DefaultTaskSequenceDetectionRule
[1146]167                (taskEqualityRuleManager, NodeEquality.SYNTACTICALLY_EQUAL,
168                 taskFactory, taskTreeBuilder),
[1107]169            new DefaultTaskSequenceDetectionRule
[1146]170                (taskEqualityRuleManager, NodeEquality.LEXICALLY_EQUAL,
171                 taskFactory, taskTreeBuilder),*/
[1127]172            /*new TreeScopeWrapperRule
173                (new DefaultIterationDetectionRule
[1146]174                    (taskEqualityRuleManager, NodeEquality.LEXICALLY_EQUAL,
175                     taskFactory, taskTreeBuilder)),
[1127]176            new TreeScopeWrapperRule
177                (new DefaultIterationDetectionRule
[1146]178                    (taskEqualityRuleManager, NodeEquality.SYNTACTICALLY_EQUAL,
179                     taskFactory, taskTreeBuilder)),
[1127]180            new TreeScopeWrapperRule
181                (new DefaultIterationDetectionRule
[1146]182                    (taskEqualityRuleManager, NodeEquality.SEMANTICALLY_EQUAL,
183                     taskFactory, taskTreeBuilder))*/
[1107]184        };
[805]185       
[1107]186        //treeScopeRules.add(new DefaultGuiElementSequenceDetectionRule(frameFilter));
187
[1146]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),
[1107]193        };
194
[557]195    }
[439]196
[557]197    /**
[809]198     * <p>
[1146]199     * 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
[1107]201     * is available and, therefore, finalizes the rule application.
202     * </p>
203     *
[1146]204     * @param taskFactory  the task factory to be used for instantiating new tasks.
[1107]205     */
[1146]206    public void applyRules(List<IUserSession> sessions) {
207        applyRules(sessionScopeRules, sessions, "");
[1107]208    }
209
210    /**
211     * <p>
[1146]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
[809]214     * rule application is finalized as far as possible without waiting for further data. If it is
215     * false, the rule application is broken up at the first rule returning, that its application
[1146]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.
[809]218     * </p>
[557]219     *
[1146]220     * @param parent       the parent task to apply the rules on
[809]221     * @param finalize     used to indicate, if the rule application shall break up if a rule would
222     *                     be feasible if further data was available, or not.
[1146]223     * @param logIndent    simply used for logging purposes to indent the log messages depending
224     *                     on the recursion depth of calling this method.
[557]225     */
[1146]226    private int applyRules(ISessionScopeRule[] rules,
227                           List<IUserSession>  sessions,
228                           String              logIndent)
229    {
230        Console.traceln
231            (Level.FINER, logIndent + "applying rules for " + sessions.size() + " sessions");
232
233        int noOfRuleApplications = 0;
234
235        for (ISessionScopeRule rule : rules) {
236            RuleApplicationResult result;
237            do {
238                Console.traceln(Level.FINER, logIndent + "trying rule " + rule);
239                result = rule.apply(sessions);
240
241                if ((result != null) &&
242                    (result.getRuleApplicationStatus() == RuleApplicationStatus.FINISHED))
243                {
244                    Console.traceln(Level.FINE, logIndent + "applied rule " + rule);
245                    noOfRuleApplications++;
246                   
247                    //dumpTask(parent, "");
248
249                    for (ITaskInstance newParent : result.getNewlyCreatedTaskInstances()) {
250                        noOfRuleApplications +=
251                            applyRules(taskScopeRules, newParent, logIndent + "  ");
252                    }
253                }
254            }
255            while ((result != null) &&
256                   (result.getRuleApplicationStatus() == RuleApplicationStatus.FINISHED));
257
258        }
259
260        if (noOfRuleApplications <= 0) {
261            Console.traceln(Level.FINE, logIndent + "no rules applied --> no temporal " +
262                            "relationship generated");
263        }
264
265        return noOfRuleApplications;
[439]266    }
[557]267
268    /**
[809]269     * <p>
[1146]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
[809]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
[1146]274     * would be feasible. The method calls itself for each parent task created through the rule
[809]275     * application. In this case, the finalize parameter is always true.
276     * </p>
[557]277     *
[1146]278     * @param parent       the parent task to apply the rules on
[809]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.
[987]281     * @param logIndent    simply used for logging purposes to indent the log messages depending
[809]282     *                     on the recursion depth of calling this method.
[557]283     */
[1146]284    private int applyRules(ITaskInstanceListScopeRule[] rules,
285                           ITaskInstanceList            taskInstances,
286                           String                       logIndent)
[439]287    {
[1146]288        Console.traceln(Level.FINER, logIndent + "applying rules for " + taskInstances.size() +
289                        " task instances");
[557]290
291        int noOfRuleApplications = 0;
292
[1146]293        for (ITaskInstanceListScopeRule rule : rules) {
[557]294            RuleApplicationResult result;
295            do {
[1146]296                Console.traceln
297                    (Level.FINER, logIndent + "trying rule " + rule + " on " + taskInstances);
298                result = rule.apply(taskInstances);
[557]299
300                if ((result != null) &&
[1127]301                    (result.getRuleApplicationStatus() == RuleApplicationStatus.FINISHED))
[557]302                {
[725]303                    Console.traceln
[1146]304                        (Level.FINE, logIndent + "applied rule " + rule + " on " + taskInstances);
[557]305                    noOfRuleApplications++;
[987]306                   
[1127]307                    //dumpTask(parent, "");
[557]308
[1146]309                    for (ITaskInstance newParent : result.getNewlyCreatedTaskInstances()) {
[557]310                        noOfRuleApplications +=
[1146]311                            applyRules(taskScopeRules, newParent, logIndent + "  ");
[557]312                    }
313                }
314            }
315            while ((result != null) &&
[1127]316                   (result.getRuleApplicationStatus() == RuleApplicationStatus.FINISHED));
[557]317        }
318
319        if (noOfRuleApplications <= 0) {
[1127]320            Console.traceln(Level.FINE, logIndent + "no rules applied --> no temporal " +
[725]321                            "relationship generated");
[557]322        }
323
324        return noOfRuleApplications;
[439]325    }
[557]326
327    /**
[809]328     *
329     */
[1146]330    /*private void dumpTask(ITask task, String indent) {
[987]331        StringBuffer message = new StringBuffer();
332        message.append(indent);
333        message.append(task);
334        if (task.getDescription() != null) {
335            message.append('(');
336            message.append(task.getDescription());
337            message.append(')');
338        }
339       
340        Console.traceln(Level.FINER, message.toString());
341       
342        if ((task.getChildren() != null) && (task.getChildren().size() > 0)) {
[1146]343            for (ITask child : task.getChildren()) {
[987]344                dumpTask(child, indent + "  ");
345            }
346        }
[1131]347    }*/
[439]348
349}
Note: See TracBrowser for help on using the repository browser.