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

Last change on this file since 1062 was 1062, checked in by pharms, 11 years ago
  • moving to new version of the HTLM plugin
File size: 14.2 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.BufferedReader;
18import java.io.File;
19import java.io.FileInputStream;
20import java.io.FileNotFoundException;
21import java.io.IOException;
22import java.io.InputStreamReader;
23import java.net.MalformedURLException;
24import java.net.URL;
25import java.util.ArrayList;
26import java.util.Collection;
27import java.util.List;
28import java.util.logging.Level;
29import java.util.regex.Matcher;
30import java.util.regex.Pattern;
31
32import de.ugoe.cs.autoquest.eventcore.Event;
33import de.ugoe.cs.autoquest.eventcore.gui.DialogClose;
34import de.ugoe.cs.autoquest.eventcore.gui.DialogOpen;
35import de.ugoe.cs.autoquest.eventcore.gui.IInteraction;
36import de.ugoe.cs.autoquest.eventcore.gui.KeyboardFocusChange;
37import de.ugoe.cs.autoquest.eventcore.gui.MouseButtonInteraction;
38import de.ugoe.cs.autoquest.eventcore.gui.MouseClick;
39import de.ugoe.cs.autoquest.eventcore.gui.Scroll;
40import de.ugoe.cs.autoquest.eventcore.gui.TextInput;
41import de.ugoe.cs.autoquest.eventcore.guimodel.GUIElementFactory;
42import de.ugoe.cs.autoquest.eventcore.guimodel.GUIModel;
43import de.ugoe.cs.autoquest.eventcore.guimodel.GUIModelException;
44import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement;
45import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElementSpec;
46import de.ugoe.cs.autoquest.eventcore.guimodel.ITextArea;
47import de.ugoe.cs.autoquest.eventcore.guimodel.ITextField;
48import de.ugoe.cs.autoquest.plugin.html.guimodel.HTMLPageElementSpec;
49import de.ugoe.cs.autoquest.plugin.html.guimodel.HTMLPageSpec;
50import de.ugoe.cs.util.FileTools;
51import de.ugoe.cs.util.console.Console;
52
53/**
54 * <p>
55 * TODO comment
56 * </p>
57 *
58 * @author Patrick Harms
59 */
60public class OldHTMLLogParser {
61
62    /**
63     * <p>
64     * Name and path of the robot filter.
65     * </p>
66     */
67    private static final String ROBOTFILTERFILE = "data/robots/robotfilter.txt";
68
69    /**
70     * <p>
71     * Field that contains a regular expression that matches all robots
72     * contained in {@link #ROBOTFILTERFILE}.
73     * </p>
74     */
75    private String robotRegex = null;
76
77    /**
78     *
79     */
80    private Pattern htmlElementPattern = Pattern.compile("(\\w+)(\\[(\\d+)\\]|\\(id=([\\w-]+)\\))");
81
82    /**
83     *
84     */
85    private List<List<Event>> sequences = new ArrayList<List<Event>>();
86   
87    /**
88     *
89     */
90    private GUIModel guiModel = new GUIModel();
91   
92    /**
93     * <p>
94     * TODO: comment
95     * </p>
96     *
97     * @param source
98     */
99    public void parseFile(String source) throws IllegalArgumentException {
100        if (source == null) {
101            throw new IllegalArgumentException("source must not be null");
102        }
103
104        parseFile(new File(source));
105    }
106
107    /**
108     * <p>
109     * TODO: comment
110     * </p>
111     *
112     * @param source
113     */
114    public void parseFile(File source) throws IllegalArgumentException {
115        if (source == null) {
116            throw new IllegalArgumentException("source must not be null");
117        }
118        else if (!source.exists()) {
119            throw new IllegalArgumentException("source file does not exist");
120        }
121        else if (!source.isFile()) {
122            throw new IllegalArgumentException("source is not a file");
123        }
124
125        BufferedReader reader = null;
126       
127        try {
128            reader =
129                new BufferedReader(new InputStreamReader(new FileInputStream(source), "UTF-8"));
130       
131            loadRobotRegex();
132
133            List<Event> sequence = new ArrayList<Event>();
134
135            int lineCounter = 0;
136            String line = reader.readLine();
137            while ((line != null) && (!"".equals(line))) {
138                lineCounter++;
139                String[] values = line.substring(1, line.length() - 1).split("\" \"");
140
141                String clientId = values[0];
142                long timestamp = Long.parseLong(values[1]);
143                String title = values[2];
144                String uriString = values[3];
145                String agent = values[4];
146                String eventName = values[5];
147                String htmlElementPath = values[6];
148
149                List<String> eventParameters = null;
150                if (values.length > 7) {
151                    eventParameters = new ArrayList<String>();
152
153                    for (int i = 7; i < values.length; i++) {
154                        eventParameters.add(values[i]);
155                    }
156                }
157               
158                if (isRobot(agent)) {
159                    // do not handle sessions of robots
160                    Console.println("ignoring robot session: " + agent);
161                    break;
162                }
163               
164               
165                try {
166                    URL url = new URL(uriString);
167                    IGUIElement guiElement = getGUIElement(url, title, htmlElementPath);
168                    IInteraction interaction =
169                        getInteraction(eventName, guiElement, eventParameters);
170                   
171                    if (interaction != null) {
172                        Event event =
173                            createEvent(clientId, interaction, guiElement, timestamp, agent);
174                        sequence.add(event);
175                    }
176                }
177                catch (MalformedURLException e) {
178                    Console.traceln(Level.FINE, "Ignored line " + lineCounter + ": " +
179                                    e.getMessage());
180                }
181               
182                line = reader.readLine();
183            }
184           
185            Console.traceln(Level.INFO, "read user sequence with " + sequence.size() +
186                            " events from " + source);
187           
188            sequences.add(sequence);
189        }
190        catch (Exception e) {
191            Console.printerrln("could not parse file " + source + ": " + e);
192            e.printStackTrace();
193        }
194    }
195
196    /**
197     * <p>
198     * TODO: comment
199     * </p>
200     *
201     * @return
202     */
203    public Collection<List<Event>> getSequences() {
204        return sequences;
205    }
206
207    /**
208     * <p>
209     * TODO: comment
210     * </p>
211     *
212     * @return
213     */
214    public GUIModel getGuiModel() {
215        return guiModel;
216    }
217
218    /**
219     * <p>
220     * Reads {@link #ROBOTFILTERFILE} and creates a regular expression that
221     * matches all the robots defined in the file. The regular expression is
222     * stored in the field {@link #robotRegex}.
223     * </p>
224     *
225     * @throws IOException
226     *             thrown if there is a problem reading the robot filter
227     * @throws FileNotFoundException
228     *             thrown if the robot filter is not found
229     */
230    private void loadRobotRegex() throws IOException, FileNotFoundException {
231        String[] lines = FileTools.getLinesFromFile(ROBOTFILTERFILE);
232        StringBuilder regex = new StringBuilder();
233        for (int i = 0; i < lines.length; i++) {
234            regex.append("(.*" + lines[i] + ".*)");
235            if (i != lines.length - 1) {
236                regex.append('|');
237            }
238        }
239        robotRegex = regex.toString();
240    }
241
242    /**
243     * <p>
244     * TODO: comment
245     * </p>
246     *
247     * @param htmlElementPath
248     * @return
249     * @throws GUIModelException
250     * @throws 
251     */
252    private IGUIElement getGUIElement(URL url, String title, String htmlElementPath)
253        throws GUIModelException
254    {
255        String[] pathElements = htmlElementPath.split("/");
256        List<IGUIElementSpec> guiElementPath = new ArrayList<IGUIElementSpec>();
257       
258        HTMLPageSpec page = new HTMLPageSpec(url, title);
259       
260        guiElementPath.add(page.getServer());
261        guiElementPath.add(page);
262       
263        for (String pathElement : pathElements) {
264            if ((pathElement != null) && (!"".equals(pathElement))) {           
265                Matcher matcher = htmlElementPattern.matcher(pathElement);
266                if (!matcher.matches()) {
267                    throw new IllegalArgumentException("could not parse HTML element " + pathElement);
268                }
269
270                String type = matcher.group(1);
271                String indexStr = matcher.group(3);
272                String id = matcher.group(4);
273
274                int index = -1;
275
276                if ((indexStr != null) && (!"".equals(indexStr))) {
277                    index = Integer.parseInt(indexStr);
278                }
279
280                guiElementPath.add(new HTMLPageElementSpec(page, type, id, index));
281            }
282        }
283       
284        return guiModel.integratePath(guiElementPath, GUIElementFactory.getInstance());
285    }
286
287    /**
288     * <p>
289     * TODO: comment
290     * </p>
291     *
292     * @param eventName
293     * @param guiElement
294     * @param eventParameters
295     * @return
296     */
297    private IInteraction getInteraction(String       eventName,
298                                        IGUIElement  guiElement,
299                                        List<String> eventParameters)
300    {
301        IInteraction result = null;
302       
303        if ("onclick".equals(eventName)) {
304            int[] coordinates =
305                getCoordinateParameter(eventName, eventParameters, 0, "click coordinates");
306            result = new MouseClick
307                (MouseButtonInteraction.Button.LEFT, coordinates[0], coordinates[1]);
308        }
309        else if ("onfocus".equals(eventName)) {
310            result = new KeyboardFocusChange();
311        }
312        else if ("onscroll".equals(eventName)) {
313            int[] coordinates =
314                getCoordinateParameter(eventName, eventParameters, 0, "click coordinates");
315            result = new Scroll(coordinates[0], coordinates[1]);
316        }
317        else if ("onchange".equals(eventName)) {
318            String value = getStringParameter(eventName, eventParameters, 0, "selected value");
319           
320            if ((guiElement instanceof ITextArea) || (guiElement instanceof ITextField)) {
321                result = new TextInput(value, null);
322            }
323            else {
324                throw new IllegalArgumentException("can not handle onchange events on GUI " +
325                                                   "elements of type " + guiElement.getClass());
326            }
327        }
328        else if ("onload".equals(eventName)) {
329            result = new DialogOpen();
330        }
331        else if ("onunload".equals(eventName)) {
332            result = new DialogClose();
333        }
334        else if ("onbeforeunload".equals(eventName) ||
335                 "onpagehide".equals(eventName) ||
336                 "onpageshow".equals(eventName))
337        {
338            Console.traceln(Level.FINE, "Ignored event name \"" + eventName + "\"");
339        }
340        else {
341            throw new IllegalArgumentException("unknown event name: \"" + eventName + "\"");
342        }
343       
344        return result;
345    }
346
347    /**
348     * <p>
349     * TODO: comment
350     * </p>
351     *
352     * @param clientId
353     * @param interaction
354     * @param guiElement
355     * @param timestamp
356     * @param agent
357     * @return
358     */
359    private Event createEvent(String       clientId,
360                              IInteraction interaction,
361                              IGUIElement  guiElement,
362                              long         timestamp,
363                              String       agent)
364    {
365        Event event = new Event(interaction, guiElement);
366        event.setParameter("clientId", clientId);
367        event.setParameter("agent", agent);
368       
369        event.setTimestamp(timestamp);
370       
371        return event;
372    }
373
374    /**
375     * <p>
376     * TODO: comment
377     * </p>
378     *
379     * @param eventName
380     * @param eventParameters
381     * @param i
382     * @param string
383     * @return
384     */
385    private String getStringParameter(String       eventName,
386                                      List<String> eventParameters,
387                                      int          parameterIndex,
388                                      String       parameterDesc)
389        throws IllegalArgumentException
390    {
391        String value =
392            eventParameters.size() > parameterIndex ? eventParameters.get(parameterIndex) : null;
393       
394        if (value == null) {
395            throw new IllegalArgumentException
396                (eventName + " event does not provide the " + parameterDesc);
397        }
398       
399        return value;
400    }
401
402    /**
403     * <p>
404     * TODO: comment
405     * </p>
406     *
407     * @param eventName
408     * @param eventParameters
409     * @return
410     */
411    private int[] getCoordinateParameter(String       eventName,
412                                         List<String> eventParameters,
413                                         int          parameterIndex,
414                                         String       parameterDesc)
415    {
416        String value =
417            getStringParameter(eventName, eventParameters, parameterIndex, parameterDesc);
418       
419        String[] intStrs = value.split(",");
420       
421        if ((intStrs == null) || (intStrs.length != 2)) {
422            throw new IllegalArgumentException("the " + parameterDesc + " of an " + eventName +
423                                               " event does not provide two correct coordinates");
424        }
425       
426        try {
427            return new int[] { Integer.parseInt(intStrs[0]), Integer.parseInt(intStrs[1]) };
428        }
429        catch (NumberFormatException e) {
430            throw new IllegalArgumentException("the coordinates provided as " + parameterDesc +
431                                               " of an " + eventName + " event are no numbers");
432        }
433    }
434
435    /**
436     * <p>
437     * Checks whether an agent is a robot.
438     * </p>
439     *
440     * @param agent
441     *            agent that is checked
442     * @return true, if the agent is a robot; false otherwise
443     */
444    private boolean isRobot(String agent) {
445        return agent.matches(robotRegex);
446    }
447
448}
Note: See TracBrowser for help on using the repository browser.