Index: /trunk/autoquest-plugin-jfc/src/main/java/de/ugoe/cs/autoquest/plugin/android/AndroidLogParser.java
===================================================================
--- /trunk/autoquest-plugin-jfc/src/main/java/de/ugoe/cs/autoquest/plugin/android/AndroidLogParser.java	(revision 1755)
+++ /trunk/autoquest-plugin-jfc/src/main/java/de/ugoe/cs/autoquest/plugin/android/AndroidLogParser.java	(revision 1755)
@@ -0,0 +1,301 @@
+//   Copyright 2014 Georg-August-Universität Göttingen, Germany
+//
+//   Licensed under the Apache License, Version 2.0 (the "License");
+//   you may not use this file except in compliance with the License.
+//   You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+//   Unless required by applicable law or agreed to in writing, software
+//   distributed under the License is distributed on an "AS IS" BASIS,
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//   See the License for the specific language governing permissions and
+//   limitations under the License.
+package de.ugoe.cs.autoquest.plugin.android;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import de.ugoe.cs.autoquest.eventcore.Event;
+import de.ugoe.cs.autoquest.eventcore.guimodel.GUIElementTree;
+import de.ugoe.cs.autoquest.eventcore.guimodel.GUIModel;
+import de.ugoe.cs.autoquest.eventcore.guimodel.GUIModelException;
+import de.ugoe.cs.autoquest.plugin.android.guimodel.AndroidGUIElementSpec;
+import de.ugoe.cs.util.console.Console;
+
+/**
+ * <p>
+ * This class provides functionality to parse XML log files generated by the AndroidMonitor of
+ * autoquest. The result of parsing a file is a collection of event sequences.
+ * </p>
+ * 
+ * @author Florian Unger
+ * @version 1.0
+ */
+public class AndroidLogParser extends DefaultHandler{
+	
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * int java.lang.Object.hashCode() is used in the Androidmonitor
+	 * Long is used to internally handle and compare the number. e.g. 
+	 * currentGUIElementHash != null
+	 * */
+	/**
+     * 
+     * <p>
+     * Internal handle to the hashcode of the GUI element, that is currently parsed.
+     * </p>
+     */
+    private Long currentGUIElementHash;
+    
+	/**
+     * <p>
+     * internal handle to the parsed GUI structure, stored in a GUIElementTree
+     * </p>
+     */
+    private GUIElementTree<Long> currentGUIElementTree;
+    
+    /**
+     * <p>
+     * internal handle to the specification currently parsed for a GUI element
+     * </p>
+     */
+    private AndroidGUIElementSpec currentGUIElementSpec;
+    
+    /**
+     * 
+     * <p>
+     * Internal handle to the hashcode of the parent of the GUI element, that is currently parsed.
+     * </p>
+     */
+    private Long currentParentHash;
+    
+    /**
+     * <p>
+     * Internal handle to the event sequence that is currently being parsed.
+     * </p>
+     */
+  //  private List<Event> currentSequence;
+    
+	/**
+     * <p>
+     * Map that holds events that had no registered target GUI element during parsing. Keys are the
+     * IDs of the unregistered targets.
+     * </p>
+     */
+    private Map<Long, List<Event>> eventsWithoutTargets;
+    
+	/**
+     * <p>
+     * Collection of event sequences that is contained in the log file, which is parsed.
+     * </p>
+     */
+    private Collection<List<Event>> sequences;
+    
+	/**
+     * <p>
+     * Constructor. Creates a new AndroidLogParser.
+     * </p>
+     */
+	public AndroidLogParser(){
+		sequences = new LinkedList<List<Event>>();
+		//currentSequence = null;		
+	}
+	
+	// TODO create a constructor which creates a new AndroidLogParser with a specific event filter.
+	
+	/**
+     * <p>
+     * Parses a log file written by the JFCMonitor and creates a collection of event sequences.
+     * </p>
+     * 
+     * @param filename
+     *            name and path of the log file
+     */
+    public void parseFile(String filename) {
+        if (filename == null) {
+            throw new IllegalArgumentException("filename must not be null");
+        }
+
+        parseFile(new File(filename));
+    }
+    
+    /**
+     * <p>
+     * Parses a log file written by the JFCMonitor and creates a collection of event sequences.
+     * </p>
+     * 
+     * @param file
+     *            name and path of the log file
+     */
+    public void parseFile(File file) {
+    	if (file == null) {
+            throw new IllegalArgumentException("file must not be null");
+        }
+    	
+    	SAXParserFactory spf = SAXParserFactory.newInstance();
+    	//TODO Why? Ask Steffen on next meeting.
+        spf.setValidating(true);
+        
+        SAXParser saxParser = null;
+        InputSource inputSource = null;
+        try {
+        	saxParser = spf.newSAXParser();
+            inputSource =
+                new InputSource(new InputStreamReader(new FileInputStream(file), "UTF-8"));
+		}
+        catch (UnsupportedEncodingException e) {
+            Console.printerr("Error parsing file + " + file.getName());
+            Console.logException(e);
+            return;
+        }
+        catch (ParserConfigurationException e) {
+            Console.printerr("Error parsing file + " + file.getName());
+            Console.logException(e);
+            return;
+        }
+        catch (SAXException e) {
+            Console.printerr("Error parsing file + " + file.getName());
+            Console.logException(e);
+            return;
+        }
+        catch (FileNotFoundException e) {
+            Console.printerr("Error parsing file + " + file.getName());
+            Console.logException(e);
+            return;
+        }
+        if (inputSource != null) {
+        	inputSource.setSystemId("file://" + file.getAbsolutePath());
+        	try {
+        		// TODO Why is saxParser checked for a second time? It is checked in one of the catch blocks right above. http://docs.oracle.com/javase/7/docs/api/javax/xml/parsers/SAXParserFactory.html#newSAXParser()
+                if (saxParser == null) {
+                    throw new RuntimeException("SAXParser creation failed");
+                }
+                saxParser.parse(inputSource, this);
+            }
+            catch (SAXParseException e) {
+                Console.printerrln("Failure parsing file in line " + e.getLineNumber() +
+                    ", column " + e.getColumnNumber() + ".");
+                Console.logException(e);
+                return;
+            }
+            catch (SAXException e) {
+                Console.printerr("Error parsing file + " + file.getName());
+                Console.logException(e);
+                return;
+            }
+            catch (IOException e) {
+                Console.printerr("Error parsing file + " + file.getName());
+                Console.logException(e);
+                return;
+            }
+        }
+        if (!eventsWithoutTargets.isEmpty()) {
+            Console.printerr("Some events reference GUI elements that are not part of logfile. " +
+            		"These events have been parsed without target.");
+        }
+    }
+    
+    /**
+     * <p>
+     * Returns the collection of event sequences that is obtained from parsing log files.
+     * </p>
+     * 
+     * @return collection of event sequences
+     */
+    public Collection<List<Event>> getSequences() {
+        return sequences;
+    }
+    
+    /**
+     * <p>
+     * Returns the GUI model that is obtained from parsing log files.
+     * </p>
+     * 
+     * @return GUIModel
+     */
+    public GUIModel getGuiModel() {
+        return currentGUIElementTree.getGUIModel();
+    }
+    
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String,
+     * java.lang.String, org.xml.sax.Attributes)
+     */
+    public void startElement(String uri, String localName, String qName, Attributes atts)
+        throws SAXException
+    {
+    	if (qName.equals("sessions")) {
+          //  currentSequence = new LinkedList<Event>(); Up to know it is necessary to handle different sessions. All components are known before an event occurs.
+            if (currentGUIElementTree == null)
+                currentGUIElementTree = new GUIElementTree<Long>();
+        }
+    	
+    	if (qName.equals("component")) {
+    		currentGUIElementHash = Long.parseLong(atts.getValue("hash"));
+    		currentGUIElementSpec = new AndroidGUIElementSpec();
+    		currentGUIElementSpec.setHashCode((int) currentGUIElementHash.longValue());
+        }
+    	else if (qName.equals("event")) {
+    		// TODO
+    	}
+    	else if (qName.equals("param")) {
+    		if (currentGUIElementHash != null) {
+    			if ("class".equals(atts.getValue("name"))) {
+                    currentGUIElementSpec.setType(atts.getValue("value"));
+                }
+    			else if("path".equals(atts.getValue("name"))){
+    				currentGUIElementSpec.setPath(atts.getValue("value"));
+    			}
+    			else if ("parent".equals(atts.getValue("name"))) {
+                    currentParentHash = Long.parseLong(atts.getValue("value"), 16);
+                }
+    		}
+    		//TODO evaluate event values else if(currentEventId != null)
+    	}
+    }
+    
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String,
+     * java.lang.String)
+     */
+    @Override
+    public void endElement(String uri, String localName, String qName) throws SAXException {
+    	if (qName.equals("component") && currentGUIElementHash != null) {
+    		try {
+				currentGUIElementTree.add(currentGUIElementHash, currentParentHash,
+				        currentGUIElementSpec);
+			} catch (GUIModelException e) {
+				throw new SAXException("could not handle GUI element with hash " +
+                        currentGUIElementHash + ": " + e.getMessage(), e);
+			}
+    		currentGUIElementHash = null;
+            currentParentHash = null;            
+    	}
+    	// TODO else if (currentEventId != null) {
+    }
+	
+}
