Index: trunk/autoquest-plugin-jfc/src/main/java/de/ugoe/cs/autoquest/plugin/jfc/JFCSimplifiedLogParser.java
===================================================================
--- trunk/autoquest-plugin-jfc/src/main/java/de/ugoe/cs/autoquest/plugin/jfc/JFCSimplifiedLogParser.java	(revision 1027)
+++ trunk/autoquest-plugin-jfc/src/main/java/de/ugoe/cs/autoquest/plugin/jfc/JFCSimplifiedLogParser.java	(revision 1049)
@@ -1,2 +1,3 @@
+
 package de.ugoe.cs.autoquest.plugin.jfc;
 
@@ -58,4 +59,12 @@
     /**
      * <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>
@@ -81,5 +90,5 @@
      * 
      * <p>
-     * Internal handle to the hashcode of the parent of the GUI element, that is currently parsed. 
+     * Internal handle to the hashcode of the parent of the GUI element, that is currently parsed.
      * </p>
      */
@@ -129,14 +138,6 @@
     /**
      * <p>
-     * internal handle to the GUI element of the previous event to be potentially reused for the
-     * current
-     * </p>
-     */
-    private IGUIElement lastGUIElement;
-
-    /**
-     * <p>
      * internal handle to the class ancestors
-     * </p> 
+     * </p>
      */
     private List<String> currentTypeHierarchy;
@@ -165,5 +166,6 @@
         sequences = new LinkedList<List<Event>>();
         currentSequence = null;
-        //setupDefaultEventFilter();
+        eventsWithoutTargets = new HashMap<Long, List<Event>>();
+        // setupDefaultEventFilter();
     }
 
@@ -183,4 +185,5 @@
         sequences = new LinkedList<List<Event>>();
         currentSequence = null;
+        eventsWithoutTargets = new HashMap<Long, List<Event>>();
         eventFilter = ignoredEvents;
     }
@@ -223,5 +226,5 @@
             saxParser = spf.newSAXParser();
             inputSource =
-                    new InputSource(new InputStreamReader(new FileInputStream(file), "UTF-8"));
+                new InputSource(new InputStreamReader(new FileInputStream(file), "UTF-8"));
         }
         catch (UnsupportedEncodingException e) {
@@ -255,5 +258,5 @@
             catch (SAXParseException e) {
                 Console.printerrln("Failure parsing file in line " + e.getLineNumber() +
-                                   ", column " + e.getColumnNumber() + ".");
+                    ", column " + e.getColumnNumber() + ".");
                 Console.logException(e);
                 return;
@@ -270,4 +273,8 @@
             }
         }
+        if (!eventsWithoutTargets.isEmpty()) {
+            Console.printerr("Some events reference GUI elments that are not part of logfile. +"
+                + "These events have been ignored.");
+        }
     }
 
@@ -301,5 +308,6 @@
      */
     public void startElement(String uri, String localName, String qName, Attributes atts)
