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

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