source: trunk/autoquest-plugin-html/src/main/java/de/ugoe/cs/autoquest/plugin/html/HTMLLogParser.java @ 1093

Last change on this file since 1093 was 1093, checked in by pharms, 11 years ago
  • bugfix to correctly handle sessions without an included event
  • Property svn:mime-type set to text/plain
File size: 10.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.plugin.html;
16
17import java.util.List;
18import java.util.Map;
19import java.util.regex.Matcher;
20import java.util.regex.Pattern;
21
22import org.xml.sax.SAXException;
23
24import de.ugoe.cs.autoquest.eventcore.Event;
25import de.ugoe.cs.autoquest.eventcore.IEventType;
26import de.ugoe.cs.autoquest.eventcore.guimodel.GUIModel;
27import de.ugoe.cs.autoquest.eventcore.guimodel.GUIModelException;
28import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement;
29import de.ugoe.cs.autoquest.plugin.html.eventcore.HTMLEventTypeFactory;
30import de.ugoe.cs.autoquest.plugin.html.guimodel.HTMLDocumentSpec;
31import de.ugoe.cs.autoquest.plugin.html.guimodel.HTMLGUIElement;
32import de.ugoe.cs.autoquest.plugin.html.guimodel.HTMLGUIElementSpec;
33import de.ugoe.cs.autoquest.plugin.html.guimodel.HTMLPageElementSpec;
34import de.ugoe.cs.autoquest.plugin.html.guimodel.HTMLServerSpec;
35
36/**
37 * <p>
38 * This class provides the functionality to parse XML log files generated by the HTMLMonitor of
39 * AutoQUEST. The result of parsing a file is a collection of event sequences and a GUI model
40 * </p>
41 *
42 * @author Fabian Glaser, Patrick Harms
43 * @version 1.0
44 *
45 */
46public class HTMLLogParser extends AbstractDefaultLogParser {
47   
48    /**
49     *
50     */
51    private Pattern htmlElementPattern =
52        Pattern.compile("(\\w+)(\\[(\\d+)\\]|\\(htmlId=([\\w-]+)\\))");
53
54    /* (non-Javadoc)
55     * @see de.ugoe.cs.autoquest.plugin.html.AbstractDefaultLogParser#handleGUIElement(java.lang.String, java.util.Map)
56     */
57    @Override
58    protected boolean handleGUIElement(String id, Map<String, String> parameters)
59        throws SAXException
60    {
61        HTMLGUIElementSpec specification = null;
62       
63        String parentId = parameters.get("parent");
64        IGUIElement parent = super.getGUIElementTree().find(parentId);
65
66        if (parameters.containsKey("host")) {
67            // this is a server specification
68            int port = 80;
69            String portStr = parameters.get(port);
70           
71            if (portStr != null) {
72                port = Integer.parseInt(portStr);
73            }
74           
75            specification = new HTMLServerSpec(parameters.get("host"), port);
76        }
77        else if (parameters.containsKey("path")) {
78            // this is a document specification
79           
80            if (parent != null) {
81                if (!(parent.getSpecification() instanceof HTMLServerSpec)) {
82                    throw new SAXException
83                        ("invalid log: parent GUI element of a document is not of type server");
84                }
85               
86                specification = new HTMLDocumentSpec
87                    ((HTMLServerSpec) parent.getSpecification(), parameters.get("path"),
88                     parameters.get("query"), parameters.get("title"));
89            }
90            else if (parentId == null) {
91                throw new SAXException("invalid log: a document has no parent id");
92            }
93        }
94        else if (parameters.containsKey("tagname")) {
95            String tagName = parameters.get("tagname");
96           
97            if (!tagNameMustBeConsidered(tagName)) {
98                return true;
99            }
100
101            if (parent != null) {
102                IGUIElement document = parent;
103               
104                while ((document != null) &&
105                       (!(document.getSpecification() instanceof HTMLDocumentSpec)))
106                {
107                    document = document.getParent();
108                }
109               
110                if (document == null) {
111                    throw new SAXException
112                        ("invalid log: parent hierarchy of a page element does not contain a " +
113                         "document");
114                }
115               
116                int index = -1;
117                String indexStr = parameters.get("index");
118
119                if ((indexStr != null) && (!"".equals(indexStr))) {
120                    index = Integer.parseInt(indexStr);
121                }
122
123                specification = new HTMLPageElementSpec
124                    ((HTMLDocumentSpec) document.getSpecification(), tagName,
125                     parameters.get("htmlid"), index);
126            }
127            else if (parentId == null) {
128                throw new SAXException("invalid log: a page element has no parent id");
129            }
130        }
131        else {
132            throw new SAXException("invalid log: unknown GUI element");
133        }
134
135        if (specification != null) {
136            try {
137                super.getGUIElementTree().add(id, parentId, specification);
138            }
139            catch (GUIModelException e) {
140                throw new SAXException("could not handle GUI element with id " +
141                                       id + ": " + e.getMessage(), e);
142            }
143            return true;
144        }
145        else {
146            return false;
147        }
148    }
149
150    /* (non-Javadoc)
151     * @see de.ugoe.cs.autoquest.plugin.html.AbstractDefaultLogParser#handleEvent(java.lang.String, java.util.Map)
152     */
153    @Override
154    protected boolean handleEvent(String type, Map<String, String> parameters) throws SAXException {
155        String targetId = parameters.get("target");
156       
157        if (targetId == null) {
158            String targetDocument = parameters.get("targetDocument");
159            String targetDOMPath = parameters.get("targetDOMPath");
160           
161            if ((targetDocument == null) || (targetDOMPath == null)) {
162                throw new SAXException("event has no target defined");
163            }
164           
165            targetId = determineTargetId(targetDocument, targetDOMPath);
166           
167            if (targetId == null) {
168                // the target id can not be determined yet
169                return false;
170            }
171        }
172       
173        IGUIElement target = super.getGUIElementTree().find(targetId);
174       
175        if (target == null) {
176            // event not processible yet
177            return false;
178        }
179
180        IEventType eventType =
181            HTMLEventTypeFactory.getInstance().getEventType(type, parameters, target);
182       
183        if (eventType != null) {
184            Event event = new Event(eventType, target);
185
186            String timestampStr = parameters.get("timestamp");
187       
188            if (timestampStr != null) {
189                event.setTimestamp(Long.parseLong(timestampStr));
190            }
191
192            ((HTMLGUIElement) event.getTarget()).markUsed();
193       
194            super.addToSequence(event);
195        }
196        // else ignore unknown event type
197
198        return true;
199    }
200
201    /**
202     * <p>
203     * TODO: comment
204     * </p>
205     *
206     * @param targetDocument
207     * @param targetDOMPath
208     * @return
209     */
210    private String determineTargetId(String targetDocument, String targetDOMPath)
211        throws SAXException
212    {
213        IGUIElement document = super.getGUIElementTree().find(targetDocument);
214       
215        if (document == null) {
216            return null;
217        }
218       
219        if (!(document.getSpecification() instanceof HTMLDocumentSpec)) {
220            throw new SAXException("an id that should refer to an HTML document refers to" +
221                                   "something else");
222        }
223       
224        GUIModel model = super.getGUIElementTree().getGUIModel();
225        IGUIElement child = document;
226        String[] pathElements = targetDOMPath.split("/");
227        int pathIndex = 0;
228       
229        HTMLPageElementSpec compareSpec;
230        String tagName;
231        int index;
232        String htmlId;
233       
234        while ((pathIndex < pathElements.length) && (child != null)) {
235            if ((pathElements[pathIndex] != null) && (!"".equals(pathElements[pathIndex]))) {           
236                Matcher matcher = htmlElementPattern.matcher(pathElements[pathIndex]);
237                if (!matcher.matches()) {
238                    throw new SAXException
239                        ("could not parse target DOM path element " + pathElements[pathIndex]);
240                }
241
242                tagName = matcher.group(1);
243                String indexStr = matcher.group(3);
244                htmlId = matcher.group(4);
245
246                index = -1;
247                if ((indexStr != null) && (!"".equals(indexStr))) {
248                    index = Integer.parseInt(indexStr);
249                }
250
251                compareSpec = new HTMLPageElementSpec
252                    ((HTMLDocumentSpec) document.getSpecification(), tagName, htmlId, index);
253
254                List<IGUIElement> children = model.getChildren(child);
255                child = null;
256
257                for (IGUIElement candidate : children) {
258                    if (compareSpec.getSimilarity(candidate.getSpecification())) {
259                        child = candidate;
260                        break;
261                    }
262                }
263            }
264           
265            pathIndex++;
266        }
267       
268        if (child != null) {
269            return super.getGUIElementTree().find(child);
270        }
271        else {
272            return null;
273        }
274    }
275
276    /**
277     * <p>
278     * checks if tags with the provided name must be handled in the GUI model. As an example,
279     * it is not necessary to handle "head" tags and anything included in them.
280     * </p>
281     *
282     * @param tagName
283     * @return
284     */
285    private boolean tagNameMustBeConsidered(String tagName) {
286        return
287            !"head".equals(tagName) && !"title".equals(tagName) && !"script".equals(tagName) &&
288            !"style".equals(tagName) && !"link".equals(tagName) && !"meta".equals(tagName) &&
289            !"iframe".equals(tagName) && !"input_hidden".equals(tagName) &&
290            !"option".equals(tagName) && !"tt".equals(tagName) && !"br".equals(tagName) &&
291            !"colgroup".equals(tagName) && !"col".equals(tagName);
292
293    }
294
295}
Note: See TracBrowser for help on using the repository browser.