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

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