-            throws SAXException{
+        throws SAXException
+    {
         if (qName.equals("sessions")) {
             currentSequence = new LinkedList<Event>();
@@ -336,13 +344,14 @@
         }
         else if (qName.equals("param")) {
-            if (currentEventId != null){
-                if ("source".equals(atts.getValue("name"))){
+            if (currentEventId != null) {
+                if ("source".equals(atts.getValue("name"))) {
                     currentEventSource = Long.parseLong(atts.getValue("value"), 16);
                 }
-                if ("timestamp".equals(atts.getValue("name"))){
+                if ("timestamp".equals(atts.getValue("name"))) {
                     currentEventTimestamp = Long.parseLong(atts.getValue("value"));
                 }
                 currentEventParameters.put(atts.getValue("name"), atts.getValue("value"));
-            } else if(currentGUIElementHash != null){
+            }
+            else if (currentGUIElementHash != null) {
                 if ("title".equals(atts.getValue("name"))) {
                     currentGuiElementSpec.setName(atts.getValue("value"));
@@ -362,8 +371,8 @@
             }
         }
-        else if (qName.equals("ancestor")){
+        else if (qName.equals("ancestor")) {
             currentTypeHierarchy.add(atts.getValue("name"));
         }
-        else if (qName.equals("ancestors")){
+        else if (qName.equals("ancestors")) {
             currentTypeHierarchy = new LinkedList<String>();
         }
@@ -384,10 +393,21 @@
             currentSequence = null;
         }
-        else if (qName.equals("ancestors")){
+        else if (qName.equals("ancestors")) {
             currentGuiElementSpec.setTypeHierarchy(currentTypeHierarchy);
         }
         else if (qName.equals("component") && currentGUIElementHash != null) {
-            currentGUIElementTree.add(currentGUIElementHash, currentParentHash, currentGuiElementSpec);
-
+            currentGUIElementTree.add(currentGUIElementHash, currentParentHash,
+                                      currentGuiElementSpec);
+            List<Event> unhandledEvents = eventsWithoutTargets.get(currentGUIElementHash);
+            if (unhandledEvents != null) {
+                JFCGUIElement guiElement =
+                    (JFCGUIElement) currentGUIElementTree.find(currentGUIElementHash);
+                for (Event event : unhandledEvents) {
+                    event.setTarget(guiElement);
+                    guiElement.markAsUsed();
+                    currentSequence.add(event);
+                }
+                eventsWithoutTargets.remove(currentGUIElementHash);
+            }
             currentGUIElementHash = null;
             currentParentHash = null;
@@ -400,22 +420,32 @@
                 currentGUIElement = currentGUIElementTree.find(currentEventSource);
 
-                Event event = new Event
-                        (instantiateInteraction(currentEventId, currentEventParameters),
-                         (currentGUIElement == null ? lastGUIElement : currentGUIElement));
-                event.setTimestamp(currentEventTimestamp);
-                JFCGUIElement currentEventTarget = (JFCGUIElement) event.getTarget();
-                currentEventTarget.markAsUsed();
-
-                currentSequence.add(event);
+                // in some rare cases the target GUI element of the event is not
+                // known yet
+                if (currentGUIElement == null) {
+                    Event event =
+                        new Event(instantiateInteraction(currentEventId, currentEventParameters));
+                    event.setTimestamp(currentEventTimestamp);
+
+                    List<Event> eventList = eventsWithoutTargets.get(currentEventSource);
+                    if (eventList == null) {
+                        eventList = new ArrayList<Event>();
+                        eventsWithoutTargets.put(currentEventSource, eventList);
+                    }
+                    eventList.add(event);
+                }
+                else {
+                    Event event =
+                        new Event(instantiateInteraction(currentEventId, currentEventParameters),
+                                  currentGUIElement);
+                    event.setTimestamp(currentEventTimestamp);
+                    JFCGUIElement currentEventTarget = (JFCGUIElement) event.getTarget();
+                    currentEventTarget.markAsUsed();
+
+                    currentSequence.add(event);
+                }
 
                 currentEventParameters = null;
                 currentEventId = null;
                 currentEventTimestamp = -1l;
-
-                if (currentGUIElement != null) {
-                    lastGUIElement = currentGUIElement;
-                }
-
-                currentGUIElement = null;
             }
         }
@@ -427,18 +457,19 @@
      * interaction, that took place, i.e. the event type
      * </p>
-     *
+     * 
      * @param eventId
      *            the id of the event
      * @param eventParameters
      *            the parameters provided for the event
-     *            
+     * 
      * @return as described
      * 
-     * @throws SAXException thrown if the provided event id is unknown
-     */
-    private IInteraction instantiateInteraction(JFCEventId          eventId,
+     * @throws SAXException
+     *             thrown if the provided event id is unknown
+     */
+    private IInteraction instantiateInteraction(JFCEventId eventId,
                                                 Map<String, String> eventParameters)
-                                                        throws SAXException
-                                                        {
+        throws SAXException
+    {
         switch (eventId)
         {
@@ -464,5 +495,5 @@
                 throw new SAXException("unhandled event id " + eventId);
         }
-                                                        }
+    }
 
     /**
@@ -471,87 +502,79 @@
      * which mouse button is pressed, released or clicked.
      * </p>
-     *
+     * 
      * @param eventId
      *            the id of the event
      * @param eventParameters
      *            the parameters provided for the event
-     *            
+     * 
      * @return as described
      * 
-     * @throws SAXException thrown if the provided event id or button index is unknown
+     * @throws SAXException
+     *             thrown if the provided event id or button index is unknown
      */
     private IInteraction handleMouseAction(JFCEventId eventId, Map<String, String> eventParameters)
-            throws SAXException
-            {
+        throws SAXException
+    {
         MouseButtonInteraction.Button button = null;
 
-        if (eventParameters.get("Button") != null)
-        {
+        if (eventParameters.get("Button") != null) {
             int buttonId = Integer.parseInt(eventParameters.get("Button"));
-            if (buttonId == MouseEvent.BUTTON1)
-            {
+            if (buttonId == MouseEvent.BUTTON1) {
                 button = MouseButtonInteraction.Button.LEFT;
             }
-            else if (buttonId == MouseEvent.BUTTON2)
-            {
+            else if (buttonId == MouseEvent.BUTTON2) {
                 button = MouseButtonInteraction.Button.MIDDLE;
             }
-            else if (buttonId == MouseEvent.BUTTON3)
-            {
+            else if (buttonId == MouseEvent.BUTTON3) {
                 button = MouseButtonInteraction.Button.RIGHT;
             }
-            else
-            {
+            else {
                 throw new SAXException("unknown mouse button index " + buttonId);
             }
         }
 
-        if (JFCEventId.MOUSE_CLICKED == eventId)
-        {
+        if (JFCEventId.MOUSE_CLICKED == eventId) {
             int x = Integer.parseInt(eventParameters.get("X"));
             int y = Integer.parseInt(eventParameters.get("Y"));
             return new MouseClick(button, x, y);
         }
-        else if (JFCEventId.MOUSE_PRESSED == eventId)
-        {
+        else if (JFCEventId.MOUSE_PRESSED == eventId) {
             int x = Integer.parseInt(eventParameters.get("X"));
             int y = Integer.parseInt(eventParameters.get("Y"));
             return new MouseButtonDown(button, x, y);
         }
-        else if (JFCEventId.MOUSE_RELEASED == eventId)
-        {
+        else if (JFCEventId.MOUSE_RELEASED == eventId) {
             int x = Integer.parseInt(eventParameters.get("X"));
             int y = Integer.parseInt(eventParameters.get("Y"));
             return new MouseButtonUp(button, x, y);
         }
-        else
-        {
+        else {
             throw new SAXException("unknown event id " + eventId);
         }
-            }
+    }
 
     /**
      * <p>
      * handles a keyboard interaction. The method determines based on the event id and the
-     * parameters which key on the keyboard is pressed or released. It further checks, if for 
-     * every released key there is also a pressed event
-     * </p>
-     *
+     * parameters which key on the keyboard is pressed or released. It further checks, if for every
+     * released key there is also a pressed event
+     * </p>
+     * 
      * @param eventId
      *            the id of the event
      * @param eventParameters
      *            the parameters provided for the event
-     *            
+     * 
      * @return as described
      * 
-     * @throws SAXException thrown if the provided event id is unknown or if there is a key
-     *                      release without a preceding press of the same key
+     * @throws SAXException
+     *             thrown if the provided event id is unknown or if there is a key release without a
+     *             preceding press of the same key
      */
     private IInteraction handleKeyAction(JFCEventId eventId, Map<String, String> eventParameters)
-            throws SAXException
-            {
+        throws SAXException
+    {
         // TODO handle shortcuts
-        if (JFCEventId.KEY_PRESSED == eventId)
-        {
+        if (JFCEventId.KEY_PRESSED == eventId) {
             VirtualKey key = VirtualKey.parseVirtualKey(eventParameters.get("KeyCode"));
             mPressedKeys.add(key);
@@ -559,15 +582,13 @@
             return new KeyPressed(key);
         }
-        else if (JFCEventId.KEY_RELEASED == eventId)
-        {
+        else if (JFCEventId.KEY_RELEASED == eventId) {
             VirtualKey key = VirtualKey.parseVirtualKey(eventParameters.get("KeyCode"));
-            if (mPressedKeys.contains(key))
-            {
+            if (mPressedKeys.contains(key)) {
                 mPressedKeys.remove(key);
             }
-            else
-            {
-                Console.traceln(Level.SEVERE, "log file has an error, as it contains a key up event on key " +
-                        key + " for which there is no preceeding key down event");
+            else {
+                Console.traceln(Level.SEVERE,
+                                "log file has an error, as it contains a key up event on key " +
+                                    key + " for which there is no preceeding key down event");
             }
 
@@ -576,5 +597,5 @@
 
         throw new SAXException("unknown event id " + eventId);
-            }
+    }
 
     /**
@@ -582,26 +603,25 @@
      * handles explicit keyboard focus changes.
      * </p>
-     *
+     * 
      * @param eventId
      *            the id of the event
      * @param eventParameters
      *            the parameters provided for the event
-     *            
+     * 
      * @return as described
      * 
-     * @throws SAXException thrown if the provided event id is unknown
+     * @throws SAXException
+     *             thrown if the provided event id is unknown
      */
     private IInteraction handleNewFocus(JFCEventId eventId, Map<String, String> eventParameters)
-            throws SAXException
-            {
-        if (JFCEventId.FOCUS_GAINED == eventId)
-        {
+        throws SAXException
+    {
+        if (JFCEventId.FOCUS_GAINED == eventId) {
             return new KeyboardFocusChange();
         }
-        else
-        {
+        else {
             throw new SAXException("unknown event id " + eventId);
         }
-            }
+    }
 
     /**
@@ -611,9 +631,8 @@
      * </p>
      */
-    /*private void setupDefaultEventFilter() {
-        eventFilter = new HashSet<JFCEventId>();
-        eventFilter.add(JFCEventId.MOUSE_PRESSED);
-        eventFilter.add(JFCEventId.MOUSE_RELEASED);
-        eventFilter.add(JFCEventId.FOCUS_GAINED);
-    }*/
+    /*
+     * private void setupDefaultEventFilter() { eventFilter = new HashSet<JFCEventId>();
+     * eventFilter.add(JFCEventId.MOUSE_PRESSED); eventFilter.add(JFCEventId.MOUSE_RELEASED);
+     * eventFilter.add(JFCEventId.FOCUS_GAINED); }
+     */
 }
