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

Last change on this file since 1178 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
RevLine 
[1051]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.
[1047]14
15package de.ugoe.cs.autoquest.plugin.html;
16
17import java.util.List;
18import java.util.Map;
[1069]19import java.util.regex.Matcher;
20import java.util.regex.Pattern;
[1047]21
22import org.xml.sax.SAXException;
23
24import de.ugoe.cs.autoquest.eventcore.Event;
[1059]25import de.ugoe.cs.autoquest.eventcore.IEventType;
[1047]26import de.ugoe.cs.autoquest.eventcore.guimodel.GUIModel;
[1084]27import de.ugoe.cs.autoquest.eventcore.guimodel.GUIModelException;
[1047]28import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement;
29import de.ugoe.cs.autoquest.plugin.html.eventcore.HTMLEventTypeFactory;
[1069]30import de.ugoe.cs.autoquest.plugin.html.guimodel.HTMLDocumentSpec;
[1047]31import de.ugoe.cs.autoquest.plugin.html.guimodel.HTMLGUIElement;
32import de.ugoe.cs.autoquest.plugin.html.guimodel.HTMLGUIElementSpec;
[1059]33import de.ugoe.cs.autoquest.plugin.html.guimodel.HTMLPageElementSpec;
34import de.ugoe.cs.autoquest.plugin.html.guimodel.HTMLServerSpec;
[1047]35
36/**
37 * <p>
38 * This class provides the functionality to parse XML log files generated by the HTMLMonitor of
[1069]39 * AutoQUEST. The result of parsing a file is a collection of event sequences and a GUI model
[1047]40 * </p>
41 *
[1069]42 * @author Fabian Glaser, Patrick Harms
[1047]43 * @version 1.0
44 *
45 */
[1069]46public class HTMLLogParser extends AbstractDefaultLogParser {
47   
[1047]48    /**
[1069]49     *
[1047]50     */
[1069]51    private Pattern htmlElementPattern =
52        Pattern.compile("(\\w+)(\\[(\\d+)\\]|\\(htmlId=([\\w-]+)\\))");
[1047]53
[1069]54    /* (non-Javadoc)
55     * @see de.ugoe.cs.autoquest.plugin.html.AbstractDefaultLogParser#handleGUIElement(java.lang.String, java.util.Map)
[1047]56     */
[1069]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);
[1059]65
[1069]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);
[1047]76        }
[1069]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");
[1059]84                }
[1069]85               
86                specification = new HTMLDocumentSpec
87                    ((HTMLServerSpec) parent.getSpecification(), parameters.get("path"),
88                     parameters.get("query"), parameters.get("title"));
[1059]89            }
[1069]90            else if (parentId == null) {
91                throw new SAXException("invalid log: a document has no parent id");
[1059]92            }
[1069]93        }
94        else if (parameters.containsKey("tagname")) {
95            String tagName = parameters.get("tagname");
96           
97            if (!tagNameMustBeConsidered(tagName)) {
98                return true;
[1059]99            }
[1047]100
[1069]101            if (parent != null) {
102                IGUIElement document = parent;
103               
104                while ((document != null) &&
105                       (!(document.getSpecification() instanceof HTMLDocumentSpec)))
106                {
107                    document = document.getParent();
[1047]108                }
[1069]109               
110                if (document == null) {
111                    throw new SAXException
112                        ("invalid log: parent hierarchy of a page element does not contain a " +
113                         "document");
[1047]114                }
[1069]115               
116                int index = -1;
117                String indexStr = parameters.get("index");
118
119                if ((indexStr != null) && (!"".equals(indexStr))) {
120                    index = Integer.parseInt(indexStr);
[1047]121                }
[1069]122
123                specification = new HTMLPageElementSpec
124                    ((HTMLDocumentSpec) document.getSpecification(), tagName,
125                     parameters.get("htmlid"), index);
[1047]126            }
[1069]127            else if (parentId == null) {
128                throw new SAXException("invalid log: a page element has no parent id");
[1047]129            }
130        }
[1059]131        else {
[1069]132            throw new SAXException("invalid log: unknown GUI element");
[1047]133        }
134
[1069]135        if (specification != null) {
[1084]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            }
[1069]143            return true;
144        }
145        else {
146            return false;
147        }
[1047]148    }
149
[1069]150    /* (non-Javadoc)
151     * @see de.ugoe.cs.autoquest.plugin.html.AbstractDefaultLogParser#handleEvent(java.lang.String, java.util.Map)
[1051]152     */
[1047]153    @Override
[1069]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");
[1047]163            }
[1069]164           
165            targetId = determineTargetId(targetDocument, targetDOMPath);
166           
167            if (targetId == null) {
168                // the target id can not be determined yet
169                return false;
170            }
[1047]171        }
[1069]172       
173        IGUIElement target = super.getGUIElementTree().find(targetId);
174       
175        if (target == null) {
[1093]176            // event not processible yet
[1069]177            return false;
[1047]178        }
[1059]179
[1069]180        IEventType eventType =
181            HTMLEventTypeFactory.getInstance().getEventType(type, parameters, target);
182       
[1084]183        if (eventType != null) {
184            Event event = new Event(eventType, target);
[1059]185
[1084]186            String timestampStr = parameters.get("timestamp");
[1069]187       
[1084]188            if (timestampStr != null) {
189                event.setTimestamp(Long.parseLong(timestampStr));
190            }
[1059]191
[1084]192            ((HTMLGUIElement) event.getTarget()).markUsed();
[1069]193       
[1084]194            super.addToSequence(event);
195        }
196        // else ignore unknown event type
[1059]197
[1069]198        return true;
[1047]199    }
[1059]200
[1047]201    /**
202     * <p>
[1069]203     * TODO: comment
[1047]204     * </p>
[1069]205     *
206     * @param targetDocument
207     * @param targetDOMPath
[1047]208     * @return
209     */
[1069]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        }
[1047]274    }
[1059]275
[1047]276    /**
277     * <p>
[1069]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.
[1047]280     * </p>
[1069]281     *
282     * @param tagName
[1059]283     * @return
284     */
[1069]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);
[1059]292
[1069]293    }
[1059]294
[1047]295}
Note: See TracBrowser for help on using the repository browser.