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

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