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

Last change on this file since 1059 was 1059, checked in by fglaser, 11 years ago
  • Further works on NewHTMLLogParser to parse testtrace without errors
  • Test for NewHTMLLogParser added
  • dummy mapping for html added that contains unmapped elements
  • Property svn:mime-type set to text/plain
File size: 13.5 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.io.File;
18import java.io.FileInputStream;
19import java.io.FileNotFoundException;
20import java.io.IOException;
21import java.io.InputStreamReader;
22import java.io.UnsupportedEncodingException;
23import java.util.Collection;
24import java.util.HashMap;
25import java.util.LinkedList;
26import java.util.List;
27import java.util.Map;
28
29import javax.xml.parsers.ParserConfigurationException;
30import javax.xml.parsers.SAXParser;
31import javax.xml.parsers.SAXParserFactory;
32
33import org.xml.sax.Attributes;
34import org.xml.sax.InputSource;
35import org.xml.sax.SAXException;
36import org.xml.sax.SAXParseException;
37import org.xml.sax.helpers.DefaultHandler;
38
39import de.ugoe.cs.autoquest.eventcore.Event;
40import de.ugoe.cs.autoquest.eventcore.IEventType;
41import de.ugoe.cs.autoquest.eventcore.guimodel.GUIElementTree;
42import de.ugoe.cs.autoquest.eventcore.guimodel.GUIModel;
43import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement;
44import de.ugoe.cs.autoquest.plugin.html.eventcore.HTMLEventTypeFactory;
45import de.ugoe.cs.autoquest.plugin.html.guimodel.HTMLGUIElement;
46import de.ugoe.cs.autoquest.plugin.html.guimodel.HTMLGUIElementSpec;
47import de.ugoe.cs.autoquest.plugin.html.guimodel.HTMLPageElementSpec;
48import de.ugoe.cs.autoquest.plugin.html.guimodel.HTMLPageSpec;
49import de.ugoe.cs.autoquest.plugin.html.guimodel.HTMLServerSpec;
50import de.ugoe.cs.util.console.Console;
51
52/**
53 * <p>
54 * This class provides the functionality to parse XML log files generated by the HTMLMonitor of
55 * autoquest. The result of parsing a file is a collection of event sequences.
56 * </p>
57 *
58 * @author Fabian Glaser
59 * @version 1.0
60 *
61 */
62public class NewHTMLLogParser extends DefaultHandler {
63    /**
64     * <p>
65     * Constructor. Creates a new HTMLLogParser.
66     * </p>
67     */
68    public NewHTMLLogParser() {
69        sequences = new LinkedList<List<Event>>();
70    }
71
72    /**
73     * <p>
74     * Collection of event sequences that is contained in the parsed log file.
75     * </p>
76     */
77    private Collection<List<Event>> sequences;
78
79    /**
80     * <p>
81     * Internal handle to the parsed GUI structure, stored in a GUIElementTree
82     * </p>
83     */
84    private GUIElementTree<String> currentGUIElementTree;
85
86    /**
87     * <p>
88     * Path of the GUI element currently being parsed.
89     * </p>
90     */
91    private String currentGUIElementPath;
92
93    /**
94     * <p>
95     * Path of the parent of the GUI element currently being parsed.
96     * </p>
97     */
98    private String currentParentPath;
99
100    /**
101     * <p>
102     * Source of the GUI element currently being parsed.
103     * </p>
104     */
105    private String currentEventSource;
106
107    /**
108     * <p>
109     * Timestamp of the event currently being parsed.
110     * </p>
111     */
112    private Long currentEventTimestamp;
113
114    /**
115     * <p>
116     * Internal handle to the parameters of the event currently being parsed.
117     * </p>
118     */
119    private Map<String, String> currentEventParameters;
120
121    /**
122     * <p>
123     * Internal handle to the parameters of the GUI element currently being parsed.
124     * </p>
125     */
126    private Map<String, String> currentGUIElementParameters;
127    /**
128     * <p>
129     * Internal handle to the sequence currently being parsed.
130     * </p>
131     */
132    private List<Event> currentSequence;
133
134    /**
135     * <p>
136     * Internal handle to type of the event currently being parsed.
137     * </p>
138     */
139    private String currentEventType;
140
141    /**
142     * <p>
143     * Class of the GUI element currently being parsed.
144     * </p>
145     */
146    private String currentGUIElementClass;
147
148    /**
149     * <p>
150     * Index of the GUI element currently being parsed.
151     * </p>
152     */
153    private String currentGUIElementIndex;
154
155    /**
156     * <p>
157     * internal handle to the GUI element of the previous event to be potentially reused for the
158     * current
159     * </p>
160     */
161    private IGUIElement lastGUIElement;
162
163    /**
164     * <p>
165     * internal handle to the server specification currently being used.
166     * </p>
167     */
168    private HTMLServerSpec currentServerSpec;
169
170    /**
171     * <p>
172     * Parses a log file written by the HTMLMonitor and creates a collection of event sequences.
173     * </p>
174     *
175     * @param filename
176     *            name and path of the log file
177     */
178    public void parseFile(String filename) {
179        if (filename == null) {
180            throw new IllegalArgumentException("filename must not be null");
181        }
182
183        parseFile(new File(filename));
184    }
185
186    /**
187     * <p>
188     * Parses a log file written by the HTMLMonitor and creates a collection of event sequences.
189     * </p>
190     *
191     * @param file
192     *            file to be parsed
193     */
194    public void parseFile(File file) {
195        if (file == null) {
196            throw new IllegalArgumentException("file must not be null");
197        }
198        SAXParserFactory spf = SAXParserFactory.newInstance();
199        spf.setValidating(true);
200        SAXParser saxParser = null;
201        InputSource inputSource = null;
202        try {
203            saxParser = spf.newSAXParser();
204            inputSource =
205                new InputSource(new InputStreamReader(new FileInputStream(file), "UTF-8"));
206        }
207        catch (UnsupportedEncodingException e) {
208            Console.printerr("Error parsing file " + file.getName());
209            Console.logException(e);
210            return;
211        }
212        catch (ParserConfigurationException e) {
213            Console.printerr("Error parsing file " + file.getName());
214            Console.logException(e);
215            return;
216        }
217        catch (SAXException e) {
218            Console.printerr("Error parsing file " + file.getName());
219            Console.logException(e);
220        }
221        catch (FileNotFoundException e) {
222            Console.printerr("Error parsing file " + file.getName());
223            Console.logException(e);
224        }
225        if (inputSource != null) {
226            inputSource.setSystemId("file://" + file.getAbsolutePath());
227            try {
228                if (saxParser == null) {
229                    throw new RuntimeException("SaxParser creation failed");
230                }
231                saxParser.parse(inputSource, this);
232            }
233            catch (SAXParseException e) {
234                Console.printerrln("Failure parsing file in line " + e.getLineNumber() +
235                    ", column " + e.getColumnNumber() + ".");
236                Console.logException(e);
237            }
238            catch (SAXException e) {
239                Console.printerr("Error parsing file " + file.getName());
240                Console.logException(e);
241                return;
242            }
243            catch (IOException e) {
244                Console.printerr("Error parsing file " + file.getName());
245                Console.logException(e);
246                return;
247            }
248        }
249    }
250
251    /*
252     * (non-Javadoc)
253     *
254     * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String,
255     * java.lang.String, org.xml.sax.Attributes)
256     */
257    @Override
258    public void startElement(String uri, String localName, String qName, Attributes atts)
259        throws SAXException
260    {
261        if (qName.equals("session")) {
262            currentSequence = new LinkedList<Event>();
263            if (currentGUIElementTree == null)
264                currentGUIElementTree = new GUIElementTree<String>();
265        }
266        else if (qName.equals("component")) {
267            currentGUIElementPath = atts.getValue("path");
268            currentGUIElementParameters = new HashMap<String, String>();
269        }
270        else if (qName.equals("event")) {
271            currentEventType = atts.getValue("type");
272            currentEventParameters = new HashMap<String, String>();
273        }
274        else if (qName.equals("param")) {
275            String paramName = atts.getValue("name");
276            if (currentGUIElementPath != null) {
277                if ("parent".equals(paramName)) {
278                    currentParentPath = atts.getValue("value");
279                }
280                if ("class".equals(paramName)) {
281                    currentGUIElementClass = atts.getValue("value");
282                }
283                if ("index".equals(paramName)) {
284                    currentGUIElementIndex = atts.getValue("value");
285                }
286                currentGUIElementParameters.put(paramName, atts.getValue("value"));
287            }
288            else if (currentEventType != null) {
289                if ("target".equals(paramName)) {
290                    currentEventSource = atts.getValue("value");
291                }
292                if ("timestamp".equals(paramName)) {
293                    currentEventTimestamp = Long.parseLong(atts.getValue("value"));
294                }
295                currentEventParameters.put(paramName, atts.getValue("value"));
296            }
297            else {
298                throw new SAXException("param tag found where it should not be.");
299            }
300        }
301        else {
302            throw new SAXException("unknown tag found: " + qName);
303        }
304
305    }
306
307    /*
308     * (non-Javadoc)
309     *
310     * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String,
311     * java.lang.String)
312     */
313    @Override
314    public void endElement(String uri, String localName, String qName) throws SAXException {
315        if (qName.equals("session")) {
316            if (currentSequence != null && !currentSequence.isEmpty()) {
317                sequences.add(currentSequence);
318            }
319            currentSequence = null;
320        }
321        else if (qName.equals("component") && currentGUIElementPath != null) {
322            HTMLGUIElementSpec guiElementSpec =
323                getGUIElementSpec(currentGUIElementClass, currentGUIElementParameters);
324            currentGUIElementTree.add(currentGUIElementPath, currentParentPath, guiElementSpec);
325
326            currentParentPath = null;
327            currentGUIElementPath = null;
328            currentGUIElementParameters = null;
329        }
330        else if (qName.equals("event")) {
331            IGUIElement currentGUIElement;
332            currentGUIElement = currentGUIElementTree.find(currentEventSource);
333
334            IEventType eventType =
335                HTMLEventTypeFactory.getInstance().getEventType(currentEventType,
336                                                                currentEventParameters,
337                                                                currentGUIElement);
338            Event event =
339                new Event(eventType, (currentGUIElement == null ? lastGUIElement
340                    : currentGUIElement));
341
342            event.setTimestamp(currentEventTimestamp);
343            HTMLGUIElement currentEventTarget = (HTMLGUIElement) event.getTarget();
344            currentEventTarget.markUsed();
345            currentSequence.add(event);
346
347            currentEventSource = null;
348            currentEventTimestamp = -1l;
349            currentEventParameters = null;
350            currentEventType = null;
351
352            if (currentGUIElement != null) {
353                lastGUIElement = currentGUIElement;
354            }
355
356            currentGUIElement = null;
357        }
358    }
359
360    /**
361     * <p>
362     * Returns a collection of event sequences that was obtained from parsing log files.
363     * </p>
364     *
365     * @return
366     */
367    public Collection<List<Event>> getSequences() {
368        return sequences;
369    }
370
371    /**
372     * <p>
373     * Returns the GUI model that is obtained from parsing log files.
374     * </p>
375     *
376     * @return GUIModel
377     */
378    public GUIModel getGuiModel() {
379        return currentGUIElementTree.getGUIModel();
380    }
381
382    /**
383     * Returns the HTMLGUIElementSpecification for a GUI Element described
384     * by its class name and its parameters.
385     * @param guiElementClass
386     * @param guiElementParameters
387     * @return
388     */
389    private HTMLGUIElementSpec getGUIElementSpec(String guiElementClass,
390                                                 Map<String, String> guiElementParameters)
391    {
392        HTMLGUIElementSpec specification = null;
393        if ("server".equals(guiElementClass)) {
394            // TODO: add correct port handling
395            specification = new HTMLServerSpec(guiElementParameters.get("htmlId"), 0);
396            currentServerSpec = (HTMLServerSpec) specification;
397        }
398
399        else {
400            String id = guiElementParameters.get("htmlId");
401            if (id == null) {
402                HTMLPageElementSpec parentSpec =
403                    (HTMLPageElementSpec) currentGUIElementTree.find(currentParentPath)
404                        .getSpecification();
405                id = parentSpec.getPage().getPagePath();
406            }
407
408            int index = -1;
409            String indexStr = guiElementParameters.get("index");
410
411            if ((indexStr != null) && (!"".equals(indexStr))) {
412                index = Integer.parseInt(indexStr);
413            }
414            String title = guiElementParameters.get("title");
415            HTMLPageSpec page = new HTMLPageSpec(currentServerSpec, id, title);
416            specification = new HTMLPageElementSpec(page, guiElementClass, id, index);
417        }
418
419        return specification;
420    }
421}
Note: See TracBrowser for help on using the repository browser.